diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-14 07:13:22 +0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-15 23:25:07 +0400 |
commit | 0c0d06cac63ee327ceaab4b5ffe2206574ab86bd (patch) | |
tree | e759f0dc3185d97f2a0c6b5cd5e32ea6faa74d40 /drivers/media/video | |
parent | 84cfe9e79bd5ac11c963f4841158454fefa872f6 (diff) | |
download | linux-0c0d06cac63ee327ceaab4b5ffe2206574ab86bd.tar.xz |
[media] rename most media/video usb drivers to media/usb
Rename all USB drivers with their own directory under
drivers/media/video into drivers/media/usb and update the
building system.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
285 files changed, 0 insertions, 184642 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 068e8daa6b7b..097b17ced172 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -616,16 +616,6 @@ menuconfig V4L_USB_DRIVERS if V4L_USB_DRIVERS && MEDIA_CAMERA_SUPPORT - comment "Webcam devices" - -source "drivers/media/video/uvc/Kconfig" - -source "drivers/media/video/gspca/Kconfig" - -source "drivers/media/video/pwc/Kconfig" - -source "drivers/media/video/cpia2/Kconfig" - config USB_ZR364XX tristate "USB ZR364XX Camera support" depends on VIDEO_V4L2 @@ -662,40 +652,9 @@ config USB_S2255 Say Y here if you want support for the Sensoray 2255 USB device. This driver can be compiled as a module, called s2255drv. -source "drivers/media/video/sn9c102/Kconfig" endif # V4L_USB_DRIVERS && MEDIA_CAMERA_SUPPORT -if V4L_USB_DRIVERS - - comment "Webcam and/or TV USB devices" - -source "drivers/media/video/em28xx/Kconfig" - -endif - -if V4L_USB_DRIVERS && MEDIA_ANALOG_TV_SUPPORT - - comment "TV USB devices" - -source "drivers/media/video/au0828/Kconfig" - -source "drivers/media/video/pvrusb2/Kconfig" - -source "drivers/media/video/hdpvr/Kconfig" - -source "drivers/media/video/tlg2300/Kconfig" - -source "drivers/media/video/cx231xx/Kconfig" - -source "drivers/media/video/tm6000/Kconfig" - -source "drivers/media/video/usbvision/Kconfig" - -source "drivers/media/video/stk1160/Kconfig" - -endif # V4L_USB_DRIVERS - # # PCI drivers configuration - No devices here are for webcams # diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 9dff3e2ec613..a22a2580ce30 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -99,20 +99,12 @@ obj-$(CONFIG_VIDEO_VINO) += vino.o obj-$(CONFIG_VIDEO_MEYE) += meye.o obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ obj-$(CONFIG_VIDEO_CX88) += cx88/ -obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ -obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/ -obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/ obj-$(CONFIG_VIDEO_CX25821) += cx25821/ -obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ -obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ -obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ -obj-$(CONFIG_VIDEO_TM6000) += tm6000/ obj-$(CONFIG_VIDEO_MXB) += mxb.o obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o obj-$(CONFIG_STA2X11_VIP) += sta2x11_vip.o obj-$(CONFIG_VIDEO_TIMBERDALE) += timblogiw.o -obj-$(CONFIG_VIDEO_STK1160) += stk1160/ obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o @@ -130,11 +122,6 @@ obj-$(CONFIG_VIDEO_OMAP3) += omap3isp/ obj-$(CONFIG_USB_ZR364XX) += zr364xx.o obj-$(CONFIG_USB_STKWEBCAM) += stkwebcam.o -obj-$(CONFIG_USB_SN9C102) += sn9c102/ -obj-$(CONFIG_USB_PWC) += pwc/ -obj-$(CONFIG_USB_GSPCA) += gspca/ - -obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/ obj-$(CONFIG_USB_S2255) += s2255drv.o @@ -179,9 +166,6 @@ obj-$(CONFIG_ARCH_DAVINCI) += davinci/ obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o -obj-$(CONFIG_VIDEO_AU0828) += au0828/ - -obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/ obj-$(CONFIG_VIDEO_SAA7164) += saa7164/ obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig deleted file mode 100644 index 23f7fd22f0eb..000000000000 --- a/drivers/media/video/au0828/Kconfig +++ /dev/null @@ -1,18 +0,0 @@ - -config VIDEO_AU0828 - tristate "Auvitek AU0828 support" - depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2 - depends on DVB_CAPTURE_DRIVERS - select I2C_ALGOBIT - select VIDEO_TVEEPROM - select VIDEOBUF_VMALLOC - select DVB_AU8522_DTV if !DVB_FE_CUSTOMISE - select DVB_AU8522_V4L if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE - ---help--- - This is a video4linux driver for Auvitek's USB device. - - To compile this driver as a module, choose M here: the - module will be called au0828 diff --git a/drivers/media/video/au0828/Makefile b/drivers/media/video/au0828/Makefile deleted file mode 100644 index 98cc20cc0ffb..000000000000 --- a/drivers/media/video/au0828/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o au0828-video.o au0828-vbi.o - -obj-$(CONFIG_VIDEO_AU0828) += au0828.o - -ccflags-y += -Idrivers/media/tuners -ccflags-y += -Idrivers/media/dvb-core -ccflags-y += -Idrivers/media/dvb-frontends - -ccflags-y += $(extra-cflags-y) $(extra-cflags-m) diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c deleted file mode 100644 index 448361c6a13e..000000000000 --- a/drivers/media/video/au0828/au0828-cards.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Driver for the Auvitek USB bridge - * - * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> - * - * 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 "au0828.h" -#include "au0828-cards.h" -#include "au8522.h" -#include "media/tuner.h" -#include "media/v4l2-common.h" - -void hvr950q_cs5340_audio(void *priv, int enable) -{ - /* Because the HVR-950q shares an i2s bus between the cs5340 and the - au8522, we need to hold cs5340 in reset when using the au8522 */ - struct au0828_dev *dev = priv; - if (enable == 1) - au0828_set(dev, REG_000, 0x10); - else - au0828_clear(dev, REG_000, 0x10); -} - -struct au0828_board au0828_boards[] = { - [AU0828_BOARD_UNKNOWN] = { - .name = "Unknown board", - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - }, - [AU0828_BOARD_HAUPPAUGE_HVR850] = { - .name = "Hauppauge HVR850", - .tuner_type = TUNER_XC5000, - .tuner_addr = 0x61, - .i2c_clk_divider = AU0828_I2C_CLK_20KHZ, - .input = { - { - .type = AU0828_VMUX_TELEVISION, - .vmux = AU8522_COMPOSITE_CH4_SIF, - .amux = AU8522_AUDIO_SIF, - }, - { - .type = AU0828_VMUX_COMPOSITE, - .vmux = AU8522_COMPOSITE_CH1, - .amux = AU8522_AUDIO_NONE, - .audio_setup = hvr950q_cs5340_audio, - }, - { - .type = AU0828_VMUX_SVIDEO, - .vmux = AU8522_SVIDEO_CH13, - .amux = AU8522_AUDIO_NONE, - .audio_setup = hvr950q_cs5340_audio, - }, - }, - }, - [AU0828_BOARD_HAUPPAUGE_HVR950Q] = { - .name = "Hauppauge HVR950Q", - .tuner_type = TUNER_XC5000, - .tuner_addr = 0x61, - /* The au0828 hardware i2c implementation does not properly - support the xc5000's i2c clock stretching. So we need to - lower the clock frequency enough where the 15us clock - stretch fits inside of a normal clock cycle, or else the - au0828 fails to set the STOP bit. A 30 KHz clock puts the - clock pulse width at 18us */ - .i2c_clk_divider = AU0828_I2C_CLK_20KHZ, - .input = { - { - .type = AU0828_VMUX_TELEVISION, - .vmux = AU8522_COMPOSITE_CH4_SIF, - .amux = AU8522_AUDIO_SIF, - }, - { - .type = AU0828_VMUX_COMPOSITE, - .vmux = AU8522_COMPOSITE_CH1, - .amux = AU8522_AUDIO_NONE, - .audio_setup = hvr950q_cs5340_audio, - }, - { - .type = AU0828_VMUX_SVIDEO, - .vmux = AU8522_SVIDEO_CH13, - .amux = AU8522_AUDIO_NONE, - .audio_setup = hvr950q_cs5340_audio, - }, - }, - }, - [AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = { - .name = "Hauppauge HVR950Q rev xxF8", - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, - }, - [AU0828_BOARD_DVICO_FUSIONHDTV7] = { - .name = "DViCO FusionHDTV USB", - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, - }, - [AU0828_BOARD_HAUPPAUGE_WOODBURY] = { - .name = "Hauppauge Woodbury", - .tuner_type = UNSET, - .tuner_addr = ADDR_UNSET, - .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, - }, -}; - -/* Tuner callback function for au0828 boards. Currently only needed - * for HVR1500Q, which has an xc5000 tuner. - */ -int au0828_tuner_callback(void *priv, int component, int command, int arg) -{ - struct au0828_dev *dev = priv; - - dprintk(1, "%s()\n", __func__); - - switch (dev->boardnr) { - case AU0828_BOARD_HAUPPAUGE_HVR850: - case AU0828_BOARD_HAUPPAUGE_HVR950Q: - case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: - case AU0828_BOARD_DVICO_FUSIONHDTV7: - if (command == 0) { - /* Tuner Reset Command from xc5000 */ - /* Drive the tuner into reset and out */ - au0828_clear(dev, REG_001, 2); - mdelay(10); - au0828_set(dev, REG_001, 2); - mdelay(10); - return 0; - } else { - printk(KERN_ERR - "%s(): Unknown command.\n", __func__); - return -EINVAL; - } - break; - } - - return 0; /* Should never be here */ -} - -static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) -{ - struct tveeprom tv; - - tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data); - dev->board.tuner_type = tv.tuner_type; - - /* Make sure we support the board model */ - switch (tv.model) { - case 72000: /* WinTV-HVR950q (Retail, IR, ATSC/QAM */ - case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */ - case 72101: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */ - case 72201: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ - case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ - case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ - case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ - case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */ - case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */ - case 72261: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */ - case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and analog video */ - case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */ - break; - default: - printk(KERN_WARNING "%s: warning: " - "unknown hauppauge model #%d\n", __func__, tv.model); - break; - } - - printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n", - __func__, tv.model); -} - -void au0828_card_setup(struct au0828_dev *dev) -{ - static u8 eeprom[256]; - struct tuner_setup tun_setup; - struct v4l2_subdev *sd; - unsigned int mode_mask = T_ANALOG_TV; - - dprintk(1, "%s()\n", __func__); - - memcpy(&dev->board, &au0828_boards[dev->boardnr], sizeof(dev->board)); - - if (dev->i2c_rc == 0) { - dev->i2c_client.addr = 0xa0 >> 1; - tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom)); - } - - switch (dev->boardnr) { - case AU0828_BOARD_HAUPPAUGE_HVR850: - case AU0828_BOARD_HAUPPAUGE_HVR950Q: - case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: - case AU0828_BOARD_HAUPPAUGE_WOODBURY: - if (dev->i2c_rc == 0) - hauppauge_eeprom(dev, eeprom+0xa0); - break; - } - - if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) { - /* Load the analog demodulator driver (note this would need to - be abstracted out if we ever need to support a different - demod) */ - sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "au8522", 0x8e >> 1, NULL); - if (sd == NULL) - printk(KERN_ERR "analog subdev registration failed\n"); - } - - /* Setup tuners */ - if (dev->board.tuner_type != TUNER_ABSENT) { - /* Load the tuner module, which does the attach */ - sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tuner", dev->board.tuner_addr, NULL); - if (sd == NULL) - printk(KERN_ERR "tuner subdev registration fail\n"); - - tun_setup.mode_mask = mode_mask; - tun_setup.type = dev->board.tuner_type; - tun_setup.addr = dev->board.tuner_addr; - tun_setup.tuner_callback = au0828_tuner_callback; - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, - &tun_setup); - } -} - -/* - * The bridge has between 8 and 12 gpios. - * Regs 1 and 0 deal with output enables. - * Regs 3 and 2 deal with direction. - */ -void au0828_gpio_setup(struct au0828_dev *dev) -{ - dprintk(1, "%s()\n", __func__); - - switch (dev->boardnr) { - case AU0828_BOARD_HAUPPAUGE_HVR850: - case AU0828_BOARD_HAUPPAUGE_HVR950Q: - case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: - case AU0828_BOARD_HAUPPAUGE_WOODBURY: - /* GPIO's - * 4 - CS5340 - * 5 - AU8522 Demodulator - * 6 - eeprom W/P - * 7 - power supply - * 9 - XC5000 Tuner - */ - - /* Into reset */ - au0828_write(dev, REG_003, 0x02); - au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10); - au0828_write(dev, REG_001, 0x0); - au0828_write(dev, REG_000, 0x0); - msleep(100); - - /* Out of reset (leave the cs5340 in reset until needed) */ - au0828_write(dev, REG_003, 0x02); - au0828_write(dev, REG_001, 0x02); - au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10); - au0828_write(dev, REG_000, 0x80 | 0x40 | 0x20); - - msleep(250); - break; - case AU0828_BOARD_DVICO_FUSIONHDTV7: - /* GPIO's - * 6 - ? - * 8 - AU8522 Demodulator - * 9 - XC5000 Tuner - */ - - /* Into reset */ - au0828_write(dev, REG_003, 0x02); - au0828_write(dev, REG_002, 0xa0); - au0828_write(dev, REG_001, 0x0); - au0828_write(dev, REG_000, 0x0); - msleep(100); - - /* Out of reset */ - au0828_write(dev, REG_003, 0x02); - au0828_write(dev, REG_002, 0xa0); - au0828_write(dev, REG_001, 0x02); - au0828_write(dev, REG_000, 0xa0); - msleep(250); - break; - } -} - -/* table of devices that work with this driver */ -struct usb_device_id au0828_usb_id_table[] = { - { USB_DEVICE(0x2040, 0x7200), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x2040, 0x7240), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 }, - { USB_DEVICE(0x0fe9, 0xd620), - .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 }, - { USB_DEVICE(0x2040, 0x7210), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x2040, 0x7217), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x2040, 0x721b), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x2040, 0x721e), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x2040, 0x721f), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x2040, 0x7280), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x0fd9, 0x0008), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x2040, 0x7201), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL }, - { USB_DEVICE(0x2040, 0x7211), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL }, - { USB_DEVICE(0x2040, 0x7281), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL }, - { USB_DEVICE(0x05e1, 0x0480), - .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY }, - { USB_DEVICE(0x2040, 0x8200), - .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY }, - { USB_DEVICE(0x2040, 0x7260), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { USB_DEVICE(0x2040, 0x7213), - .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, - { }, -}; - -MODULE_DEVICE_TABLE(usb, au0828_usb_id_table); diff --git a/drivers/media/video/au0828/au0828-cards.h b/drivers/media/video/au0828/au0828-cards.h deleted file mode 100644 index 48a1882c2b6b..000000000000 --- a/drivers/media/video/au0828/au0828-cards.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Driver for the Auvitek USB bridge - * - * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> - * - * 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. - */ - -#define AU0828_BOARD_UNKNOWN 0 -#define AU0828_BOARD_HAUPPAUGE_HVR950Q 1 -#define AU0828_BOARD_HAUPPAUGE_HVR850 2 -#define AU0828_BOARD_DVICO_FUSIONHDTV7 3 -#define AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL 4 -#define AU0828_BOARD_HAUPPAUGE_WOODBURY 5 diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c deleted file mode 100644 index 745a80a798c8..000000000000 --- a/drivers/media/video/au0828/au0828-core.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Driver for the Auvitek USB bridge - * - * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> - * - * 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 <linux/module.h> -#include <linux/slab.h> -#include <linux/videodev2.h> -#include <media/v4l2-common.h> -#include <linux/mutex.h> - -#include "au0828.h" - -/* - * 1 = General debug messages - * 2 = USB handling - * 4 = I2C related - * 8 = Bridge related - */ -int au0828_debug; -module_param_named(debug, au0828_debug, int, 0644); -MODULE_PARM_DESC(debug, "enable debug messages"); - -static unsigned int disable_usb_speed_check; -module_param(disable_usb_speed_check, int, 0444); -MODULE_PARM_DESC(disable_usb_speed_check, - "override min bandwidth requirement of 480M bps"); - -#define _AU0828_BULKPIPE 0x03 -#define _BULKPIPESIZE 0xffff - -static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, - u16 index); -static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, - u16 index, unsigned char *cp, u16 size); - -/* USB Direction */ -#define CMD_REQUEST_IN 0x00 -#define CMD_REQUEST_OUT 0x01 - -u32 au0828_readreg(struct au0828_dev *dev, u16 reg) -{ - u8 result = 0; - - recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, &result, 1); - dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, result); - - return result; -} - -u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val) -{ - dprintk(8, "%s(0x%04x, 0x%02x)\n", __func__, reg, val); - return send_control_msg(dev, CMD_REQUEST_OUT, val, reg); -} - -static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value, - u16 index) -{ - int status = -ENODEV; - - if (dev->usbdev) { - - /* cp must be memory that has been allocated by kmalloc */ - status = usb_control_msg(dev->usbdev, - usb_sndctrlpipe(dev->usbdev, 0), - request, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, - value, index, NULL, 0, 1000); - - status = min(status, 0); - - if (status < 0) { - printk(KERN_ERR "%s() Failed sending control message, error %d.\n", - __func__, status); - } - - } - - return status; -} - -static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value, - u16 index, unsigned char *cp, u16 size) -{ - int status = -ENODEV; - mutex_lock(&dev->mutex); - if (dev->usbdev) { - status = usb_control_msg(dev->usbdev, - usb_rcvctrlpipe(dev->usbdev, 0), - request, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, - dev->ctrlmsg, size, 1000); - - status = min(status, 0); - - if (status < 0) { - printk(KERN_ERR "%s() Failed receiving control message, error %d.\n", - __func__, status); - } - - /* the host controller requires heap allocated memory, which - is why we didn't just pass "cp" into usb_control_msg */ - memcpy(cp, dev->ctrlmsg, size); - } - mutex_unlock(&dev->mutex); - return status; -} - -static void au0828_usb_disconnect(struct usb_interface *interface) -{ - struct au0828_dev *dev = usb_get_intfdata(interface); - - dprintk(1, "%s()\n", __func__); - - /* Digital TV */ - au0828_dvb_unregister(dev); - - if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) - au0828_analog_unregister(dev); - - /* I2C */ - au0828_i2c_unregister(dev); - - v4l2_device_unregister(&dev->v4l2_dev); - - usb_set_intfdata(interface, NULL); - - mutex_lock(&dev->mutex); - dev->usbdev = NULL; - mutex_unlock(&dev->mutex); - - kfree(dev); - -} - -static int au0828_usb_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - int ifnum, retval; - struct au0828_dev *dev; - struct usb_device *usbdev = interface_to_usbdev(interface); - - ifnum = interface->altsetting->desc.bInterfaceNumber; - - if (ifnum != 0) - return -ENODEV; - - dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__, - le16_to_cpu(usbdev->descriptor.idVendor), - le16_to_cpu(usbdev->descriptor.idProduct), - ifnum); - - /* - * Make sure we have 480 Mbps of bandwidth, otherwise things like - * video stream wouldn't likely work, since 12 Mbps is generally - * not enough even for most Digital TV streams. - */ - if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) { - printk(KERN_ERR "au0828: Device initialization failed.\n"); - printk(KERN_ERR "au0828: Device must be connected to a " - "high-speed USB 2.0 port.\n"); - return -ENODEV; - } - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - printk(KERN_ERR "%s() Unable to allocate memory\n", __func__); - return -ENOMEM; - } - - mutex_init(&dev->lock); - mutex_lock(&dev->lock); - mutex_init(&dev->mutex); - mutex_init(&dev->dvb.lock); - dev->usbdev = usbdev; - dev->boardnr = id->driver_info; - - /* Create the v4l2_device */ - retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); - if (retval) { - printk(KERN_ERR "%s() v4l2_device_register failed\n", - __func__); - mutex_unlock(&dev->lock); - kfree(dev); - return -EIO; - } - - /* Power Up the bridge */ - au0828_write(dev, REG_600, 1 << 4); - - /* Bring up the GPIO's and supporting devices */ - au0828_gpio_setup(dev); - - /* I2C */ - au0828_i2c_register(dev); - - /* Setup */ - au0828_card_setup(dev); - - /* Analog TV */ - if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) - au0828_analog_register(dev, interface); - - /* Digital TV */ - au0828_dvb_register(dev); - - /* Store the pointer to the au0828_dev so it can be accessed in - au0828_usb_disconnect */ - usb_set_intfdata(interface, dev); - - printk(KERN_INFO "Registered device AU0828 [%s]\n", - dev->board.name == NULL ? "Unset" : dev->board.name); - - mutex_unlock(&dev->lock); - - return 0; -} - -static struct usb_driver au0828_usb_driver = { - .name = DRIVER_NAME, - .probe = au0828_usb_probe, - .disconnect = au0828_usb_disconnect, - .id_table = au0828_usb_id_table, -}; - -static int __init au0828_init(void) -{ - int ret; - - if (au0828_debug & 1) - printk(KERN_INFO "%s() Debugging is enabled\n", __func__); - - if (au0828_debug & 2) - printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__); - - if (au0828_debug & 4) - printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__); - - if (au0828_debug & 8) - printk(KERN_INFO "%s() Bridge Debugging is enabled\n", - __func__); - - printk(KERN_INFO "au0828 driver loaded\n"); - - ret = usb_register(&au0828_usb_driver); - if (ret) - printk(KERN_ERR "usb_register failed, error = %d\n", ret); - - return ret; -} - -static void __exit au0828_exit(void) -{ - usb_deregister(&au0828_usb_driver); -} - -module_init(au0828_init); -module_exit(au0828_exit); - -MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products"); -MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); -MODULE_LICENSE("GPL"); -MODULE_VERSION("0.0.2"); diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c deleted file mode 100644 index b328f6550d0b..000000000000 --- a/drivers/media/video/au0828/au0828-dvb.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * Driver for the Auvitek USB bridge - * - * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> - * - * 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 <linux/module.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/suspend.h> -#include <media/v4l2-common.h> -#include <media/tuner.h> - -#include "au0828.h" -#include "au8522.h" -#include "xc5000.h" -#include "mxl5007t.h" -#include "tda18271.h" - -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - -#define _AU0828_BULKPIPE 0x83 -#define _BULKPIPESIZE 0xe522 - -static u8 hauppauge_hvr950q_led_states[] = { - 0x00, /* off */ - 0x02, /* yellow */ - 0x04, /* green */ -}; - -static struct au8522_led_config hauppauge_hvr950q_led_cfg = { - .gpio_output = 0x00e0, - .gpio_output_enable = 0x6006, - .gpio_output_disable = 0x0660, - - .gpio_leds = 0x00e2, - .led_states = hauppauge_hvr950q_led_states, - .num_led_states = sizeof(hauppauge_hvr950q_led_states), - - .vsb8_strong = 20 /* dB */ * 10, - .qam64_strong = 25 /* dB */ * 10, - .qam256_strong = 32 /* dB */ * 10, -}; - -static struct au8522_config hauppauge_hvr950q_config = { - .demod_address = 0x8e >> 1, - .status_mode = AU8522_DEMODLOCKING, - .qam_if = AU8522_IF_6MHZ, - .vsb_if = AU8522_IF_6MHZ, - .led_cfg = &hauppauge_hvr950q_led_cfg, -}; - -static struct au8522_config fusionhdtv7usb_config = { - .demod_address = 0x8e >> 1, - .status_mode = AU8522_DEMODLOCKING, - .qam_if = AU8522_IF_6MHZ, - .vsb_if = AU8522_IF_6MHZ, -}; - -static struct au8522_config hauppauge_woodbury_config = { - .demod_address = 0x8e >> 1, - .status_mode = AU8522_DEMODLOCKING, - .qam_if = AU8522_IF_4MHZ, - .vsb_if = AU8522_IF_3_25MHZ, -}; - -static struct xc5000_config hauppauge_xc5000a_config = { - .i2c_address = 0x61, - .if_khz = 6000, - .chip_id = XC5000A, -}; - -static struct xc5000_config hauppauge_xc5000c_config = { - .i2c_address = 0x61, - .if_khz = 6000, - .chip_id = XC5000C, -}; - -static struct mxl5007t_config mxl5007t_hvr950q_config = { - .xtal_freq_hz = MxL_XTAL_24_MHZ, - .if_freq_hz = MxL_IF_6_MHZ, -}; - -static struct tda18271_config hauppauge_woodbury_tunerconfig = { - .gate = TDA18271_GATE_DIGITAL, -}; - -static void au0828_restart_dvb_streaming(struct work_struct *work); - -/*-------------------------------------------------------------------*/ -static void urb_completion(struct urb *purb) -{ - struct au0828_dev *dev = purb->context; - int ptype = usb_pipetype(purb->pipe); - unsigned char *ptr; - - dprintk(2, "%s()\n", __func__); - - if (!dev) - return; - - if (dev->urb_streaming == 0) - return; - - if (ptype != PIPE_BULK) { - printk(KERN_ERR "%s() Unsupported URB type %d\n", - __func__, ptype); - return; - } - - /* See if the stream is corrupted (to work around a hardware - bug where the stream gets misaligned */ - ptr = purb->transfer_buffer; - if (purb->actual_length > 0 && ptr[0] != 0x47) { - dprintk(1, "Need to restart streaming %02x len=%d!\n", - ptr[0], purb->actual_length); - schedule_work(&dev->restart_streaming); - return; - } - - /* Feed the transport payload into the kernel demux */ - dvb_dmx_swfilter_packets(&dev->dvb.demux, - purb->transfer_buffer, purb->actual_length / 188); - - /* Clean the buffer before we requeue */ - memset(purb->transfer_buffer, 0, URB_BUFSIZE); - - /* Requeue URB */ - usb_submit_urb(purb, GFP_ATOMIC); -} - -static int stop_urb_transfer(struct au0828_dev *dev) -{ - int i; - - dprintk(2, "%s()\n", __func__); - - dev->urb_streaming = 0; - for (i = 0; i < URB_COUNT; i++) { - usb_kill_urb(dev->urbs[i]); - kfree(dev->urbs[i]->transfer_buffer); - usb_free_urb(dev->urbs[i]); - } - - return 0; -} - -static int start_urb_transfer(struct au0828_dev *dev) -{ - struct urb *purb; - int i, ret = -ENOMEM; - - dprintk(2, "%s()\n", __func__); - - if (dev->urb_streaming) { - dprintk(2, "%s: bulk xfer already running!\n", __func__); - return 0; - } - - for (i = 0; i < URB_COUNT; i++) { - - dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->urbs[i]) - goto err; - - purb = dev->urbs[i]; - - purb->transfer_buffer = kzalloc(URB_BUFSIZE, GFP_KERNEL); - if (!purb->transfer_buffer) { - usb_free_urb(purb); - dev->urbs[i] = NULL; - goto err; - } - - purb->status = -EINPROGRESS; - usb_fill_bulk_urb(purb, - dev->usbdev, - usb_rcvbulkpipe(dev->usbdev, - _AU0828_BULKPIPE), - purb->transfer_buffer, - URB_BUFSIZE, - urb_completion, - dev); - - } - - for (i = 0; i < URB_COUNT; i++) { - ret = usb_submit_urb(dev->urbs[i], GFP_ATOMIC); - if (ret != 0) { - stop_urb_transfer(dev); - printk(KERN_ERR "%s: failed urb submission, " - "err = %d\n", __func__, ret); - return ret; - } - } - - dev->urb_streaming = 1; - ret = 0; - -err: - return ret; -} - -static int au0828_dvb_start_feed(struct dvb_demux_feed *feed) -{ - struct dvb_demux *demux = feed->demux; - struct au0828_dev *dev = (struct au0828_dev *) demux->priv; - struct au0828_dvb *dvb = &dev->dvb; - int ret = 0; - - dprintk(1, "%s()\n", __func__); - - if (!demux->dmx.frontend) - return -EINVAL; - - if (dvb) { - mutex_lock(&dvb->lock); - if (dvb->feeding++ == 0) { - /* Start transport */ - au0828_write(dev, 0x608, 0x90); - au0828_write(dev, 0x609, 0x72); - au0828_write(dev, 0x60a, 0x71); - au0828_write(dev, 0x60b, 0x01); - ret = start_urb_transfer(dev); - } - mutex_unlock(&dvb->lock); - } - - return ret; -} - -static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed) -{ - struct dvb_demux *demux = feed->demux; - struct au0828_dev *dev = (struct au0828_dev *) demux->priv; - struct au0828_dvb *dvb = &dev->dvb; - int ret = 0; - - dprintk(1, "%s()\n", __func__); - - if (dvb) { - mutex_lock(&dvb->lock); - if (--dvb->feeding == 0) { - /* Stop transport */ - ret = stop_urb_transfer(dev); - au0828_write(dev, 0x60b, 0x00); - } - mutex_unlock(&dvb->lock); - } - - return ret; -} - -static void au0828_restart_dvb_streaming(struct work_struct *work) -{ - struct au0828_dev *dev = container_of(work, struct au0828_dev, - restart_streaming); - struct au0828_dvb *dvb = &dev->dvb; - int ret; - - if (dev->urb_streaming == 0) - return; - - dprintk(1, "Restarting streaming...!\n"); - - mutex_lock(&dvb->lock); - - /* Stop transport */ - ret = stop_urb_transfer(dev); - au0828_write(dev, 0x608, 0x00); - au0828_write(dev, 0x609, 0x00); - au0828_write(dev, 0x60a, 0x00); - au0828_write(dev, 0x60b, 0x00); - - /* Start transport */ - au0828_write(dev, 0x608, 0x90); - au0828_write(dev, 0x609, 0x72); - au0828_write(dev, 0x60a, 0x71); - au0828_write(dev, 0x60b, 0x01); - ret = start_urb_transfer(dev); - - mutex_unlock(&dvb->lock); -} - -static int dvb_register(struct au0828_dev *dev) -{ - struct au0828_dvb *dvb = &dev->dvb; - int result; - - dprintk(1, "%s()\n", __func__); - - INIT_WORK(&dev->restart_streaming, au0828_restart_dvb_streaming); - - /* register adapter */ - result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE, - &dev->usbdev->dev, adapter_nr); - if (result < 0) { - printk(KERN_ERR "%s: dvb_register_adapter failed " - "(errno = %d)\n", DRIVER_NAME, result); - goto fail_adapter; - } - dvb->adapter.priv = dev; - - /* register frontend */ - result = dvb_register_frontend(&dvb->adapter, dvb->frontend); - if (result < 0) { - printk(KERN_ERR "%s: dvb_register_frontend failed " - "(errno = %d)\n", DRIVER_NAME, result); - goto fail_frontend; - } - - /* register demux stuff */ - dvb->demux.dmx.capabilities = - DMX_TS_FILTERING | DMX_SECTION_FILTERING | - DMX_MEMORY_BASED_FILTERING; - dvb->demux.priv = dev; - dvb->demux.filternum = 256; - dvb->demux.feednum = 256; - dvb->demux.start_feed = au0828_dvb_start_feed; - dvb->demux.stop_feed = au0828_dvb_stop_feed; - result = dvb_dmx_init(&dvb->demux); - if (result < 0) { - printk(KERN_ERR "%s: dvb_dmx_init failed (errno = %d)\n", - DRIVER_NAME, result); - goto fail_dmx; - } - - dvb->dmxdev.filternum = 256; - dvb->dmxdev.demux = &dvb->demux.dmx; - dvb->dmxdev.capabilities = 0; - result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); - if (result < 0) { - printk(KERN_ERR "%s: dvb_dmxdev_init failed (errno = %d)\n", - DRIVER_NAME, result); - goto fail_dmxdev; - } - - dvb->fe_hw.source = DMX_FRONTEND_0; - result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); - if (result < 0) { - printk(KERN_ERR "%s: add_frontend failed " - "(DMX_FRONTEND_0, errno = %d)\n", DRIVER_NAME, result); - goto fail_fe_hw; - } - - dvb->fe_mem.source = DMX_MEMORY_FE; - result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); - if (result < 0) { - printk(KERN_ERR "%s: add_frontend failed " - "(DMX_MEMORY_FE, errno = %d)\n", DRIVER_NAME, result); - goto fail_fe_mem; - } - - result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); - if (result < 0) { - printk(KERN_ERR "%s: connect_frontend failed (errno = %d)\n", - DRIVER_NAME, result); - goto fail_fe_conn; - } - - /* register network adapter */ - dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); - return 0; - -fail_fe_conn: - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); -fail_fe_mem: - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); -fail_fe_hw: - dvb_dmxdev_release(&dvb->dmxdev); -fail_dmxdev: - dvb_dmx_release(&dvb->demux); -fail_dmx: - dvb_unregister_frontend(dvb->frontend); -fail_frontend: - dvb_frontend_detach(dvb->frontend); - dvb_unregister_adapter(&dvb->adapter); -fail_adapter: - return result; -} - -void au0828_dvb_unregister(struct au0828_dev *dev) -{ - struct au0828_dvb *dvb = &dev->dvb; - - dprintk(1, "%s()\n", __func__); - - if (dvb->frontend == NULL) - return; - - dvb_net_release(&dvb->net); - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); - dvb_dmxdev_release(&dvb->dmxdev); - dvb_dmx_release(&dvb->demux); - dvb_unregister_frontend(dvb->frontend); - dvb_frontend_detach(dvb->frontend); - dvb_unregister_adapter(&dvb->adapter); -} - -/* All the DVB attach calls go here, this function get's modified - * for each new card. No other function in this file needs - * to change. - */ -int au0828_dvb_register(struct au0828_dev *dev) -{ - struct au0828_dvb *dvb = &dev->dvb; - int ret; - - dprintk(1, "%s()\n", __func__); - - /* init frontend */ - switch (dev->boardnr) { - case AU0828_BOARD_HAUPPAUGE_HVR850: - case AU0828_BOARD_HAUPPAUGE_HVR950Q: - dvb->frontend = dvb_attach(au8522_attach, - &hauppauge_hvr950q_config, - &dev->i2c_adap); - if (dvb->frontend != NULL) - switch (dev->board.tuner_type) { - default: - case TUNER_XC5000: - dvb_attach(xc5000_attach, dvb->frontend, - &dev->i2c_adap, - &hauppauge_xc5000a_config); - break; - case TUNER_XC5000C: - dvb_attach(xc5000_attach, dvb->frontend, - &dev->i2c_adap, - &hauppauge_xc5000c_config); - break; - } - break; - case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: - dvb->frontend = dvb_attach(au8522_attach, - &hauppauge_hvr950q_config, - &dev->i2c_adap); - if (dvb->frontend != NULL) - dvb_attach(mxl5007t_attach, dvb->frontend, - &dev->i2c_adap, 0x60, - &mxl5007t_hvr950q_config); - break; - case AU0828_BOARD_HAUPPAUGE_WOODBURY: - dvb->frontend = dvb_attach(au8522_attach, - &hauppauge_woodbury_config, - &dev->i2c_adap); - if (dvb->frontend != NULL) - dvb_attach(tda18271_attach, dvb->frontend, - 0x60, &dev->i2c_adap, - &hauppauge_woodbury_tunerconfig); - break; - case AU0828_BOARD_DVICO_FUSIONHDTV7: - dvb->frontend = dvb_attach(au8522_attach, - &fusionhdtv7usb_config, - &dev->i2c_adap); - if (dvb->frontend != NULL) { - dvb_attach(xc5000_attach, dvb->frontend, - &dev->i2c_adap, - &hauppauge_xc5000a_config); - } - break; - default: - printk(KERN_WARNING "The frontend of your DVB/ATSC card " - "isn't supported yet\n"); - break; - } - if (NULL == dvb->frontend) { - printk(KERN_ERR "%s() Frontend initialization failed\n", - __func__); - return -1; - } - /* define general-purpose callback pointer */ - dvb->frontend->callback = au0828_tuner_callback; - - /* register everything */ - ret = dvb_register(dev); - if (ret < 0) { - if (dvb->frontend->ops.release) - dvb->frontend->ops.release(dvb->frontend); - return ret; - } - - return 0; -} diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c deleted file mode 100644 index 4ded17fe1957..000000000000 --- a/drivers/media/video/au0828/au0828-i2c.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Driver for the Auvitek AU0828 USB bridge - * - * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> - * - * 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 <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/io.h> - -#include "au0828.h" -#include "media/tuner.h" -#include <media/v4l2-common.h> - -static int i2c_scan; -module_param(i2c_scan, int, 0444); -MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); - -#define I2C_WAIT_DELAY 25 -#define I2C_WAIT_RETRY 1000 - -static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap) -{ - struct au0828_dev *dev = i2c_adap->algo_data; - return au0828_read(dev, AU0828_I2C_STATUS_201) & - AU0828_I2C_STATUS_NO_WRITE_ACK ? 0 : 1; -} - -static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap) -{ - struct au0828_dev *dev = i2c_adap->algo_data; - return au0828_read(dev, AU0828_I2C_STATUS_201) & - AU0828_I2C_STATUS_NO_READ_ACK ? 0 : 1; -} - -static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap) -{ - int count; - - for (count = 0; count < I2C_WAIT_RETRY; count++) { - if (!i2c_slave_did_read_ack(i2c_adap)) - break; - udelay(I2C_WAIT_DELAY); - } - - if (I2C_WAIT_RETRY == count) - return 0; - - return 1; -} - -static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap) -{ - struct au0828_dev *dev = i2c_adap->algo_data; - return au0828_read(dev, AU0828_I2C_STATUS_201) & - AU0828_I2C_STATUS_READ_DONE ? 0 : 1; -} - -static int i2c_wait_read_done(struct i2c_adapter *i2c_adap) -{ - int count; - - for (count = 0; count < I2C_WAIT_RETRY; count++) { - if (!i2c_is_read_busy(i2c_adap)) - break; - udelay(I2C_WAIT_DELAY); - } - - if (I2C_WAIT_RETRY == count) - return 0; - - return 1; -} - -static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap) -{ - struct au0828_dev *dev = i2c_adap->algo_data; - return au0828_read(dev, AU0828_I2C_STATUS_201) & - AU0828_I2C_STATUS_WRITE_DONE ? 1 : 0; -} - -static int i2c_wait_write_done(struct i2c_adapter *i2c_adap) -{ - int count; - - for (count = 0; count < I2C_WAIT_RETRY; count++) { - if (i2c_is_write_done(i2c_adap)) - break; - udelay(I2C_WAIT_DELAY); - } - - if (I2C_WAIT_RETRY == count) - return 0; - - return 1; -} - -static inline int i2c_is_busy(struct i2c_adapter *i2c_adap) -{ - struct au0828_dev *dev = i2c_adap->algo_data; - return au0828_read(dev, AU0828_I2C_STATUS_201) & - AU0828_I2C_STATUS_BUSY ? 1 : 0; -} - -static int i2c_wait_done(struct i2c_adapter *i2c_adap) -{ - int count; - - for (count = 0; count < I2C_WAIT_RETRY; count++) { - if (!i2c_is_busy(i2c_adap)) - break; - udelay(I2C_WAIT_DELAY); - } - - if (I2C_WAIT_RETRY == count) - return 0; - - return 1; -} - -/* FIXME: Implement join handling correctly */ -static int i2c_sendbytes(struct i2c_adapter *i2c_adap, - const struct i2c_msg *msg, int joined_rlen) -{ - int i, strobe = 0; - struct au0828_dev *dev = i2c_adap->algo_data; - - dprintk(4, "%s()\n", __func__); - - au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); - - /* Set the I2C clock */ - if (((dev->board.tuner_type == TUNER_XC5000) || - (dev->board.tuner_type == TUNER_XC5000C)) && - (dev->board.tuner_addr == msg->addr) && - (msg->len == 64)) { - /* Hack to speed up firmware load. The xc5000 lets us do up - to 400 KHz when in firmware download mode */ - au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, - AU0828_I2C_CLK_250KHZ); - } else { - /* Use the i2c clock speed in the board configuration */ - au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, - dev->board.i2c_clk_divider); - } - - /* Hardware needs 8 bit addresses */ - au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); - - dprintk(4, "SEND: %02x\n", msg->addr); - - /* Deal with i2c_scan */ - if (msg->len == 0) { - /* The analog tuner detection code makes use of the SMBUS_QUICK - message (which involves a zero length i2c write). To avoid - checking the status register when we didn't strobe out any - actual bytes to the bus, just do a read check. This is - consistent with how I saw i2c device checking done in the - USB trace of the Windows driver */ - au0828_write(dev, AU0828_I2C_TRIGGER_200, - AU0828_I2C_TRIGGER_READ); - - if (!i2c_wait_done(i2c_adap)) - return -EIO; - - if (i2c_wait_read_ack(i2c_adap)) - return -EIO; - - return 0; - } - - for (i = 0; i < msg->len;) { - - dprintk(4, " %02x\n", msg->buf[i]); - - au0828_write(dev, AU0828_I2C_WRITE_FIFO_205, msg->buf[i]); - - strobe++; - i++; - - if ((strobe >= 4) || (i >= msg->len)) { - - /* Strobe the byte into the bus */ - if (i < msg->len) - au0828_write(dev, AU0828_I2C_TRIGGER_200, - AU0828_I2C_TRIGGER_WRITE | - AU0828_I2C_TRIGGER_HOLD); - else - au0828_write(dev, AU0828_I2C_TRIGGER_200, - AU0828_I2C_TRIGGER_WRITE); - - /* Reset strobe trigger */ - strobe = 0; - - if (!i2c_wait_write_done(i2c_adap)) - return -EIO; - - } - - } - if (!i2c_wait_done(i2c_adap)) - return -EIO; - - dprintk(4, "\n"); - - return msg->len; -} - -/* FIXME: Implement join handling correctly */ -static int i2c_readbytes(struct i2c_adapter *i2c_adap, - const struct i2c_msg *msg, int joined) -{ - struct au0828_dev *dev = i2c_adap->algo_data; - int i; - - dprintk(4, "%s()\n", __func__); - - au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); - - /* Set the I2C clock */ - au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, - dev->board.i2c_clk_divider); - - /* Hardware needs 8 bit addresses */ - au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); - - dprintk(4, " RECV:\n"); - - /* Deal with i2c_scan */ - if (msg->len == 0) { - au0828_write(dev, AU0828_I2C_TRIGGER_200, - AU0828_I2C_TRIGGER_READ); - - if (i2c_wait_read_ack(i2c_adap)) - return -EIO; - return 0; - } - - for (i = 0; i < msg->len;) { - - i++; - - if (i < msg->len) - au0828_write(dev, AU0828_I2C_TRIGGER_200, - AU0828_I2C_TRIGGER_READ | - AU0828_I2C_TRIGGER_HOLD); - else - au0828_write(dev, AU0828_I2C_TRIGGER_200, - AU0828_I2C_TRIGGER_READ); - - if (!i2c_wait_read_done(i2c_adap)) - return -EIO; - - msg->buf[i-1] = au0828_read(dev, AU0828_I2C_READ_FIFO_209) & - 0xff; - - dprintk(4, " %02x\n", msg->buf[i-1]); - } - if (!i2c_wait_done(i2c_adap)) - return -EIO; - - dprintk(4, "\n"); - - return msg->len; -} - -static int i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, int num) -{ - int i, retval = 0; - - dprintk(4, "%s(num = %d)\n", __func__, num); - - for (i = 0; i < num; i++) { - dprintk(4, "%s(num = %d) addr = 0x%02x len = 0x%x\n", - __func__, num, msgs[i].addr, msgs[i].len); - if (msgs[i].flags & I2C_M_RD) { - /* read */ - retval = i2c_readbytes(i2c_adap, &msgs[i], 0); - } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && - msgs[i].addr == msgs[i + 1].addr) { - /* write then read from same address */ - retval = i2c_sendbytes(i2c_adap, &msgs[i], - msgs[i + 1].len); - if (retval < 0) - goto err; - i++; - retval = i2c_readbytes(i2c_adap, &msgs[i], 1); - } else { - /* write */ - retval = i2c_sendbytes(i2c_adap, &msgs[i], 0); - } - if (retval < 0) - goto err; - } - return num; - -err: - return retval; -} - -static u32 au0828_functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; -} - -static struct i2c_algorithm au0828_i2c_algo_template = { - .master_xfer = i2c_xfer, - .functionality = au0828_functionality, -}; - -/* ----------------------------------------------------------------------- */ - -static struct i2c_adapter au0828_i2c_adap_template = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - .algo = &au0828_i2c_algo_template, -}; - -static struct i2c_client au0828_i2c_client_template = { - .name = "au0828 internal", -}; - -static char *i2c_devs[128] = { - [0x8e >> 1] = "au8522", - [0xa0 >> 1] = "eeprom", - [0xc2 >> 1] = "tuner/xc5000", -}; - -static void do_i2c_scan(char *name, struct i2c_client *c) -{ - unsigned char buf; - int i, rc; - - for (i = 0; i < 128; i++) { - c->addr = i; - rc = i2c_master_recv(c, &buf, 0); - if (rc < 0) - continue; - printk(KERN_INFO "%s: i2c scan: found device @ 0x%x [%s]\n", - name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); - } -} - -/* init + register i2c adapter */ -int au0828_i2c_register(struct au0828_dev *dev) -{ - dprintk(1, "%s()\n", __func__); - - memcpy(&dev->i2c_adap, &au0828_i2c_adap_template, - sizeof(dev->i2c_adap)); - memcpy(&dev->i2c_algo, &au0828_i2c_algo_template, - sizeof(dev->i2c_algo)); - memcpy(&dev->i2c_client, &au0828_i2c_client_template, - sizeof(dev->i2c_client)); - - dev->i2c_adap.dev.parent = &dev->usbdev->dev; - - strlcpy(dev->i2c_adap.name, DRIVER_NAME, - sizeof(dev->i2c_adap.name)); - - dev->i2c_adap.algo = &dev->i2c_algo; - dev->i2c_adap.algo_data = dev; - i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); - i2c_add_adapter(&dev->i2c_adap); - - dev->i2c_client.adapter = &dev->i2c_adap; - - if (0 == dev->i2c_rc) { - printk(KERN_INFO "%s: i2c bus registered\n", DRIVER_NAME); - if (i2c_scan) - do_i2c_scan(DRIVER_NAME, &dev->i2c_client); - } else - printk(KERN_INFO "%s: i2c bus register FAILED\n", DRIVER_NAME); - - return dev->i2c_rc; -} - -int au0828_i2c_unregister(struct au0828_dev *dev) -{ - i2c_del_adapter(&dev->i2c_adap); - return 0; -} - diff --git a/drivers/media/video/au0828/au0828-reg.h b/drivers/media/video/au0828/au0828-reg.h deleted file mode 100644 index 2140f4cfb645..000000000000 --- a/drivers/media/video/au0828/au0828-reg.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Driver for the Auvitek USB bridge - * - * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> - * - * 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. - */ - -/* We'll start to rename these registers once we have a better - * understanding of their meaning. - */ -#define REG_000 0x000 -#define REG_001 0x001 -#define REG_002 0x002 -#define REG_003 0x003 - -#define AU0828_SENSORCTRL_100 0x100 -#define AU0828_SENSORCTRL_VBI_103 0x103 - -/* I2C registers */ -#define AU0828_I2C_TRIGGER_200 0x200 -#define AU0828_I2C_STATUS_201 0x201 -#define AU0828_I2C_CLK_DIVIDER_202 0x202 -#define AU0828_I2C_DEST_ADDR_203 0x203 -#define AU0828_I2C_WRITE_FIFO_205 0x205 -#define AU0828_I2C_READ_FIFO_209 0x209 -#define AU0828_I2C_MULTIBYTE_MODE_2FF 0x2ff - -/* Audio registers */ -#define AU0828_AUDIOCTRL_50C 0x50C - -#define REG_600 0x600 - -/*********************************************************************/ -/* Here are constants for values associated with the above registers */ - -/* I2C Trigger (Reg 0x200) */ -#define AU0828_I2C_TRIGGER_WRITE 0x01 -#define AU0828_I2C_TRIGGER_READ 0x20 -#define AU0828_I2C_TRIGGER_HOLD 0x40 - -/* I2C Status (Reg 0x201) */ -#define AU0828_I2C_STATUS_READ_DONE 0x01 -#define AU0828_I2C_STATUS_NO_READ_ACK 0x02 -#define AU0828_I2C_STATUS_WRITE_DONE 0x04 -#define AU0828_I2C_STATUS_NO_WRITE_ACK 0x08 -#define AU0828_I2C_STATUS_BUSY 0x10 - -/* I2C Clock Divider (Reg 0x202) */ -#define AU0828_I2C_CLK_250KHZ 0x07 -#define AU0828_I2C_CLK_100KHZ 0x14 -#define AU0828_I2C_CLK_30KHZ 0x40 -#define AU0828_I2C_CLK_20KHZ 0x60 diff --git a/drivers/media/video/au0828/au0828-vbi.c b/drivers/media/video/au0828/au0828-vbi.c deleted file mode 100644 index 63f593070ee8..000000000000 --- a/drivers/media/video/au0828/au0828-vbi.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - au0828-vbi.c - VBI driver for au0828 - - Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com> - - This work was sponsored by GetWellNetwork Inc. - - 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., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> - -#include "au0828.h" - -static unsigned int vbibufs = 5; -module_param(vbibufs, int, 0644); -MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32"); - -/* ------------------------------------------------------------------ */ - -static void -free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf) -{ - struct au0828_fh *fh = vq->priv_data; - struct au0828_dev *dev = fh->dev; - unsigned long flags = 0; - if (in_interrupt()) - BUG(); - - /* We used to wait for the buffer to finish here, but this didn't work - because, as we were keeping the state as VIDEOBUF_QUEUED, - videobuf_queue_cancel marked it as finished for us. - (Also, it could wedge forever if the hardware was misconfigured.) - - This should be safe; by the time we get here, the buffer isn't - queued anymore. If we ever start marking the buffers as - VIDEOBUF_ACTIVE, it won't be, though. - */ - spin_lock_irqsave(&dev->slock, flags); - if (dev->isoc_ctl.vbi_buf == buf) - dev->isoc_ctl.vbi_buf = NULL; - spin_unlock_irqrestore(&dev->slock, flags); - - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int -vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) -{ - struct au0828_fh *fh = q->priv_data; - struct au0828_dev *dev = fh->dev; - - *size = dev->vbi_width * dev->vbi_height * 2; - - if (0 == *count) - *count = vbibufs; - if (*count < 2) - *count = 2; - if (*count > 32) - *count = 32; - return 0; -} - -static int -vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct au0828_fh *fh = q->priv_data; - struct au0828_dev *dev = fh->dev; - struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); - int rc = 0; - - buf->vb.size = dev->vbi_width * dev->vbi_height * 2; - - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - buf->vb.width = dev->vbi_width; - buf->vb.height = dev->vbi_height; - buf->vb.field = field; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(q, &buf->vb, NULL); - if (rc < 0) - goto fail; - } - - buf->vb.state = VIDEOBUF_PREPARED; - return 0; - -fail: - free_buffer(q, buf); - return rc; -} - -static void -vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct au0828_buffer *buf = container_of(vb, - struct au0828_buffer, - vb); - struct au0828_fh *fh = vq->priv_data; - struct au0828_dev *dev = fh->dev; - struct au0828_dmaqueue *vbiq = &dev->vbiq; - - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vbiq->active); -} - -static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); - free_buffer(q, buf); -} - -struct videobuf_queue_ops au0828_vbi_qops = { - .buf_setup = vbi_setup, - .buf_prepare = vbi_prepare, - .buf_queue = vbi_queue, - .buf_release = vbi_release, -}; diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c deleted file mode 100644 index fa0fa9ae91c7..000000000000 --- a/drivers/media/video/au0828/au0828-video.c +++ /dev/null @@ -1,2034 +0,0 @@ -/* - * Auvitek AU0828 USB Bridge (Analog video support) - * - * Copyright (C) 2009 Devin Heitmueller <dheitmueller@linuxtv.org> - * Copyright (C) 2005-2008 Auvitek International, Ltd. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/* Developer Notes: - * - * VBI support is not yet working - * The hardware scaler supported is unimplemented - * AC97 audio support is unimplemented (only i2s audio mode) - * - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/suspend.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-chip-ident.h> -#include <media/tuner.h> -#include "au0828.h" -#include "au0828-reg.h" - -static DEFINE_MUTEX(au0828_sysfs_lock); - -/* ------------------------------------------------------------------ - Videobuf operations - ------------------------------------------------------------------*/ - -static unsigned int isoc_debug; -module_param(isoc_debug, int, 0644); -MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]"); - -#define au0828_isocdbg(fmt, arg...) \ -do {\ - if (isoc_debug) { \ - printk(KERN_INFO "au0828 %s :"fmt, \ - __func__ , ##arg); \ - } \ - } while (0) - -static inline void print_err_status(struct au0828_dev *dev, - int packet, int status) -{ - char *errmsg = "Unknown"; - - switch (status) { - case -ENOENT: - errmsg = "unlinked synchronuously"; - break; - case -ECONNRESET: - errmsg = "unlinked asynchronuously"; - break; - case -ENOSR: - errmsg = "Buffer error (overrun)"; - break; - case -EPIPE: - errmsg = "Stalled (device not responding)"; - break; - case -EOVERFLOW: - errmsg = "Babble (bad cable?)"; - break; - case -EPROTO: - errmsg = "Bit-stuff error (bad cable?)"; - break; - case -EILSEQ: - errmsg = "CRC/Timeout (could be anything)"; - break; - case -ETIME: - errmsg = "Device does not respond"; - break; - } - if (packet < 0) { - au0828_isocdbg("URB status %d [%s].\n", status, errmsg); - } else { - au0828_isocdbg("URB packet %d, status %d [%s].\n", - packet, status, errmsg); - } -} - -static int check_dev(struct au0828_dev *dev) -{ - if (dev->dev_state & DEV_DISCONNECTED) { - printk(KERN_INFO "v4l2 ioctl: device not present\n"); - return -ENODEV; - } - - if (dev->dev_state & DEV_MISCONFIGURED) { - printk(KERN_INFO "v4l2 ioctl: device is misconfigured; " - "close and open it again\n"); - return -EIO; - } - return 0; -} - -/* - * IRQ callback, called by URB callback - */ -static void au0828_irq_callback(struct urb *urb) -{ - struct au0828_dmaqueue *dma_q = urb->context; - struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq); - unsigned long flags = 0; - int i; - - switch (urb->status) { - case 0: /* success */ - case -ETIMEDOUT: /* NAK */ - break; - case -ECONNRESET: /* kill */ - case -ENOENT: - case -ESHUTDOWN: - au0828_isocdbg("au0828_irq_callback called: status kill\n"); - return; - default: /* unknown error */ - au0828_isocdbg("urb completition error %d.\n", urb->status); - break; - } - - /* Copy data from URB */ - spin_lock_irqsave(&dev->slock, flags); - dev->isoc_ctl.isoc_copy(dev, urb); - spin_unlock_irqrestore(&dev->slock, flags); - - /* Reset urb buffers */ - for (i = 0; i < urb->number_of_packets; i++) { - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = 0; - } - urb->status = 0; - - urb->status = usb_submit_urb(urb, GFP_ATOMIC); - if (urb->status) { - au0828_isocdbg("urb resubmit failed (error=%i)\n", - urb->status); - } -} - -/* - * Stop and Deallocate URBs - */ -void au0828_uninit_isoc(struct au0828_dev *dev) -{ - struct urb *urb; - int i; - - au0828_isocdbg("au0828: called au0828_uninit_isoc\n"); - - dev->isoc_ctl.nfields = -1; - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - urb = dev->isoc_ctl.urb[i]; - if (urb) { - if (!irqs_disabled()) - usb_kill_urb(urb); - else - usb_unlink_urb(urb); - - if (dev->isoc_ctl.transfer_buffer[i]) { - usb_free_coherent(dev->usbdev, - urb->transfer_buffer_length, - dev->isoc_ctl.transfer_buffer[i], - urb->transfer_dma); - } - usb_free_urb(urb); - dev->isoc_ctl.urb[i] = NULL; - } - dev->isoc_ctl.transfer_buffer[i] = NULL; - } - - kfree(dev->isoc_ctl.urb); - kfree(dev->isoc_ctl.transfer_buffer); - - dev->isoc_ctl.urb = NULL; - dev->isoc_ctl.transfer_buffer = NULL; - dev->isoc_ctl.num_bufs = 0; -} - -/* - * Allocate URBs and start IRQ - */ -int au0828_init_isoc(struct au0828_dev *dev, int max_packets, - int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb)) -{ - struct au0828_dmaqueue *dma_q = &dev->vidq; - int i; - int sb_size, pipe; - struct urb *urb; - int j, k; - int rc; - - au0828_isocdbg("au0828: called au0828_prepare_isoc\n"); - - /* De-allocates all pending stuff */ - au0828_uninit_isoc(dev); - - dev->isoc_ctl.isoc_copy = isoc_copy; - dev->isoc_ctl.num_bufs = num_bufs; - - dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); - if (!dev->isoc_ctl.urb) { - au0828_isocdbg("cannot alloc memory for usb buffers\n"); - return -ENOMEM; - } - - dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, - GFP_KERNEL); - if (!dev->isoc_ctl.transfer_buffer) { - au0828_isocdbg("cannot allocate memory for usb transfer\n"); - kfree(dev->isoc_ctl.urb); - return -ENOMEM; - } - - dev->isoc_ctl.max_pkt_size = max_pkt_size; - dev->isoc_ctl.buf = NULL; - - sb_size = max_packets * dev->isoc_ctl.max_pkt_size; - - /* allocate urbs and transfer buffers */ - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - urb = usb_alloc_urb(max_packets, GFP_KERNEL); - if (!urb) { - au0828_isocdbg("cannot alloc isoc_ctl.urb %i\n", i); - au0828_uninit_isoc(dev); - return -ENOMEM; - } - dev->isoc_ctl.urb[i] = urb; - - dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->usbdev, - sb_size, GFP_KERNEL, &urb->transfer_dma); - if (!dev->isoc_ctl.transfer_buffer[i]) { - printk("unable to allocate %i bytes for transfer" - " buffer %i%s\n", - sb_size, i, - in_interrupt() ? " while in int" : ""); - au0828_uninit_isoc(dev); - return -ENOMEM; - } - memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); - - pipe = usb_rcvisocpipe(dev->usbdev, - dev->isoc_in_endpointaddr), - - usb_fill_int_urb(urb, dev->usbdev, pipe, - dev->isoc_ctl.transfer_buffer[i], sb_size, - au0828_irq_callback, dma_q, 1); - - urb->number_of_packets = max_packets; - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - - k = 0; - for (j = 0; j < max_packets; j++) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = - dev->isoc_ctl.max_pkt_size; - k += dev->isoc_ctl.max_pkt_size; - } - } - - init_waitqueue_head(&dma_q->wq); - - /* submit urbs and enables IRQ */ - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); - if (rc) { - au0828_isocdbg("submit of urb %i failed (error=%i)\n", - i, rc); - au0828_uninit_isoc(dev); - return rc; - } - } - - return 0; -} - -/* - * Announces that a buffer were filled and request the next - */ -static inline void buffer_filled(struct au0828_dev *dev, - struct au0828_dmaqueue *dma_q, - struct au0828_buffer *buf) -{ - /* Advice that buffer was filled */ - au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); - - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - do_gettimeofday(&buf->vb.ts); - - dev->isoc_ctl.buf = NULL; - - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); -} - -static inline void vbi_buffer_filled(struct au0828_dev *dev, - struct au0828_dmaqueue *dma_q, - struct au0828_buffer *buf) -{ - /* Advice that buffer was filled */ - au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); - - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - do_gettimeofday(&buf->vb.ts); - - dev->isoc_ctl.vbi_buf = NULL; - - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); -} - -/* - * Identify the buffer header type and properly handles - */ -static void au0828_copy_video(struct au0828_dev *dev, - struct au0828_dmaqueue *dma_q, - struct au0828_buffer *buf, - unsigned char *p, - unsigned char *outp, unsigned long len) -{ - void *fieldstart, *startwrite, *startread; - int linesdone, currlinedone, offset, lencopy, remain; - int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */ - - if (len == 0) - return; - - if (dma_q->pos + len > buf->vb.size) - len = buf->vb.size - dma_q->pos; - - startread = p; - remain = len; - - /* Interlaces frame */ - if (buf->top_field) - fieldstart = outp; - else - fieldstart = outp + bytesperline; - - linesdone = dma_q->pos / bytesperline; - currlinedone = dma_q->pos % bytesperline; - offset = linesdone * bytesperline * 2 + currlinedone; - startwrite = fieldstart + offset; - lencopy = bytesperline - currlinedone; - lencopy = lencopy > remain ? remain : lencopy; - - if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) { - au0828_isocdbg("Overflow of %zi bytes past buffer end (1)\n", - ((char *)startwrite + lencopy) - - ((char *)outp + buf->vb.size)); - remain = (char *)outp + buf->vb.size - (char *)startwrite; - lencopy = remain; - } - if (lencopy <= 0) - return; - memcpy(startwrite, startread, lencopy); - - remain -= lencopy; - - while (remain > 0) { - startwrite += lencopy + bytesperline; - startread += lencopy; - if (bytesperline > remain) - lencopy = remain; - else - lencopy = bytesperline; - - if ((char *)startwrite + lencopy > (char *)outp + - buf->vb.size) { - au0828_isocdbg("Overflow %zi bytes past buf end (2)\n", - ((char *)startwrite + lencopy) - - ((char *)outp + buf->vb.size)); - lencopy = remain = (char *)outp + buf->vb.size - - (char *)startwrite; - } - if (lencopy <= 0) - break; - - memcpy(startwrite, startread, lencopy); - - remain -= lencopy; - } - - if (offset > 1440) { - /* We have enough data to check for greenscreen */ - if (outp[0] < 0x60 && outp[1440] < 0x60) - dev->greenscreen_detected = 1; - } - - dma_q->pos += len; -} - -/* - * video-buf generic routine to get the next available buffer - */ -static inline void get_next_buf(struct au0828_dmaqueue *dma_q, - struct au0828_buffer **buf) -{ - struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq); - - if (list_empty(&dma_q->active)) { - au0828_isocdbg("No active queue to serve\n"); - dev->isoc_ctl.buf = NULL; - *buf = NULL; - return; - } - - /* Get the next buffer */ - *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue); - dev->isoc_ctl.buf = *buf; - - return; -} - -static void au0828_copy_vbi(struct au0828_dev *dev, - struct au0828_dmaqueue *dma_q, - struct au0828_buffer *buf, - unsigned char *p, - unsigned char *outp, unsigned long len) -{ - unsigned char *startwrite, *startread; - int bytesperline; - int i, j = 0; - - if (dev == NULL) { - au0828_isocdbg("dev is null\n"); - return; - } - - if (dma_q == NULL) { - au0828_isocdbg("dma_q is null\n"); - return; - } - if (buf == NULL) - return; - if (p == NULL) { - au0828_isocdbg("p is null\n"); - return; - } - if (outp == NULL) { - au0828_isocdbg("outp is null\n"); - return; - } - - bytesperline = dev->vbi_width; - - if (dma_q->pos + len > buf->vb.size) - len = buf->vb.size - dma_q->pos; - - startread = p; - startwrite = outp + (dma_q->pos / 2); - - /* Make sure the bottom field populates the second half of the frame */ - if (buf->top_field == 0) - startwrite += bytesperline * dev->vbi_height; - - for (i = 0; i < len; i += 2) - startwrite[j++] = startread[i+1]; - - dma_q->pos += len; -} - - -/* - * video-buf generic routine to get the next available VBI buffer - */ -static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q, - struct au0828_buffer **buf) -{ - struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vbiq); - char *outp; - - if (list_empty(&dma_q->active)) { - au0828_isocdbg("No active queue to serve\n"); - dev->isoc_ctl.vbi_buf = NULL; - *buf = NULL; - return; - } - - /* Get the next buffer */ - *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue); - /* Cleans up buffer - Useful for testing for frame/URB loss */ - outp = videobuf_to_vmalloc(&(*buf)->vb); - memset(outp, 0x00, (*buf)->vb.size); - - dev->isoc_ctl.vbi_buf = *buf; - - return; -} - -/* - * Controls the isoc copy of each urb packet - */ -static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) -{ - struct au0828_buffer *buf; - struct au0828_buffer *vbi_buf; - struct au0828_dmaqueue *dma_q = urb->context; - struct au0828_dmaqueue *vbi_dma_q = &dev->vbiq; - unsigned char *outp = NULL; - unsigned char *vbioutp = NULL; - int i, len = 0, rc = 1; - unsigned char *p; - unsigned char fbyte; - unsigned int vbi_field_size; - unsigned int remain, lencopy; - - if (!dev) - return 0; - - if ((dev->dev_state & DEV_DISCONNECTED) || - (dev->dev_state & DEV_MISCONFIGURED)) - return 0; - - if (urb->status < 0) { - print_err_status(dev, -1, urb->status); - if (urb->status == -ENOENT) - return 0; - } - - buf = dev->isoc_ctl.buf; - if (buf != NULL) - outp = videobuf_to_vmalloc(&buf->vb); - - vbi_buf = dev->isoc_ctl.vbi_buf; - if (vbi_buf != NULL) - vbioutp = videobuf_to_vmalloc(&vbi_buf->vb); - - for (i = 0; i < urb->number_of_packets; i++) { - int status = urb->iso_frame_desc[i].status; - - if (status < 0) { - print_err_status(dev, i, status); - if (urb->iso_frame_desc[i].status != -EPROTO) - continue; - } - - if (urb->iso_frame_desc[i].actual_length <= 0) - continue; - - if (urb->iso_frame_desc[i].actual_length > - dev->max_pkt_size) { - au0828_isocdbg("packet bigger than packet size"); - continue; - } - - p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - fbyte = p[0]; - len = urb->iso_frame_desc[i].actual_length - 4; - p += 4; - - if (fbyte & 0x80) { - len -= 4; - p += 4; - au0828_isocdbg("Video frame %s\n", - (fbyte & 0x40) ? "odd" : "even"); - if (fbyte & 0x40) { - /* VBI */ - if (vbi_buf != NULL) - vbi_buffer_filled(dev, - vbi_dma_q, - vbi_buf); - vbi_get_next_buf(vbi_dma_q, &vbi_buf); - if (vbi_buf == NULL) - vbioutp = NULL; - else - vbioutp = videobuf_to_vmalloc( - &vbi_buf->vb); - - /* Video */ - if (buf != NULL) - buffer_filled(dev, dma_q, buf); - get_next_buf(dma_q, &buf); - if (buf == NULL) - outp = NULL; - else - outp = videobuf_to_vmalloc(&buf->vb); - - /* As long as isoc traffic is arriving, keep - resetting the timer */ - if (dev->vid_timeout_running) - mod_timer(&dev->vid_timeout, - jiffies + (HZ / 10)); - if (dev->vbi_timeout_running) - mod_timer(&dev->vbi_timeout, - jiffies + (HZ / 10)); - } - - if (buf != NULL) { - if (fbyte & 0x40) - buf->top_field = 1; - else - buf->top_field = 0; - } - - if (vbi_buf != NULL) { - if (fbyte & 0x40) - vbi_buf->top_field = 1; - else - vbi_buf->top_field = 0; - } - - dev->vbi_read = 0; - vbi_dma_q->pos = 0; - dma_q->pos = 0; - } - - vbi_field_size = dev->vbi_width * dev->vbi_height * 2; - if (dev->vbi_read < vbi_field_size) { - remain = vbi_field_size - dev->vbi_read; - if (len < remain) - lencopy = len; - else - lencopy = remain; - - if (vbi_buf != NULL) - au0828_copy_vbi(dev, vbi_dma_q, vbi_buf, p, - vbioutp, len); - - len -= lencopy; - p += lencopy; - dev->vbi_read += lencopy; - } - - if (dev->vbi_read >= vbi_field_size && buf != NULL) - au0828_copy_video(dev, dma_q, buf, p, outp, len); - } - return rc; -} - -static int -buffer_setup(struct videobuf_queue *vq, unsigned int *count, - unsigned int *size) -{ - struct au0828_fh *fh = vq->priv_data; - *size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3; - - if (0 == *count) - *count = AU0828_DEF_BUF; - - if (*count < AU0828_MIN_BUF) - *count = AU0828_MIN_BUF; - return 0; -} - -/* This is called *without* dev->slock held; please keep it that way */ -static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf) -{ - struct au0828_fh *fh = vq->priv_data; - struct au0828_dev *dev = fh->dev; - unsigned long flags = 0; - if (in_interrupt()) - BUG(); - - /* We used to wait for the buffer to finish here, but this didn't work - because, as we were keeping the state as VIDEOBUF_QUEUED, - videobuf_queue_cancel marked it as finished for us. - (Also, it could wedge forever if the hardware was misconfigured.) - - This should be safe; by the time we get here, the buffer isn't - queued anymore. If we ever start marking the buffers as - VIDEOBUF_ACTIVE, it won't be, though. - */ - spin_lock_irqsave(&dev->slock, flags); - if (dev->isoc_ctl.buf == buf) - dev->isoc_ctl.buf = NULL; - spin_unlock_irqrestore(&dev->slock, flags); - - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int -buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct au0828_fh *fh = vq->priv_data; - struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb); - struct au0828_dev *dev = fh->dev; - int rc = 0, urb_init = 0; - - buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3; - - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - buf->vb.width = dev->width; - buf->vb.height = dev->height; - buf->vb.field = field; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(vq, &buf->vb, NULL); - if (rc < 0) { - printk(KERN_INFO "videobuf_iolock failed\n"); - goto fail; - } - } - - if (!dev->isoc_ctl.num_bufs) - urb_init = 1; - - if (urb_init) { - rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB, - AU0828_MAX_ISO_BUFS, dev->max_pkt_size, - au0828_isoc_copy); - if (rc < 0) { - printk(KERN_INFO "au0828_init_isoc failed\n"); - goto fail; - } - } - - buf->vb.state = VIDEOBUF_PREPARED; - return 0; - -fail: - free_buffer(vq, buf); - return rc; -} - -static void -buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct au0828_buffer *buf = container_of(vb, - struct au0828_buffer, - vb); - struct au0828_fh *fh = vq->priv_data; - struct au0828_dev *dev = fh->dev; - struct au0828_dmaqueue *vidq = &dev->vidq; - - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vidq->active); -} - -static void buffer_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) -{ - struct au0828_buffer *buf = container_of(vb, - struct au0828_buffer, - vb); - - free_buffer(vq, buf); -} - -static struct videobuf_queue_ops au0828_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, -}; - -/* ------------------------------------------------------------------ - V4L2 interface - ------------------------------------------------------------------*/ - -static int au0828_i2s_init(struct au0828_dev *dev) -{ - /* Enable i2s mode */ - au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01); - return 0; -} - -/* - * Auvitek au0828 analog stream enable - * Please set interface0 to AS5 before enable the stream - */ -int au0828_analog_stream_enable(struct au0828_dev *d) -{ - dprintk(1, "au0828_analog_stream_enable called\n"); - au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00); - au0828_writereg(d, 0x106, 0x00); - /* set x position */ - au0828_writereg(d, 0x110, 0x00); - au0828_writereg(d, 0x111, 0x00); - au0828_writereg(d, 0x114, 0xa0); - au0828_writereg(d, 0x115, 0x05); - /* set y position */ - au0828_writereg(d, 0x112, 0x00); - au0828_writereg(d, 0x113, 0x00); - au0828_writereg(d, 0x116, 0xf2); - au0828_writereg(d, 0x117, 0x00); - au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3); - - return 0; -} - -int au0828_analog_stream_disable(struct au0828_dev *d) -{ - dprintk(1, "au0828_analog_stream_disable called\n"); - au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0); - return 0; -} - -void au0828_analog_stream_reset(struct au0828_dev *dev) -{ - dprintk(1, "au0828_analog_stream_reset called\n"); - au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0); - mdelay(30); - au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3); -} - -/* - * Some operations needs to stop current streaming - */ -static int au0828_stream_interrupt(struct au0828_dev *dev) -{ - int ret = 0; - - dev->stream_state = STREAM_INTERRUPT; - if (dev->dev_state == DEV_DISCONNECTED) - return -ENODEV; - else if (ret) { - dev->dev_state = DEV_MISCONFIGURED; - dprintk(1, "%s device is misconfigured!\n", __func__); - return ret; - } - return 0; -} - -/* - * au0828_release_resources - * unregister v4l2 devices - */ -void au0828_analog_unregister(struct au0828_dev *dev) -{ - dprintk(1, "au0828_release_resources called\n"); - mutex_lock(&au0828_sysfs_lock); - - if (dev->vdev) - video_unregister_device(dev->vdev); - if (dev->vbi_dev) - video_unregister_device(dev->vbi_dev); - - mutex_unlock(&au0828_sysfs_lock); -} - - -/* Usage lock check functions */ -static int res_get(struct au0828_fh *fh, unsigned int bit) -{ - struct au0828_dev *dev = fh->dev; - - if (fh->resources & bit) - /* have it already allocated */ - return 1; - - /* is it free? */ - if (dev->resources & bit) { - /* no, someone else uses it */ - return 0; - } - /* it's free, grab it */ - fh->resources |= bit; - dev->resources |= bit; - dprintk(1, "res: get %d\n", bit); - - return 1; -} - -static int res_check(struct au0828_fh *fh, unsigned int bit) -{ - return fh->resources & bit; -} - -static int res_locked(struct au0828_dev *dev, unsigned int bit) -{ - return dev->resources & bit; -} - -static void res_free(struct au0828_fh *fh, unsigned int bits) -{ - struct au0828_dev *dev = fh->dev; - - BUG_ON((fh->resources & bits) != bits); - - fh->resources &= ~bits; - dev->resources &= ~bits; - dprintk(1, "res: put %d\n", bits); -} - -static int get_ressource(struct au0828_fh *fh) -{ - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - return AU0828_RESOURCE_VIDEO; - case V4L2_BUF_TYPE_VBI_CAPTURE: - return AU0828_RESOURCE_VBI; - default: - BUG(); - return 0; - } -} - -/* This function ensures that video frames continue to be delivered even if - the ITU-656 input isn't receiving any data (thereby preventing applications - such as tvtime from hanging) */ -void au0828_vid_buffer_timeout(unsigned long data) -{ - struct au0828_dev *dev = (struct au0828_dev *) data; - struct au0828_dmaqueue *dma_q = &dev->vidq; - struct au0828_buffer *buf; - unsigned char *vid_data; - unsigned long flags = 0; - - spin_lock_irqsave(&dev->slock, flags); - - buf = dev->isoc_ctl.buf; - if (buf != NULL) { - vid_data = videobuf_to_vmalloc(&buf->vb); - memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */ - buffer_filled(dev, dma_q, buf); - } - get_next_buf(dma_q, &buf); - - if (dev->vid_timeout_running == 1) - mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); - - spin_unlock_irqrestore(&dev->slock, flags); -} - -void au0828_vbi_buffer_timeout(unsigned long data) -{ - struct au0828_dev *dev = (struct au0828_dev *) data; - struct au0828_dmaqueue *dma_q = &dev->vbiq; - struct au0828_buffer *buf; - unsigned char *vbi_data; - unsigned long flags = 0; - - spin_lock_irqsave(&dev->slock, flags); - - buf = dev->isoc_ctl.vbi_buf; - if (buf != NULL) { - vbi_data = videobuf_to_vmalloc(&buf->vb); - memset(vbi_data, 0x00, buf->vb.size); - vbi_buffer_filled(dev, dma_q, buf); - } - vbi_get_next_buf(dma_q, &buf); - - if (dev->vbi_timeout_running == 1) - mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); - spin_unlock_irqrestore(&dev->slock, flags); -} - - -static int au0828_v4l2_open(struct file *filp) -{ - int ret = 0; - struct video_device *vdev = video_devdata(filp); - struct au0828_dev *dev = video_drvdata(filp); - struct au0828_fh *fh; - int type; - - switch (vdev->vfl_type) { - case VFL_TYPE_GRABBER: - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - break; - case VFL_TYPE_VBI: - type = V4L2_BUF_TYPE_VBI_CAPTURE; - break; - default: - return -EINVAL; - } - - fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL); - if (NULL == fh) { - dprintk(1, "Failed allocate au0828_fh struct!\n"); - return -ENOMEM; - } - - fh->type = type; - fh->dev = dev; - filp->private_data = fh; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { - /* set au0828 interface0 to AS5 here again */ - ret = usb_set_interface(dev->usbdev, 0, 5); - if (ret < 0) { - printk(KERN_INFO "Au0828 can't set alternate to 5!\n"); - return -EBUSY; - } - dev->width = NTSC_STD_W; - dev->height = NTSC_STD_H; - dev->frame_size = dev->width * dev->height * 2; - dev->field_size = dev->width * dev->height; - dev->bytesperline = dev->width * 2; - - au0828_analog_stream_enable(dev); - au0828_analog_stream_reset(dev); - - /* If we were doing ac97 instead of i2s, it would go here...*/ - au0828_i2s_init(dev); - - dev->stream_state = STREAM_OFF; - dev->dev_state |= DEV_INITIALIZED; - } - - dev->users++; - - videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops, - NULL, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct au0828_buffer), fh, - &dev->lock); - - /* VBI Setup */ - dev->vbi_width = 720; - dev->vbi_height = 1; - videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops, - NULL, &dev->slock, - V4L2_BUF_TYPE_VBI_CAPTURE, - V4L2_FIELD_SEQ_TB, - sizeof(struct au0828_buffer), fh, - &dev->lock); - return ret; -} - -static int au0828_v4l2_close(struct file *filp) -{ - int ret; - struct au0828_fh *fh = filp->private_data; - struct au0828_dev *dev = fh->dev; - - if (res_check(fh, AU0828_RESOURCE_VIDEO)) { - /* Cancel timeout thread in case they didn't call streamoff */ - dev->vid_timeout_running = 0; - del_timer_sync(&dev->vid_timeout); - - videobuf_stop(&fh->vb_vidq); - res_free(fh, AU0828_RESOURCE_VIDEO); - } - - if (res_check(fh, AU0828_RESOURCE_VBI)) { - /* Cancel timeout thread in case they didn't call streamoff */ - dev->vbi_timeout_running = 0; - del_timer_sync(&dev->vbi_timeout); - - videobuf_stop(&fh->vb_vbiq); - res_free(fh, AU0828_RESOURCE_VBI); - } - - if (dev->users == 1) { - if (dev->dev_state & DEV_DISCONNECTED) { - au0828_analog_unregister(dev); - kfree(dev); - return 0; - } - - au0828_analog_stream_disable(dev); - - au0828_uninit_isoc(dev); - - /* Save some power by putting tuner to sleep */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); - - /* When close the device, set the usb intf0 into alt0 to free - USB bandwidth */ - ret = usb_set_interface(dev->usbdev, 0, 0); - if (ret < 0) - printk(KERN_INFO "Au0828 can't set alternate to 0!\n"); - } - - videobuf_mmap_free(&fh->vb_vidq); - videobuf_mmap_free(&fh->vb_vbiq); - kfree(fh); - dev->users--; - wake_up_interruptible_nr(&dev->open, 1); - return 0; -} - -static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf, - size_t count, loff_t *pos) -{ - struct au0828_fh *fh = filp->private_data; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (res_locked(dev, AU0828_RESOURCE_VIDEO)) - return -EBUSY; - - return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, - filp->f_flags & O_NONBLOCK); - } - - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - if (!res_get(fh, AU0828_RESOURCE_VBI)) - return -EBUSY; - - if (dev->vbi_timeout_running == 0) { - /* Handle case where caller tries to read without - calling streamon first */ - dev->vbi_timeout_running = 1; - mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); - } - - return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0, - filp->f_flags & O_NONBLOCK); - } - - return 0; -} - -static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait) -{ - struct au0828_fh *fh = filp->private_data; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (!res_get(fh, AU0828_RESOURCE_VIDEO)) - return POLLERR; - return videobuf_poll_stream(filp, &fh->vb_vidq, wait); - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - if (!res_get(fh, AU0828_RESOURCE_VBI)) - return POLLERR; - return videobuf_poll_stream(filp, &fh->vb_vbiq, wait); - } else { - return POLLERR; - } -} - -static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct au0828_fh *fh = filp->private_data; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma); - - return rc; -} - -static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, - struct v4l2_format *format) -{ - int ret; - int width = format->fmt.pix.width; - int height = format->fmt.pix.height; - - if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - /* If they are demanding a format other than the one we support, - bail out (tvtime asks for UYVY and then retries with YUYV) */ - if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY) - return -EINVAL; - - /* format->fmt.pix.width only support 720 and height 480 */ - if (width != 720) - width = 720; - if (height != 480) - height = 480; - - format->fmt.pix.width = width; - format->fmt.pix.height = height; - format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; - format->fmt.pix.bytesperline = width * 2; - format->fmt.pix.sizeimage = width * height * 2; - format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - format->fmt.pix.field = V4L2_FIELD_INTERLACED; - - if (cmd == VIDIOC_TRY_FMT) - return 0; - - /* maybe set new image format, driver current only support 720*480 */ - dev->width = width; - dev->height = height; - dev->frame_size = width * height * 2; - dev->field_size = width * height; - dev->bytesperline = width * 2; - - if (dev->stream_state == STREAM_ON) { - dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n"); - ret = au0828_stream_interrupt(dev); - if (ret != 0) { - dprintk(1, "error interrupting video stream!\n"); - return ret; - } - } - - /* set au0828 interface0 to AS5 here again */ - ret = usb_set_interface(dev->usbdev, 0, 5); - if (ret < 0) { - printk(KERN_INFO "Au0828 can't set alt setting to 5!\n"); - return -EBUSY; - } - - au0828_analog_stream_enable(dev); - - return 0; -} - - -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc); - if (qc->type) - return 0; - else - return -EINVAL; -} - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - strlcpy(cap->driver, "au0828", sizeof(cap->driver)); - strlcpy(cap->card, dev->board.name, sizeof(cap->card)); - strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); - - /*set the device capabilities */ - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_VBI_CAPTURE | - V4L2_CAP_AUDIO | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING | - V4L2_CAP_TUNER; - return 0; -} - -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - if (f->index) - return -EINVAL; - - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strcpy(f->description, "Packed YUV2"); - - f->flags = 0; - f->pixelformat = V4L2_PIX_FMT_UYVY; - - return 0; -} - -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - f->fmt.pix.width = dev->width; - f->fmt.pix.height = dev->height; - f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; - f->fmt.pix.bytesperline = dev->bytesperline; - f->fmt.pix.sizeimage = dev->frame_size; - f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */ - f->fmt.pix.field = V4L2_FIELD_INTERLACED; - return 0; -} - -static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - return au0828_set_format(dev, VIDIOC_TRY_FMT, f); -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (videobuf_queue_is_busy(&fh->vb_vidq)) { - printk(KERN_INFO "%s queue busy\n", __func__); - rc = -EBUSY; - goto out; - } - - rc = au0828_set_format(dev, VIDIOC_S_FMT, f); -out: - return rc; -} - -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) - dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1); - - /* FIXME: when we support something other than NTSC, we are going to - have to make the au0828 bridge adjust the size of its capture - buffer, which is currently hardcoded at 720x480 */ - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm); - dev->std_set_in_tuner_core = 1; - - if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) - dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0); - - return 0; -} - -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *input) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - unsigned int tmp; - - static const char *inames[] = { - [AU0828_VMUX_UNDEFINED] = "Undefined", - [AU0828_VMUX_COMPOSITE] = "Composite", - [AU0828_VMUX_SVIDEO] = "S-Video", - [AU0828_VMUX_CABLE] = "Cable TV", - [AU0828_VMUX_TELEVISION] = "Television", - [AU0828_VMUX_DVB] = "DVB", - [AU0828_VMUX_DEBUG] = "tv debug" - }; - - tmp = input->index; - - if (tmp >= AU0828_MAX_INPUT) - return -EINVAL; - if (AUVI_INPUT(tmp).type == 0) - return -EINVAL; - - input->index = tmp; - strcpy(input->name, inames[AUVI_INPUT(tmp).type]); - if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) || - (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE)) - input->type |= V4L2_INPUT_TYPE_TUNER; - else - input->type |= V4L2_INPUT_TYPE_CAMERA; - - input->std = dev->vdev->tvnorms; - - return 0; -} - -static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - *i = dev->ctrl_input; - return 0; -} - -static int vidioc_s_input(struct file *file, void *priv, unsigned int index) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int i; - - dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__, - index); - if (index >= AU0828_MAX_INPUT) - return -EINVAL; - if (AUVI_INPUT(index).type == 0) - return -EINVAL; - dev->ctrl_input = index; - - switch (AUVI_INPUT(index).type) { - case AU0828_VMUX_SVIDEO: - dev->input_type = AU0828_VMUX_SVIDEO; - break; - case AU0828_VMUX_COMPOSITE: - dev->input_type = AU0828_VMUX_COMPOSITE; - break; - case AU0828_VMUX_TELEVISION: - dev->input_type = AU0828_VMUX_TELEVISION; - break; - default: - dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n", - AUVI_INPUT(index).type); - break; - } - - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, - AUVI_INPUT(index).vmux, 0, 0); - - for (i = 0; i < AU0828_MAX_INPUT; i++) { - int enable = 0; - if (AUVI_INPUT(i).audio_setup == NULL) - continue; - - if (i == index) - enable = 1; - else - enable = 0; - if (enable) { - (AUVI_INPUT(i).audio_setup)(dev, enable); - } else { - /* Make sure we leave it turned on if some - other input is routed to this callback */ - if ((AUVI_INPUT(i).audio_setup) != - ((AUVI_INPUT(index).audio_setup))) { - (AUVI_INPUT(i).audio_setup)(dev, enable); - } - } - } - - v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, - AUVI_INPUT(index).amux, 0, 0); - return 0; -} - -static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - unsigned int index = a->index; - - if (a->index > 1) - return -EINVAL; - - index = dev->ctrl_ainput; - if (index == 0) - strcpy(a->name, "Television"); - else - strcpy(a->name, "Line in"); - - a->capability = V4L2_AUDCAP_STEREO; - a->index = index; - return 0; -} - -static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - if (a->index != dev->ctrl_ainput) - return -EINVAL; - return 0; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl); - return 0; - -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl); - return 0; -} - -static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - if (t->index != 0) - return -EINVAL; - - strcpy(t->name, "Auvitek tuner"); - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); - return 0; -} - -static int vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - if (t->index != 0) - return -EINVAL; - - t->type = V4L2_TUNER_ANALOG_TV; - - if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) - dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1); - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); - - if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) - dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0); - - dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal, - t->afc); - - return 0; - -} - -static int vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *freq) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - freq->type = V4L2_TUNER_ANALOG_TV; - freq->frequency = dev->ctrl_freq; - return 0; -} - -static int vidioc_s_frequency(struct file *file, void *priv, - struct v4l2_frequency *freq) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - if (freq->tuner != 0) - return -EINVAL; - if (freq->type != V4L2_TUNER_ANALOG_TV) - return -EINVAL; - - dev->ctrl_freq = freq->frequency; - - if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) - dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1); - - if (dev->std_set_in_tuner_core == 0) { - /* If we've never sent the standard in tuner core, do so now. We - don't do this at device probe because we don't want to incur - the cost of a firmware load */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, - dev->vdev->tvnorms); - dev->std_set_in_tuner_core = 1; - } - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq); - - if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl) - dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0); - - au0828_analog_stream_reset(dev); - - return 0; -} - - -/* RAW VBI ioctls */ - -static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, - struct v4l2_format *format) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - format->fmt.vbi.samples_per_line = dev->vbi_width; - format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - format->fmt.vbi.offset = 0; - format->fmt.vbi.flags = 0; - format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; - - format->fmt.vbi.count[0] = dev->vbi_height; - format->fmt.vbi.count[1] = dev->vbi_height; - format->fmt.vbi.start[0] = 21; - format->fmt.vbi.start[1] = 284; - - return 0; -} - -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - - if (v4l2_chip_match_host(&chip->match)) { - chip->ident = V4L2_IDENT_AU0828; - return 0; - } - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip); - if (chip->ident == V4L2_IDENT_NONE) - return -EINVAL; - - return 0; -} - -static int vidioc_cropcap(struct file *file, void *priv, - struct v4l2_cropcap *cc) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - cc->bounds.left = 0; - cc->bounds.top = 0; - cc->bounds.width = dev->width; - cc->bounds.height = dev->height; - - cc->defrect = cc->bounds; - - cc->pixelaspect.numerator = 54; - cc->pixelaspect.denominator = 59; - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc = -EINVAL; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (unlikely(type != fh->type)) - return -EINVAL; - - dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n", - fh, type, fh->resources, dev->resources); - - if (unlikely(!res_get(fh, get_ressource(fh)))) - return -EBUSY; - - if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - au0828_analog_stream_enable(dev); - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); - } - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - rc = videobuf_streamon(&fh->vb_vidq); - dev->vid_timeout_running = 1; - mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - rc = videobuf_streamon(&fh->vb_vbiq); - dev->vbi_timeout_running = 1; - mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); - } - - return rc; -} - -static int vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - int i; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) - return -EINVAL; - if (type != fh->type) - return -EINVAL; - - dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n", - fh, type, fh->resources, dev->resources); - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - dev->vid_timeout_running = 0; - del_timer_sync(&dev->vid_timeout); - - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); - rc = au0828_stream_interrupt(dev); - if (rc != 0) - return rc; - - for (i = 0; i < AU0828_MAX_INPUT; i++) { - if (AUVI_INPUT(i).audio_setup == NULL) - continue; - (AUVI_INPUT(i).audio_setup)(dev, 0); - } - - if (res_check(fh, AU0828_RESOURCE_VIDEO)) { - videobuf_streamoff(&fh->vb_vidq); - res_free(fh, AU0828_RESOURCE_VIDEO); - } - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - dev->vbi_timeout_running = 0; - del_timer_sync(&dev->vbi_timeout); - - if (res_check(fh, AU0828_RESOURCE_VBI)) { - videobuf_streamoff(&fh->vb_vbiq); - res_free(fh, AU0828_RESOURCE_VBI); - } - } - - return 0; -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int vidioc_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - - reg->val = au0828_read(dev, reg->reg); - return 0; -} - -static int vidioc_s_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - return au0828_writereg(dev, reg->reg, reg->val); -} -#endif - -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_reqbufs(&fh->vb_vidq, rb); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_reqbufs(&fh->vb_vbiq, rb); - - return rc; -} - -static int vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *b) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_querybuf(&fh->vb_vidq, b); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_querybuf(&fh->vb_vbiq, b); - - return rc; -} - -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_qbuf(&fh->vb_vidq, b); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_qbuf(&fh->vb_vbiq, b); - - return rc; -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - /* Workaround for a bug in the au0828 hardware design that sometimes - results in the colorspace being inverted */ - if (dev->greenscreen_detected == 1) { - dprintk(1, "Detected green frame. Resetting stream...\n"); - au0828_analog_stream_reset(dev); - dev->greenscreen_detected = 0; - } - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags & O_NONBLOCK); - - return rc; -} - -static struct v4l2_file_operations au0828_v4l_fops = { - .owner = THIS_MODULE, - .open = au0828_v4l2_open, - .release = au0828_v4l2_close, - .read = au0828_v4l2_read, - .poll = au0828_v4l2_poll, - .mmap = au0828_v4l2_mmap, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, - .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_cropcap = vidioc_cropcap, - .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_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .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 - .vidioc_g_chip_ident = vidioc_g_chip_ident, -}; - -static const struct video_device au0828_video_template = { - .fops = &au0828_v4l_fops, - .release = video_device_release, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = V4L2_STD_NTSC_M, - .current_norm = V4L2_STD_NTSC_M, -}; - -/**************************************************************************/ - -int au0828_analog_register(struct au0828_dev *dev, - struct usb_interface *interface) -{ - int retval = -ENOMEM; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - int i, ret; - - dprintk(1, "au0828_analog_register called!\n"); - - /* set au0828 usb interface0 to as5 */ - retval = usb_set_interface(dev->usbdev, - interface->cur_altsetting->desc.bInterfaceNumber, 5); - if (retval != 0) { - printk(KERN_INFO "Failure setting usb interface0 to as5\n"); - return retval; - } - - /* Figure out which endpoint has the isoc interface */ - iface_desc = interface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { - endpoint = &iface_desc->endpoint[i].desc; - if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) - == USB_DIR_IN) && - ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_ISOC)) { - - /* we find our isoc in endpoint */ - u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize); - dev->max_pkt_size = (tmp & 0x07ff) * - (((tmp & 0x1800) >> 11) + 1); - dev->isoc_in_endpointaddr = endpoint->bEndpointAddress; - } - } - if (!(dev->isoc_in_endpointaddr)) { - printk(KERN_INFO "Could not locate isoc endpoint\n"); - kfree(dev); - return -ENODEV; - } - - init_waitqueue_head(&dev->open); - spin_lock_init(&dev->slock); - - /* init video dma queues */ - INIT_LIST_HEAD(&dev->vidq.active); - INIT_LIST_HEAD(&dev->vidq.queued); - INIT_LIST_HEAD(&dev->vbiq.active); - INIT_LIST_HEAD(&dev->vbiq.queued); - - dev->vid_timeout.function = au0828_vid_buffer_timeout; - dev->vid_timeout.data = (unsigned long) dev; - init_timer(&dev->vid_timeout); - - dev->vbi_timeout.function = au0828_vbi_buffer_timeout; - dev->vbi_timeout.data = (unsigned long) dev; - init_timer(&dev->vbi_timeout); - - dev->width = NTSC_STD_W; - dev->height = NTSC_STD_H; - dev->field_size = dev->width * dev->height; - dev->frame_size = dev->field_size << 1; - dev->bytesperline = dev->width << 1; - dev->ctrl_ainput = 0; - - /* allocate and fill v4l2 video struct */ - dev->vdev = video_device_alloc(); - if (NULL == dev->vdev) { - dprintk(1, "Can't allocate video_device.\n"); - return -ENOMEM; - } - - /* allocate the VBI struct */ - dev->vbi_dev = video_device_alloc(); - if (NULL == dev->vbi_dev) { - dprintk(1, "Can't allocate vbi_device.\n"); - ret = -ENOMEM; - goto err_vdev; - } - - /* Fill the video capture device struct */ - *dev->vdev = au0828_video_template; - dev->vdev->parent = &dev->usbdev->dev; - dev->vdev->lock = &dev->lock; - strcpy(dev->vdev->name, "au0828a video"); - - /* Setup the VBI device */ - *dev->vbi_dev = au0828_video_template; - dev->vbi_dev->parent = &dev->usbdev->dev; - dev->vbi_dev->lock = &dev->lock; - strcpy(dev->vbi_dev->name, "au0828a vbi"); - - /* Register the v4l2 device */ - video_set_drvdata(dev->vdev, dev); - retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1); - if (retval != 0) { - dprintk(1, "unable to register video device (error = %d).\n", - retval); - ret = -ENODEV; - goto err_vbi_dev; - } - - /* Register the vbi device */ - video_set_drvdata(dev->vbi_dev, dev); - retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1); - if (retval != 0) { - dprintk(1, "unable to register vbi device (error = %d).\n", - retval); - ret = -ENODEV; - goto err_vbi_dev; - } - - dprintk(1, "%s completed!\n", __func__); - - return 0; - -err_vbi_dev: - video_device_release(dev->vbi_dev); -err_vdev: - video_device_release(dev->vdev); - return ret; -} - diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h deleted file mode 100644 index 66a56ef7bbe4..000000000000 --- a/drivers/media/video/au0828/au0828.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Driver for the Auvitek AU0828 USB bridge - * - * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> - * - * 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 <linux/usb.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <media/tveeprom.h> - -/* Analog */ -#include <linux/videodev2.h> -#include <media/videobuf-vmalloc.h> -#include <media/v4l2-device.h> - -/* DVB */ -#include "demux.h" -#include "dmxdev.h" -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dvb_net.h" -#include "dvbdev.h" - -#include "au0828-reg.h" -#include "au0828-cards.h" - -#define DRIVER_NAME "au0828" -#define URB_COUNT 16 -#define URB_BUFSIZE (0xe522) - -/* Analog constants */ -#define NTSC_STD_W 720 -#define NTSC_STD_H 480 - -#define AU0828_INTERLACED_DEFAULT 1 -#define V4L2_CID_PRIVATE_SHARPNESS (V4L2_CID_PRIVATE_BASE + 0) - -/* Defination for AU0828 USB transfer */ -#define AU0828_MAX_ISO_BUFS 12 /* maybe resize this value in the future */ -#define AU0828_ISO_PACKETS_PER_URB 128 - -#define AU0828_MIN_BUF 4 -#define AU0828_DEF_BUF 8 - -#define AU0828_MAX_INPUT 4 - -/* au0828 resource types (used for res_get/res_lock etc */ -#define AU0828_RESOURCE_VIDEO 0x01 -#define AU0828_RESOURCE_VBI 0x02 - -enum au0828_itype { - AU0828_VMUX_UNDEFINED = 0, - AU0828_VMUX_COMPOSITE, - AU0828_VMUX_SVIDEO, - AU0828_VMUX_CABLE, - AU0828_VMUX_TELEVISION, - AU0828_VMUX_DVB, - AU0828_VMUX_DEBUG -}; - -struct au0828_input { - enum au0828_itype type; - unsigned int vmux; - unsigned int amux; - void (*audio_setup) (void *priv, int enable); -}; - -struct au0828_board { - char *name; - unsigned int tuner_type; - unsigned char tuner_addr; - unsigned char i2c_clk_divider; - struct au0828_input input[AU0828_MAX_INPUT]; - -}; - -struct au0828_dvb { - struct mutex lock; - struct dvb_adapter adapter; - struct dvb_frontend *frontend; - struct dvb_demux demux; - struct dmxdev dmxdev; - struct dmx_frontend fe_hw; - struct dmx_frontend fe_mem; - struct dvb_net net; - int feeding; -}; - -enum au0828_stream_state { - STREAM_OFF, - STREAM_INTERRUPT, - STREAM_ON -}; - -#define AUVI_INPUT(nr) (dev->board.input[nr]) - -/* device state */ -enum au0828_dev_state { - DEV_INITIALIZED = 0x01, - DEV_DISCONNECTED = 0x02, - DEV_MISCONFIGURED = 0x04 -}; - -struct au0828_fh { - struct au0828_dev *dev; - unsigned int resources; - - struct videobuf_queue vb_vidq; - struct videobuf_queue vb_vbiq; - enum v4l2_buf_type type; -}; - -struct au0828_usb_isoc_ctl { - /* max packet size of isoc transaction */ - int max_pkt_size; - - /* number of allocated urbs */ - int num_bufs; - - /* urb for isoc transfers */ - struct urb **urb; - - /* transfer buffers for isoc transfer */ - char **transfer_buffer; - - /* Last buffer command and region */ - u8 cmd; - int pos, size, pktsize; - - /* Last field: ODD or EVEN? */ - int field; - - /* Stores incomplete commands */ - u32 tmp_buf; - int tmp_buf_len; - - /* Stores already requested buffers */ - struct au0828_buffer *buf; - struct au0828_buffer *vbi_buf; - - /* Stores the number of received fields */ - int nfields; - - /* isoc urb callback */ - int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb); - -}; - -/* buffer for one video frame */ -struct au0828_buffer { - /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - - struct list_head frame; - int top_field; - int receiving; -}; - -struct au0828_dmaqueue { - struct list_head active; - struct list_head queued; - - wait_queue_head_t wq; - - /* Counters to control buffer fill */ - int pos; -}; - -struct au0828_dev { - struct mutex mutex; - struct usb_device *usbdev; - int boardnr; - struct au0828_board board; - u8 ctrlmsg[64]; - - /* I2C */ - struct i2c_adapter i2c_adap; - struct i2c_algorithm i2c_algo; - struct i2c_client i2c_client; - u32 i2c_rc; - - /* Digital */ - struct au0828_dvb dvb; - struct work_struct restart_streaming; - - /* Analog */ - struct v4l2_device v4l2_dev; - int users; - unsigned int resources; /* resources in use */ - struct video_device *vdev; - struct video_device *vbi_dev; - struct timer_list vid_timeout; - int vid_timeout_running; - struct timer_list vbi_timeout; - int vbi_timeout_running; - int width; - int height; - int vbi_width; - int vbi_height; - u32 vbi_read; - u32 field_size; - u32 frame_size; - u32 bytesperline; - int type; - u8 ctrl_ainput; - __u8 isoc_in_endpointaddr; - u8 isoc_init_ok; - int greenscreen_detected; - unsigned int frame_count; - int ctrl_freq; - int input_type; - int std_set_in_tuner_core; - unsigned int ctrl_input; - enum au0828_dev_state dev_state; - enum au0828_stream_state stream_state; - wait_queue_head_t open; - - struct mutex lock; - - /* Isoc control struct */ - struct au0828_dmaqueue vidq; - struct au0828_dmaqueue vbiq; - struct au0828_usb_isoc_ctl isoc_ctl; - spinlock_t slock; - - /* usb transfer */ - int alt; /* alternate */ - int max_pkt_size; /* max packet size of isoc transaction */ - int num_alt; /* Number of alternative settings */ - unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ - struct urb *urb[AU0828_MAX_ISO_BUFS]; /* urb for isoc transfers */ - char *transfer_buffer[AU0828_MAX_ISO_BUFS];/* transfer buffers for isoc - transfer */ - - /* USB / URB Related */ - int urb_streaming; - struct urb *urbs[URB_COUNT]; -}; - -/* ----------------------------------------------------------- */ -#define au0828_read(dev, reg) au0828_readreg(dev, reg) -#define au0828_write(dev, reg, value) au0828_writereg(dev, reg, value) -#define au0828_andor(dev, reg, mask, value) \ - au0828_writereg(dev, reg, \ - (au0828_readreg(dev, reg) & ~(mask)) | ((value) & (mask))) - -#define au0828_set(dev, reg, bit) au0828_andor(dev, (reg), (bit), (bit)) -#define au0828_clear(dev, reg, bit) au0828_andor(dev, (reg), (bit), 0) - -/* ----------------------------------------------------------- */ -/* au0828-core.c */ -extern u32 au0828_read(struct au0828_dev *dev, u16 reg); -extern u32 au0828_write(struct au0828_dev *dev, u16 reg, u32 val); -extern int au0828_debug; - -/* ----------------------------------------------------------- */ -/* au0828-cards.c */ -extern struct au0828_board au0828_boards[]; -extern struct usb_device_id au0828_usb_id_table[]; -extern void au0828_gpio_setup(struct au0828_dev *dev); -extern int au0828_tuner_callback(void *priv, int component, - int command, int arg); -extern void au0828_card_setup(struct au0828_dev *dev); - -/* ----------------------------------------------------------- */ -/* au0828-i2c.c */ -extern int au0828_i2c_register(struct au0828_dev *dev); -extern int au0828_i2c_unregister(struct au0828_dev *dev); - -/* ----------------------------------------------------------- */ -/* au0828-video.c */ -int au0828_analog_register(struct au0828_dev *dev, - struct usb_interface *interface); -int au0828_analog_stream_disable(struct au0828_dev *d); -void au0828_analog_unregister(struct au0828_dev *dev); - -/* ----------------------------------------------------------- */ -/* au0828-dvb.c */ -extern int au0828_dvb_register(struct au0828_dev *dev); -extern void au0828_dvb_unregister(struct au0828_dev *dev); - -/* au0828-vbi.c */ -extern struct videobuf_queue_ops au0828_vbi_qops; - -#define dprintk(level, fmt, arg...)\ - do { if (au0828_debug & level)\ - printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\ - } while (0) diff --git a/drivers/media/video/cpia2/Kconfig b/drivers/media/video/cpia2/Kconfig deleted file mode 100644 index 66e9283f5993..000000000000 --- a/drivers/media/video/cpia2/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -config VIDEO_CPIA2 - tristate "CPiA2 Video For Linux" - depends on VIDEO_DEV && USB && VIDEO_V4L2 - ---help--- - This is the video4linux driver for cameras based on Vision's CPiA2 - (Colour Processor Interface ASIC), such as the Digital Blue QX5 - Microscope. If you have one of these cameras, say Y here - - This driver is also available as a module (cpia2). diff --git a/drivers/media/video/cpia2/Makefile b/drivers/media/video/cpia2/Makefile deleted file mode 100644 index 828cf1b1df86..000000000000 --- a/drivers/media/video/cpia2/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -cpia2-objs := cpia2_v4l.o cpia2_usb.o cpia2_core.o - -obj-$(CONFIG_VIDEO_CPIA2) += cpia2.o diff --git a/drivers/media/video/cpia2/cpia2.h b/drivers/media/video/cpia2/cpia2.h deleted file mode 100644 index cdef677d57ec..000000000000 --- a/drivers/media/video/cpia2/cpia2.h +++ /dev/null @@ -1,487 +0,0 @@ -/**************************************************************************** - * - * Filename: cpia2.h - * - * Copyright 2001, STMicrolectronics, Inc. - * - * Contact: steve.miller@st.com - * - * Description: - * This is a USB driver for CPiA2 based video cameras. - * - * This driver is modelled on the cpia usb driver by - * Jochen Scharrlach and Johannes Erdfeldt. - * - * 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. - * - ****************************************************************************/ - -#ifndef __CPIA2_H__ -#define __CPIA2_H__ - -#include <linux/videodev2.h> -#include <linux/usb.h> -#include <linux/poll.h> -#include <media/v4l2-common.h> -#include <media/v4l2-device.h> -#include <media/v4l2-ctrls.h> - -#include "cpia2_registers.h" - -/* define for verbose debug output */ -//#define _CPIA2_DEBUG_ - -/*** - * Image defines - ***/ - -/* Misc constants */ -#define ALLOW_CORRUPT 0 /* Causes collater to discard checksum */ - -/* USB Transfer mode */ -#define XFER_ISOC 0 -#define XFER_BULK 1 - -/* USB Alternates */ -#define USBIF_CMDONLY 0 -#define USBIF_BULK 1 -#define USBIF_ISO_1 2 /* 128 bytes/ms */ -#define USBIF_ISO_2 3 /* 384 bytes/ms */ -#define USBIF_ISO_3 4 /* 640 bytes/ms */ -#define USBIF_ISO_4 5 /* 768 bytes/ms */ -#define USBIF_ISO_5 6 /* 896 bytes/ms */ -#define USBIF_ISO_6 7 /* 1023 bytes/ms */ - -/* Flicker Modes */ -#define NEVER_FLICKER 0 -#define FLICKER_60 60 -#define FLICKER_50 50 - -/* Debug flags */ -#define DEBUG_NONE 0 -#define DEBUG_REG 0x00000001 -#define DEBUG_DUMP_PATCH 0x00000002 -#define DEBUG_DUMP_REGS 0x00000004 - -/*** - * Video frame sizes - ***/ -enum { - VIDEOSIZE_VGA = 0, /* 640x480 */ - VIDEOSIZE_CIF, /* 352x288 */ - VIDEOSIZE_QVGA, /* 320x240 */ - VIDEOSIZE_QCIF, /* 176x144 */ - VIDEOSIZE_288_216, - VIDEOSIZE_256_192, - VIDEOSIZE_224_168, - VIDEOSIZE_192_144, -}; - -#define STV_IMAGE_CIF_ROWS 288 -#define STV_IMAGE_CIF_COLS 352 - -#define STV_IMAGE_QCIF_ROWS 144 -#define STV_IMAGE_QCIF_COLS 176 - -#define STV_IMAGE_VGA_ROWS 480 -#define STV_IMAGE_VGA_COLS 640 - -#define STV_IMAGE_QVGA_ROWS 240 -#define STV_IMAGE_QVGA_COLS 320 - -#define JPEG_MARKER_COM (1<<6) /* Comment segment */ - -/*** - * Enums - ***/ -/* Sensor types available with cpia2 asics */ -enum sensors { - CPIA2_SENSOR_410, - CPIA2_SENSOR_500 -}; - -/* Asic types available in the CPiA2 architecture */ -#define CPIA2_ASIC_672 0x67 - -/* Device types (stv672, stv676, etc) */ -#define DEVICE_STV_672 0x0001 -#define DEVICE_STV_676 0x0002 - -enum frame_status { - FRAME_EMPTY, - FRAME_READING, /* In the process of being grabbed into */ - FRAME_READY, /* Ready to be read */ - FRAME_ERROR, -}; - -/*** - * Register access (for USB request byte) - ***/ -enum { - CAMERAACCESS_SYSTEM = 0, - CAMERAACCESS_VC, - CAMERAACCESS_VP, - CAMERAACCESS_IDATA -}; - -#define CAMERAACCESS_TYPE_BLOCK 0x00 -#define CAMERAACCESS_TYPE_RANDOM 0x04 -#define CAMERAACCESS_TYPE_MASK 0x08 -#define CAMERAACCESS_TYPE_REPEAT 0x0C - -#define TRANSFER_READ 0 -#define TRANSFER_WRITE 1 - -#define DEFAULT_ALT USBIF_ISO_6 -#define DEFAULT_BRIGHTNESS 0x46 -#define DEFAULT_CONTRAST 0x93 -#define DEFAULT_SATURATION 0x7f - -/* Power state */ -#define HI_POWER_MODE CPIA2_SYSTEM_CONTROL_HIGH_POWER -#define LO_POWER_MODE CPIA2_SYSTEM_CONTROL_LOW_POWER - - -/******** - * Commands - *******/ -enum { - CPIA2_CMD_NONE = 0, - CPIA2_CMD_GET_VERSION, - CPIA2_CMD_GET_PNP_ID, - CPIA2_CMD_GET_ASIC_TYPE, - CPIA2_CMD_GET_SENSOR, - CPIA2_CMD_GET_VP_DEVICE, - CPIA2_CMD_GET_VP_BRIGHTNESS, - CPIA2_CMD_SET_VP_BRIGHTNESS, - CPIA2_CMD_GET_CONTRAST, - CPIA2_CMD_SET_CONTRAST, - CPIA2_CMD_GET_VP_SATURATION, - CPIA2_CMD_SET_VP_SATURATION, - CPIA2_CMD_GET_VP_GPIO_DIRECTION, - CPIA2_CMD_SET_VP_GPIO_DIRECTION, - CPIA2_CMD_GET_VP_GPIO_DATA, - CPIA2_CMD_SET_VP_GPIO_DATA, - CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION, - CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION, - CPIA2_CMD_GET_VC_MP_GPIO_DATA, - CPIA2_CMD_SET_VC_MP_GPIO_DATA, - CPIA2_CMD_ENABLE_PACKET_CTRL, - CPIA2_CMD_GET_FLICKER_MODES, - CPIA2_CMD_SET_FLICKER_MODES, - CPIA2_CMD_RESET_FIFO, /* clear fifo and enable stream block */ - CPIA2_CMD_SET_HI_POWER, - CPIA2_CMD_SET_LOW_POWER, - CPIA2_CMD_CLEAR_V2W_ERR, - CPIA2_CMD_SET_USER_MODE, - CPIA2_CMD_GET_USER_MODE, - CPIA2_CMD_FRAMERATE_REQ, - CPIA2_CMD_SET_COMPRESSION_STATE, - CPIA2_CMD_GET_WAKEUP, - CPIA2_CMD_SET_WAKEUP, - CPIA2_CMD_GET_PW_CONTROL, - CPIA2_CMD_SET_PW_CONTROL, - CPIA2_CMD_GET_SYSTEM_CTRL, - CPIA2_CMD_SET_SYSTEM_CTRL, - CPIA2_CMD_GET_VP_SYSTEM_STATE, - CPIA2_CMD_GET_VP_SYSTEM_CTRL, - CPIA2_CMD_SET_VP_SYSTEM_CTRL, - CPIA2_CMD_GET_VP_EXP_MODES, - CPIA2_CMD_SET_VP_EXP_MODES, - CPIA2_CMD_GET_DEVICE_CONFIG, - CPIA2_CMD_SET_DEVICE_CONFIG, - CPIA2_CMD_SET_SERIAL_ADDR, - CPIA2_CMD_SET_SENSOR_CR1, - CPIA2_CMD_GET_VC_CONTROL, - CPIA2_CMD_SET_VC_CONTROL, - CPIA2_CMD_SET_TARGET_KB, - CPIA2_CMD_SET_DEF_JPEG_OPT, - CPIA2_CMD_REHASH_VP4, - CPIA2_CMD_GET_USER_EFFECTS, - CPIA2_CMD_SET_USER_EFFECTS -}; - -enum user_cmd { - COMMAND_NONE = 0x00000001, - COMMAND_SET_FPS = 0x00000002, - COMMAND_SET_COLOR_PARAMS = 0x00000004, - COMMAND_GET_COLOR_PARAMS = 0x00000008, - COMMAND_SET_FORMAT = 0x00000010, /* size, etc */ - COMMAND_SET_FLICKER = 0x00000020 -}; - -/*** - * Some defines specific to the 676 chip - ***/ -#define CAMACC_CIF 0x01 -#define CAMACC_VGA 0x02 -#define CAMACC_QCIF 0x04 -#define CAMACC_QVGA 0x08 - - -struct cpia2_register { - u8 index; - u8 value; -}; - -struct cpia2_reg_mask { - u8 index; - u8 and_mask; - u8 or_mask; - u8 fill; -}; - -struct cpia2_command { - u32 command; - u8 req_mode; /* (Block or random) | registerBank */ - u8 reg_count; - u8 direction; - u8 start; - union reg_types { - struct cpia2_register registers[32]; - struct cpia2_reg_mask masks[16]; - u8 block_data[64]; - u8 *patch_data; /* points to function defined block */ - } buffer; -}; - -struct camera_params { - struct { - u8 firmware_revision_hi; /* For system register set (bank 0) */ - u8 firmware_revision_lo; - u8 asic_id; /* Video Compressor set (bank 1) */ - u8 asic_rev; - u8 vp_device_hi; /* Video Processor set (bank 2) */ - u8 vp_device_lo; - u8 sensor_flags; - u8 sensor_rev; - } version; - - struct { - u32 device_type; /* enumerated from vendor/product ids. - * Currently, either STV_672 or STV_676 */ - u16 vendor; - u16 product; - u16 device_revision; - } pnp_id; - - struct { - u8 brightness; /* CPIA2_VP_EXPOSURE_TARGET */ - u8 contrast; /* Note: this is CPIA2_VP_YRANGE */ - u8 saturation; /* CPIA2_VP_SATURATION */ - } color_params; - - struct { - u8 cam_register; - u8 flicker_mode_req; /* 1 if flicker on, else never flicker */ - } flicker_control; - - struct { - u8 jpeg_options; - u8 creep_period; - u8 user_squeeze; - u8 inhibit_htables; - } compression; - - struct { - u8 ohsize; /* output image size */ - u8 ovsize; - u8 hcrop; /* cropping start_pos/4 */ - u8 vcrop; - u8 hphase; /* scaling registers */ - u8 vphase; - u8 hispan; - u8 vispan; - u8 hicrop; - u8 vicrop; - u8 hifraction; - u8 vifraction; - } image_size; - - struct { - int width; /* actual window width */ - int height; /* actual window height */ - } roi; - - struct { - u8 video_mode; - u8 frame_rate; - u8 video_size; /* Not a register, just a convenience for cropped sizes */ - u8 gpio_direction; - u8 gpio_data; - u8 system_ctrl; - u8 system_state; - u8 lowlight_boost; /* Bool: 0 = off, 1 = on */ - u8 device_config; - u8 exposure_modes; - u8 user_effects; - } vp_params; - - struct { - u8 pw_control; - u8 wakeup; - u8 vc_control; - u8 vc_mp_direction; - u8 vc_mp_data; - u8 quality; - } vc_params; - - struct { - u8 power_mode; - u8 system_ctrl; - u8 stream_mode; /* This is the current alternate for usb drivers */ - u8 allow_corrupt; - } camera_state; -}; - -#define NUM_SBUF 2 - -struct cpia2_sbuf { - char *data; - struct urb *urb; -}; - -struct framebuf { - struct timeval timestamp; - unsigned long seq; - int num; - int length; - int max_length; - volatile enum frame_status status; - u8 *data; - struct framebuf *next; -}; - -struct camera_data { - /* locks */ - struct v4l2_device v4l2_dev; - struct mutex v4l2_lock; /* serialize file operations */ - struct v4l2_ctrl_handler hdl; - struct { - /* Lights control cluster */ - struct v4l2_ctrl *top_light; - struct v4l2_ctrl *bottom_light; - }; - struct v4l2_ctrl *usb_alt; - - /* camera status */ - int first_image_seen; - enum sensors sensor_type; - u8 flush; - struct v4l2_fh *stream_fh; - u8 mmapped; - int streaming; /* 0 = no, 1 = yes */ - int xfer_mode; /* XFER_BULK or XFER_ISOC */ - struct camera_params params; /* camera settings */ - - /* v4l */ - int video_size; /* VIDEO_SIZE_ */ - struct video_device vdev; /* v4l videodev */ - u32 width; - u32 height; /* Its size */ - __u32 pixelformat; /* Format fourcc */ - - /* USB */ - struct usb_device *dev; - unsigned char iface; - unsigned int cur_alt; - unsigned int old_alt; - struct cpia2_sbuf sbuf[NUM_SBUF]; /* Double buffering */ - - wait_queue_head_t wq_stream; - - /* Buffering */ - u32 frame_size; - int num_frames; - unsigned long frame_count; - u8 *frame_buffer; /* frame buffer data */ - struct framebuf *buffers; - struct framebuf * volatile curbuff; - struct framebuf *workbuff; - - /* MJPEG Extension */ - int APPn; /* Number of APP segment to be written, must be 0..15 */ - int APP_len; /* Length of data in JPEG APPn segment */ - char APP_data[60]; /* Data in the JPEG APPn segment. */ - - int COM_len; /* Length of data in JPEG COM segment */ - char COM_data[60]; /* Data in JPEG COM segment */ -}; - -/* v4l */ -int cpia2_register_camera(struct camera_data *cam); -void cpia2_unregister_camera(struct camera_data *cam); -void cpia2_camera_release(struct v4l2_device *v4l2_dev); - -/* core */ -int cpia2_reset_camera(struct camera_data *cam); -int cpia2_set_low_power(struct camera_data *cam); -void cpia2_dbg_dump_registers(struct camera_data *cam); -int cpia2_match_video_size(int width, int height); -void cpia2_set_camera_state(struct camera_data *cam); -void cpia2_save_camera_state(struct camera_data *cam); -void cpia2_set_color_params(struct camera_data *cam); -void cpia2_set_brightness(struct camera_data *cam, unsigned char value); -void cpia2_set_contrast(struct camera_data *cam, unsigned char value); -void cpia2_set_saturation(struct camera_data *cam, unsigned char value); -int cpia2_set_flicker_mode(struct camera_data *cam, int mode); -void cpia2_set_format(struct camera_data *cam); -int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd); -int cpia2_do_command(struct camera_data *cam, - unsigned int command, - unsigned char direction, unsigned char param); -struct camera_data *cpia2_init_camera_struct(struct usb_interface *intf); -int cpia2_init_camera(struct camera_data *cam); -int cpia2_allocate_buffers(struct camera_data *cam); -void cpia2_free_buffers(struct camera_data *cam); -long cpia2_read(struct camera_data *cam, - char __user *buf, unsigned long count, int noblock); -unsigned int cpia2_poll(struct camera_data *cam, - struct file *filp, poll_table *wait); -int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma); -void cpia2_set_property_flip(struct camera_data *cam, int prop_val); -void cpia2_set_property_mirror(struct camera_data *cam, int prop_val); -int cpia2_set_gpio(struct camera_data *cam, unsigned char setting); -int cpia2_set_fps(struct camera_data *cam, int framerate); - -/* usb */ -int cpia2_usb_init(void); -void cpia2_usb_cleanup(void); -int cpia2_usb_transfer_cmd(struct camera_data *cam, void *registers, - u8 request, u8 start, u8 count, u8 direction); -int cpia2_usb_stream_start(struct camera_data *cam, unsigned int alternate); -int cpia2_usb_stream_stop(struct camera_data *cam); -int cpia2_usb_stream_pause(struct camera_data *cam); -int cpia2_usb_stream_resume(struct camera_data *cam); -int cpia2_usb_change_streaming_alternate(struct camera_data *cam, - unsigned int alt); - - -/* ----------------------- debug functions ---------------------- */ -#ifdef _CPIA2_DEBUG_ -#define ALOG(lev, fmt, args...) printk(lev "%s:%d %s(): " fmt, __FILE__, __LINE__, __func__, ## args) -#define LOG(fmt, args...) ALOG(KERN_INFO, fmt, ## args) -#define ERR(fmt, args...) ALOG(KERN_ERR, fmt, ## args) -#define DBG(fmt, args...) ALOG(KERN_DEBUG, fmt, ## args) -#else -#define ALOG(fmt,args...) printk(fmt,##args) -#define LOG(fmt,args...) ALOG(KERN_INFO "cpia2: "fmt,##args) -#define ERR(fmt,args...) ALOG(KERN_ERR "cpia2: "fmt,##args) -#define DBG(fmn,args...) do {} while(0) -#endif -/* No function or lineno, for shorter lines */ -#define KINFO(fmt, args...) printk(KERN_INFO fmt,##args) - -#endif diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c deleted file mode 100644 index 187012ce444b..000000000000 --- a/drivers/media/video/cpia2/cpia2_core.c +++ /dev/null @@ -1,2417 +0,0 @@ -/**************************************************************************** - * - * Filename: cpia2_core.c - * - * Copyright 2001, STMicrolectronics, Inc. - * Contact: steve.miller@st.com - * - * Description: - * This is a USB driver for CPia2 based video cameras. - * The infrastructure of this driver is based on the cpia usb driver by - * Jochen Scharrlach and Johannes Erdfeldt. - * - * 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. - * - * Stripped of 2.4 stuff ready for main kernel submit by - * Alan Cox <alan@lxorguk.ukuu.org.uk> - * - ****************************************************************************/ - -#include "cpia2.h" - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/vmalloc.h> -#include <linux/firmware.h> - -#define FIRMWARE "cpia2/stv0672_vp4.bin" -MODULE_FIRMWARE(FIRMWARE); - -/* #define _CPIA2_DEBUG_ */ - -#ifdef _CPIA2_DEBUG_ - -static const char *block_name[] = { - "System", - "VC", - "VP", - "IDATA" -}; -#endif - -static unsigned int debugs_on; /* default 0 - DEBUG_REG */ - - -/****************************************************************************** - * - * Forward Declarations - * - *****************************************************************************/ -static int apply_vp_patch(struct camera_data *cam); -static int set_default_user_mode(struct camera_data *cam); -static int set_vw_size(struct camera_data *cam, int size); -static int configure_sensor(struct camera_data *cam, - int reqwidth, int reqheight); -static int config_sensor_410(struct camera_data *cam, - int reqwidth, int reqheight); -static int config_sensor_500(struct camera_data *cam, - int reqwidth, int reqheight); -static int set_all_properties(struct camera_data *cam); -static void wake_system(struct camera_data *cam); -static void set_lowlight_boost(struct camera_data *cam); -static void reset_camera_struct(struct camera_data *cam); -static int cpia2_set_high_power(struct camera_data *cam); - -/* Here we want the physical address of the memory. - * This is used when initializing the contents of the - * area and marking the pages as reserved. - */ -static inline unsigned long kvirt_to_pa(unsigned long adr) -{ - unsigned long kva, ret; - - kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); - kva |= adr & (PAGE_SIZE-1); /* restore the offset */ - ret = __pa(kva); - return ret; -} - -static void *rvmalloc(unsigned long size) -{ - void *mem; - unsigned long adr; - - /* Round it off to PAGE_SIZE */ - size = PAGE_ALIGN(size); - - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - - while ((long)size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - return mem; -} - -static void rvfree(void *mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - size = PAGE_ALIGN(size); - - adr = (unsigned long) mem; - while ((long)size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - vfree(mem); -} - -/****************************************************************************** - * - * cpia2_do_command - * - * Send an arbitrary command to the camera. For commands that read from - * the camera, copy the buffers into the proper param structures. - *****************************************************************************/ -int cpia2_do_command(struct camera_data *cam, - u32 command, u8 direction, u8 param) -{ - int retval = 0; - struct cpia2_command cmd; - unsigned int device = cam->params.pnp_id.device_type; - - cmd.command = command; - cmd.reg_count = 2; /* default */ - cmd.direction = direction; - - /*** - * Set up the command. - ***/ - switch (command) { - case CPIA2_CMD_GET_VERSION: - cmd.req_mode = - CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; - cmd.start = CPIA2_SYSTEM_DEVICE_HI; - break; - case CPIA2_CMD_GET_PNP_ID: - cmd.req_mode = - CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; - cmd.reg_count = 8; - cmd.start = CPIA2_SYSTEM_DESCRIP_VID_HI; - break; - case CPIA2_CMD_GET_ASIC_TYPE: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; - cmd.start = CPIA2_VC_ASIC_ID; - break; - case CPIA2_CMD_GET_SENSOR: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.start = CPIA2_VP_SENSOR_FLAGS; - break; - case CPIA2_CMD_GET_VP_DEVICE: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.start = CPIA2_VP_DEVICEH; - break; - case CPIA2_CMD_SET_VP_BRIGHTNESS: - cmd.buffer.block_data[0] = param; /* Then fall through */ - case CPIA2_CMD_GET_VP_BRIGHTNESS: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 1; - if (device == DEVICE_STV_672) - cmd.start = CPIA2_VP4_EXPOSURE_TARGET; - else - cmd.start = CPIA2_VP5_EXPOSURE_TARGET; - break; - case CPIA2_CMD_SET_CONTRAST: - cmd.buffer.block_data[0] = param; /* Then fall through */ - case CPIA2_CMD_GET_CONTRAST: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 1; - cmd.start = CPIA2_VP_YRANGE; - break; - case CPIA2_CMD_SET_VP_SATURATION: - cmd.buffer.block_data[0] = param; /* Then fall through */ - case CPIA2_CMD_GET_VP_SATURATION: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 1; - if (device == DEVICE_STV_672) - cmd.start = CPIA2_VP_SATURATION; - else - cmd.start = CPIA2_VP5_MCUVSATURATION; - break; - case CPIA2_CMD_SET_VP_GPIO_DATA: - cmd.buffer.block_data[0] = param; /* Then fall through */ - case CPIA2_CMD_GET_VP_GPIO_DATA: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 1; - cmd.start = CPIA2_VP_GPIO_DATA; - break; - case CPIA2_CMD_SET_VP_GPIO_DIRECTION: - cmd.buffer.block_data[0] = param; /* Then fall through */ - case CPIA2_CMD_GET_VP_GPIO_DIRECTION: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 1; - cmd.start = CPIA2_VP_GPIO_DIRECTION; - break; - case CPIA2_CMD_SET_VC_MP_GPIO_DATA: - cmd.buffer.block_data[0] = param; /* Then fall through */ - case CPIA2_CMD_GET_VC_MP_GPIO_DATA: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; - cmd.reg_count = 1; - cmd.start = CPIA2_VC_MP_DATA; - break; - case CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION: - cmd.buffer.block_data[0] = param; /* Then fall through */ - case CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; - cmd.reg_count = 1; - cmd.start = CPIA2_VC_MP_DIR; - break; - case CPIA2_CMD_ENABLE_PACKET_CTRL: - cmd.req_mode = - CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; - cmd.start = CPIA2_SYSTEM_INT_PACKET_CTRL; - cmd.reg_count = 1; - cmd.buffer.block_data[0] = param; - break; - case CPIA2_CMD_SET_FLICKER_MODES: - cmd.buffer.block_data[0] = param; /* Then fall through */ - case CPIA2_CMD_GET_FLICKER_MODES: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 1; - cmd.start = CPIA2_VP_FLICKER_MODES; - break; - case CPIA2_CMD_RESET_FIFO: /* clear fifo and enable stream block */ - cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC; - cmd.reg_count = 2; - cmd.start = 0; - cmd.buffer.registers[0].index = CPIA2_VC_ST_CTRL; - cmd.buffer.registers[0].value = CPIA2_VC_ST_CTRL_SRC_VC | - CPIA2_VC_ST_CTRL_DST_USB | CPIA2_VC_ST_CTRL_EOF_DETECT; - cmd.buffer.registers[1].index = CPIA2_VC_ST_CTRL; - cmd.buffer.registers[1].value = CPIA2_VC_ST_CTRL_SRC_VC | - CPIA2_VC_ST_CTRL_DST_USB | - CPIA2_VC_ST_CTRL_EOF_DETECT | - CPIA2_VC_ST_CTRL_FIFO_ENABLE; - break; - case CPIA2_CMD_SET_HI_POWER: - cmd.req_mode = - CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_SYSTEM; - cmd.reg_count = 2; - cmd.buffer.registers[0].index = - CPIA2_SYSTEM_SYSTEM_CONTROL; - cmd.buffer.registers[1].index = - CPIA2_SYSTEM_SYSTEM_CONTROL; - cmd.buffer.registers[0].value = CPIA2_SYSTEM_CONTROL_CLEAR_ERR; - cmd.buffer.registers[1].value = - CPIA2_SYSTEM_CONTROL_HIGH_POWER; - break; - case CPIA2_CMD_SET_LOW_POWER: - cmd.req_mode = - CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; - cmd.reg_count = 1; - cmd.start = CPIA2_SYSTEM_SYSTEM_CONTROL; - cmd.buffer.block_data[0] = 0; - break; - case CPIA2_CMD_CLEAR_V2W_ERR: - cmd.req_mode = - CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; - cmd.reg_count = 1; - cmd.start = CPIA2_SYSTEM_SYSTEM_CONTROL; - cmd.buffer.block_data[0] = CPIA2_SYSTEM_CONTROL_CLEAR_ERR; - break; - case CPIA2_CMD_SET_USER_MODE: /* Then fall through */ - cmd.buffer.block_data[0] = param; - case CPIA2_CMD_GET_USER_MODE: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 1; - if (device == DEVICE_STV_672) - cmd.start = CPIA2_VP4_USER_MODE; - else - cmd.start = CPIA2_VP5_USER_MODE; - break; - case CPIA2_CMD_FRAMERATE_REQ: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 1; - if (device == DEVICE_STV_672) - cmd.start = CPIA2_VP4_FRAMERATE_REQUEST; - else - cmd.start = CPIA2_VP5_FRAMERATE_REQUEST; - cmd.buffer.block_data[0] = param; - break; - case CPIA2_CMD_SET_WAKEUP: - cmd.buffer.block_data[0] = param; /* Then fall through */ - case CPIA2_CMD_GET_WAKEUP: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; - cmd.reg_count = 1; - cmd.start = CPIA2_VC_WAKEUP; - break; - case CPIA2_CMD_SET_PW_CONTROL: - cmd.buffer.block_data[0] = param; /* Then fall through */ - case CPIA2_CMD_GET_PW_CONTROL: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; - cmd.reg_count = 1; - cmd.start = CPIA2_VC_PW_CTRL; - break; - case CPIA2_CMD_GET_VP_SYSTEM_STATE: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 1; - cmd.start = CPIA2_VP_SYSTEMSTATE; - break; - case CPIA2_CMD_SET_SYSTEM_CTRL: - cmd.buffer.block_data[0] = param; /* Then fall through */ - case CPIA2_CMD_GET_SYSTEM_CTRL: - cmd.req_mode = - CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; - cmd.reg_count = 1; - cmd.start = CPIA2_SYSTEM_SYSTEM_CONTROL; - break; - case CPIA2_CMD_SET_VP_SYSTEM_CTRL: - cmd.buffer.block_data[0] = param; /* Then fall through */ - case CPIA2_CMD_GET_VP_SYSTEM_CTRL: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 1; - cmd.start = CPIA2_VP_SYSTEMCTRL; - break; - case CPIA2_CMD_SET_VP_EXP_MODES: - cmd.buffer.block_data[0] = param; /* Then fall through */ - case CPIA2_CMD_GET_VP_EXP_MODES: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 1; - cmd.start = CPIA2_VP_EXPOSURE_MODES; - break; - case CPIA2_CMD_SET_DEVICE_CONFIG: - cmd.buffer.block_data[0] = param; /* Then fall through */ - case CPIA2_CMD_GET_DEVICE_CONFIG: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 1; - cmd.start = CPIA2_VP_DEVICE_CONFIG; - break; - case CPIA2_CMD_SET_SERIAL_ADDR: - cmd.buffer.block_data[0] = param; - cmd.req_mode = - CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; - cmd.reg_count = 1; - cmd.start = CPIA2_SYSTEM_VP_SERIAL_ADDR; - break; - case CPIA2_CMD_SET_SENSOR_CR1: - cmd.buffer.block_data[0] = param; - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 1; - cmd.start = CPIA2_SENSOR_CR1; - break; - case CPIA2_CMD_SET_VC_CONTROL: - cmd.buffer.block_data[0] = param; /* Then fall through */ - case CPIA2_CMD_GET_VC_CONTROL: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; - cmd.reg_count = 1; - cmd.start = CPIA2_VC_VC_CTRL; - break; - case CPIA2_CMD_SET_TARGET_KB: - cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC; - cmd.reg_count = 1; - cmd.buffer.registers[0].index = CPIA2_VC_VC_TARGET_KB; - cmd.buffer.registers[0].value = param; - break; - case CPIA2_CMD_SET_DEF_JPEG_OPT: - cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC; - cmd.reg_count = 4; - cmd.buffer.registers[0].index = CPIA2_VC_VC_JPEG_OPT; - cmd.buffer.registers[0].value = - CPIA2_VC_VC_JPEG_OPT_DOUBLE_SQUEEZE; - cmd.buffer.registers[1].index = CPIA2_VC_VC_USER_SQUEEZE; - cmd.buffer.registers[1].value = 20; - cmd.buffer.registers[2].index = CPIA2_VC_VC_CREEP_PERIOD; - cmd.buffer.registers[2].value = 2; - cmd.buffer.registers[3].index = CPIA2_VC_VC_JPEG_OPT; - cmd.buffer.registers[3].value = CPIA2_VC_VC_JPEG_OPT_DEFAULT; - break; - case CPIA2_CMD_REHASH_VP4: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 1; - cmd.start = CPIA2_VP_REHASH_VALUES; - cmd.buffer.block_data[0] = param; - break; - case CPIA2_CMD_SET_USER_EFFECTS: /* Note: Be careful with this as - this register can also affect - flicker modes */ - cmd.buffer.block_data[0] = param; /* Then fall through */ - case CPIA2_CMD_GET_USER_EFFECTS: - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 1; - if (device == DEVICE_STV_672) - cmd.start = CPIA2_VP4_USER_EFFECTS; - else - cmd.start = CPIA2_VP5_USER_EFFECTS; - break; - default: - LOG("DoCommand received invalid command\n"); - return -EINVAL; - } - - retval = cpia2_send_command(cam, &cmd); - if (retval) { - return retval; - } - - /*** - * Now copy any results from a read into the appropriate param struct. - ***/ - switch (command) { - case CPIA2_CMD_GET_VERSION: - cam->params.version.firmware_revision_hi = - cmd.buffer.block_data[0]; - cam->params.version.firmware_revision_lo = - cmd.buffer.block_data[1]; - break; - case CPIA2_CMD_GET_PNP_ID: - cam->params.pnp_id.vendor = (cmd.buffer.block_data[0] << 8) | - cmd.buffer.block_data[1]; - cam->params.pnp_id.product = (cmd.buffer.block_data[2] << 8) | - cmd.buffer.block_data[3]; - cam->params.pnp_id.device_revision = - (cmd.buffer.block_data[4] << 8) | - cmd.buffer.block_data[5]; - if (cam->params.pnp_id.vendor == 0x553) { - if (cam->params.pnp_id.product == 0x100) { - cam->params.pnp_id.device_type = DEVICE_STV_672; - } else if (cam->params.pnp_id.product == 0x140 || - cam->params.pnp_id.product == 0x151) { - cam->params.pnp_id.device_type = DEVICE_STV_676; - } - } - break; - case CPIA2_CMD_GET_ASIC_TYPE: - cam->params.version.asic_id = cmd.buffer.block_data[0]; - cam->params.version.asic_rev = cmd.buffer.block_data[1]; - break; - case CPIA2_CMD_GET_SENSOR: - cam->params.version.sensor_flags = cmd.buffer.block_data[0]; - cam->params.version.sensor_rev = cmd.buffer.block_data[1]; - break; - case CPIA2_CMD_GET_VP_DEVICE: - cam->params.version.vp_device_hi = cmd.buffer.block_data[0]; - cam->params.version.vp_device_lo = cmd.buffer.block_data[1]; - break; - case CPIA2_CMD_GET_VP_GPIO_DATA: - cam->params.vp_params.gpio_data = cmd.buffer.block_data[0]; - break; - case CPIA2_CMD_GET_VP_GPIO_DIRECTION: - cam->params.vp_params.gpio_direction = cmd.buffer.block_data[0]; - break; - case CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION: - cam->params.vc_params.vc_mp_direction =cmd.buffer.block_data[0]; - break; - case CPIA2_CMD_GET_VC_MP_GPIO_DATA: - cam->params.vc_params.vc_mp_data = cmd.buffer.block_data[0]; - break; - case CPIA2_CMD_GET_FLICKER_MODES: - cam->params.flicker_control.cam_register = - cmd.buffer.block_data[0]; - break; - case CPIA2_CMD_GET_WAKEUP: - cam->params.vc_params.wakeup = cmd.buffer.block_data[0]; - break; - case CPIA2_CMD_GET_PW_CONTROL: - cam->params.vc_params.pw_control = cmd.buffer.block_data[0]; - break; - case CPIA2_CMD_GET_SYSTEM_CTRL: - cam->params.camera_state.system_ctrl = cmd.buffer.block_data[0]; - break; - case CPIA2_CMD_GET_VP_SYSTEM_STATE: - cam->params.vp_params.system_state = cmd.buffer.block_data[0]; - break; - case CPIA2_CMD_GET_VP_SYSTEM_CTRL: - cam->params.vp_params.system_ctrl = cmd.buffer.block_data[0]; - break; - case CPIA2_CMD_GET_VP_EXP_MODES: - cam->params.vp_params.exposure_modes = cmd.buffer.block_data[0]; - break; - case CPIA2_CMD_GET_DEVICE_CONFIG: - cam->params.vp_params.device_config = cmd.buffer.block_data[0]; - break; - case CPIA2_CMD_GET_VC_CONTROL: - cam->params.vc_params.vc_control = cmd.buffer.block_data[0]; - break; - case CPIA2_CMD_GET_USER_MODE: - cam->params.vp_params.video_mode = cmd.buffer.block_data[0]; - break; - case CPIA2_CMD_GET_USER_EFFECTS: - cam->params.vp_params.user_effects = cmd.buffer.block_data[0]; - break; - default: - break; - } - return retval; -} - -/****************************************************************************** - * - * cpia2_send_command - * - *****************************************************************************/ - -#define DIR(cmd) ((cmd->direction == TRANSFER_WRITE) ? "Write" : "Read") -#define BINDEX(cmd) (cmd->req_mode & 0x03) - -int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd) -{ - u8 count; - u8 start; - u8 *buffer; - int retval; - - switch (cmd->req_mode & 0x0c) { - case CAMERAACCESS_TYPE_RANDOM: - count = cmd->reg_count * sizeof(struct cpia2_register); - start = 0; - buffer = (u8 *) & cmd->buffer; - if (debugs_on & DEBUG_REG) - DBG("%s Random: Register block %s\n", DIR(cmd), - block_name[BINDEX(cmd)]); - break; - case CAMERAACCESS_TYPE_BLOCK: - count = cmd->reg_count; - start = cmd->start; - buffer = cmd->buffer.block_data; - if (debugs_on & DEBUG_REG) - DBG("%s Block: Register block %s\n", DIR(cmd), - block_name[BINDEX(cmd)]); - break; - case CAMERAACCESS_TYPE_MASK: - count = cmd->reg_count * sizeof(struct cpia2_reg_mask); - start = 0; - buffer = (u8 *) & cmd->buffer; - if (debugs_on & DEBUG_REG) - DBG("%s Mask: Register block %s\n", DIR(cmd), - block_name[BINDEX(cmd)]); - break; - case CAMERAACCESS_TYPE_REPEAT: /* For patch blocks only */ - count = cmd->reg_count; - start = cmd->start; - buffer = cmd->buffer.block_data; - if (debugs_on & DEBUG_REG) - DBG("%s Repeat: Register block %s\n", DIR(cmd), - block_name[BINDEX(cmd)]); - break; - default: - LOG("%s: invalid request mode\n",__func__); - return -EINVAL; - } - - retval = cpia2_usb_transfer_cmd(cam, - buffer, - cmd->req_mode, - start, count, cmd->direction); -#ifdef _CPIA2_DEBUG_ - if (debugs_on & DEBUG_REG) { - int i; - for (i = 0; i < cmd->reg_count; i++) { - if((cmd->req_mode & 0x0c) == CAMERAACCESS_TYPE_BLOCK) - KINFO("%s Block: [0x%02X] = 0x%02X\n", - DIR(cmd), start + i, buffer[i]); - if((cmd->req_mode & 0x0c) == CAMERAACCESS_TYPE_RANDOM) - KINFO("%s Random: [0x%02X] = 0x%02X\n", - DIR(cmd), cmd->buffer.registers[i].index, - cmd->buffer.registers[i].value); - } - } -#endif - - return retval; -}; - -/************* - * Functions to implement camera functionality - *************/ -/****************************************************************************** - * - * cpia2_get_version_info - * - *****************************************************************************/ -static void cpia2_get_version_info(struct camera_data *cam) -{ - cpia2_do_command(cam, CPIA2_CMD_GET_VERSION, TRANSFER_READ, 0); - cpia2_do_command(cam, CPIA2_CMD_GET_PNP_ID, TRANSFER_READ, 0); - cpia2_do_command(cam, CPIA2_CMD_GET_ASIC_TYPE, TRANSFER_READ, 0); - cpia2_do_command(cam, CPIA2_CMD_GET_SENSOR, TRANSFER_READ, 0); - cpia2_do_command(cam, CPIA2_CMD_GET_VP_DEVICE, TRANSFER_READ, 0); -} - -/****************************************************************************** - * - * cpia2_reset_camera - * - * Called at least during the open process, sets up initial params. - *****************************************************************************/ -int cpia2_reset_camera(struct camera_data *cam) -{ - u8 tmp_reg; - int retval = 0; - int target_kb; - int i; - struct cpia2_command cmd; - - /*** - * VC setup - ***/ - retval = configure_sensor(cam, - cam->params.roi.width, - cam->params.roi.height); - if (retval < 0) { - ERR("Couldn't configure sensor, error=%d\n", retval); - return retval; - } - - /* Clear FIFO and route/enable stream block */ - cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC; - cmd.direction = TRANSFER_WRITE; - cmd.reg_count = 2; - cmd.buffer.registers[0].index = CPIA2_VC_ST_CTRL; - cmd.buffer.registers[0].value = CPIA2_VC_ST_CTRL_SRC_VC | - CPIA2_VC_ST_CTRL_DST_USB | CPIA2_VC_ST_CTRL_EOF_DETECT; - cmd.buffer.registers[1].index = CPIA2_VC_ST_CTRL; - cmd.buffer.registers[1].value = CPIA2_VC_ST_CTRL_SRC_VC | - CPIA2_VC_ST_CTRL_DST_USB | - CPIA2_VC_ST_CTRL_EOF_DETECT | CPIA2_VC_ST_CTRL_FIFO_ENABLE; - - cpia2_send_command(cam, &cmd); - - cpia2_set_high_power(cam); - - if (cam->params.pnp_id.device_type == DEVICE_STV_672) { - /* Enable button notification */ - cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_SYSTEM; - cmd.buffer.registers[0].index = CPIA2_SYSTEM_INT_PACKET_CTRL; - cmd.buffer.registers[0].value = - CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_SW_XX; - cmd.reg_count = 1; - cpia2_send_command(cam, &cmd); - } - - schedule_timeout_interruptible(msecs_to_jiffies(100)); - - if (cam->params.pnp_id.device_type == DEVICE_STV_672) - retval = apply_vp_patch(cam); - - /* wait for vp to go to sleep */ - schedule_timeout_interruptible(msecs_to_jiffies(100)); - - /*** - * If this is a 676, apply VP5 fixes before we start streaming - ***/ - if (cam->params.pnp_id.device_type == DEVICE_STV_676) { - cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VP; - - /* The following writes improve the picture */ - cmd.buffer.registers[0].index = CPIA2_VP5_MYBLACK_LEVEL; - cmd.buffer.registers[0].value = 0; /* reduce from the default - * rec 601 pedestal of 16 */ - cmd.buffer.registers[1].index = CPIA2_VP5_MCYRANGE; - cmd.buffer.registers[1].value = 0x92; /* increase from 100% to - * (256/256 - 31) to fill - * available range */ - cmd.buffer.registers[2].index = CPIA2_VP5_MYCEILING; - cmd.buffer.registers[2].value = 0xFF; /* Increase from the - * default rec 601 ceiling - * of 240 */ - cmd.buffer.registers[3].index = CPIA2_VP5_MCUVSATURATION; - cmd.buffer.registers[3].value = 0xFF; /* Increase from the rec - * 601 100% level (128) - * to 145-192 */ - cmd.buffer.registers[4].index = CPIA2_VP5_ANTIFLKRSETUP; - cmd.buffer.registers[4].value = 0x80; /* Inhibit the - * anti-flicker */ - - /* The following 4 writes are a fix to allow QVGA to work at 30 fps */ - cmd.buffer.registers[5].index = CPIA2_VP_RAM_ADDR_H; - cmd.buffer.registers[5].value = 0x01; - cmd.buffer.registers[6].index = CPIA2_VP_RAM_ADDR_L; - cmd.buffer.registers[6].value = 0xE3; - cmd.buffer.registers[7].index = CPIA2_VP_RAM_DATA; - cmd.buffer.registers[7].value = 0x02; - cmd.buffer.registers[8].index = CPIA2_VP_RAM_DATA; - cmd.buffer.registers[8].value = 0xFC; - - cmd.direction = TRANSFER_WRITE; - cmd.reg_count = 9; - - cpia2_send_command(cam, &cmd); - } - - /* Activate all settings and start the data stream */ - /* Set user mode */ - set_default_user_mode(cam); - - /* Give VP time to wake up */ - schedule_timeout_interruptible(msecs_to_jiffies(100)); - - set_all_properties(cam); - - cpia2_do_command(cam, CPIA2_CMD_GET_USER_MODE, TRANSFER_READ, 0); - DBG("After SetAllProperties(cam), user mode is 0x%0X\n", - cam->params.vp_params.video_mode); - - /*** - * Set audio regulator off. This and the code to set the compresison - * state are too complex to form a CPIA2_CMD_, and seem to be somewhat - * intertwined. This stuff came straight from the windows driver. - ***/ - /* Turn AutoExposure off in VP and enable the serial bridge to the sensor */ - cpia2_do_command(cam, CPIA2_CMD_GET_VP_SYSTEM_CTRL, TRANSFER_READ, 0); - tmp_reg = cam->params.vp_params.system_ctrl; - cmd.buffer.registers[0].value = tmp_reg & - (tmp_reg & (CPIA2_VP_SYSTEMCTRL_HK_CONTROL ^ 0xFF)); - - cpia2_do_command(cam, CPIA2_CMD_GET_DEVICE_CONFIG, TRANSFER_READ, 0); - cmd.buffer.registers[1].value = cam->params.vp_params.device_config | - CPIA2_VP_DEVICE_CONFIG_SERIAL_BRIDGE; - cmd.buffer.registers[0].index = CPIA2_VP_SYSTEMCTRL; - cmd.buffer.registers[1].index = CPIA2_VP_DEVICE_CONFIG; - cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VP; - cmd.reg_count = 2; - cmd.direction = TRANSFER_WRITE; - cmd.start = 0; - cpia2_send_command(cam, &cmd); - - /* Set the correct I2C address in the CPiA-2 system register */ - cpia2_do_command(cam, - CPIA2_CMD_SET_SERIAL_ADDR, - TRANSFER_WRITE, - CPIA2_SYSTEM_VP_SERIAL_ADDR_SENSOR); - - /* Now have sensor access - set bit to turn the audio regulator off */ - cpia2_do_command(cam, - CPIA2_CMD_SET_SENSOR_CR1, - TRANSFER_WRITE, CPIA2_SENSOR_CR1_DOWN_AUDIO_REGULATOR); - - /* Set the correct I2C address in the CPiA-2 system register */ - if (cam->params.pnp_id.device_type == DEVICE_STV_672) - cpia2_do_command(cam, - CPIA2_CMD_SET_SERIAL_ADDR, - TRANSFER_WRITE, - CPIA2_SYSTEM_VP_SERIAL_ADDR_VP); // 0x88 - else - cpia2_do_command(cam, - CPIA2_CMD_SET_SERIAL_ADDR, - TRANSFER_WRITE, - CPIA2_SYSTEM_VP_SERIAL_ADDR_676_VP); // 0x8a - - /* increase signal drive strength */ - if (cam->params.pnp_id.device_type == DEVICE_STV_676) - cpia2_do_command(cam, - CPIA2_CMD_SET_VP_EXP_MODES, - TRANSFER_WRITE, - CPIA2_VP_EXPOSURE_MODES_COMPILE_EXP); - - /* Start autoexposure */ - cpia2_do_command(cam, CPIA2_CMD_GET_DEVICE_CONFIG, TRANSFER_READ, 0); - cmd.buffer.registers[0].value = cam->params.vp_params.device_config & - (CPIA2_VP_DEVICE_CONFIG_SERIAL_BRIDGE ^ 0xFF); - - cpia2_do_command(cam, CPIA2_CMD_GET_VP_SYSTEM_CTRL, TRANSFER_READ, 0); - cmd.buffer.registers[1].value = - cam->params.vp_params.system_ctrl | CPIA2_VP_SYSTEMCTRL_HK_CONTROL; - - cmd.buffer.registers[0].index = CPIA2_VP_DEVICE_CONFIG; - cmd.buffer.registers[1].index = CPIA2_VP_SYSTEMCTRL; - cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VP; - cmd.reg_count = 2; - cmd.direction = TRANSFER_WRITE; - - cpia2_send_command(cam, &cmd); - - /* Set compression state */ - cpia2_do_command(cam, CPIA2_CMD_GET_VC_CONTROL, TRANSFER_READ, 0); - if (cam->params.compression.inhibit_htables) { - tmp_reg = cam->params.vc_params.vc_control | - CPIA2_VC_VC_CTRL_INHIBIT_H_TABLES; - } else { - tmp_reg = cam->params.vc_params.vc_control & - ~CPIA2_VC_VC_CTRL_INHIBIT_H_TABLES; - } - cpia2_do_command(cam, CPIA2_CMD_SET_VC_CONTROL, TRANSFER_WRITE,tmp_reg); - - /* Set target size (kb) on vc - This is a heuristic based on the quality parameter and the raw - framesize in kB divided by 16 (the compression factor when the - quality is 100%) */ - target_kb = (cam->width * cam->height * 2 / 16384) * - cam->params.vc_params.quality / 100; - if (target_kb < 1) - target_kb = 1; - cpia2_do_command(cam, CPIA2_CMD_SET_TARGET_KB, - TRANSFER_WRITE, target_kb); - - /* Wiggle VC Reset */ - /*** - * First read and wait a bit. - ***/ - for (i = 0; i < 50; i++) { - cpia2_do_command(cam, CPIA2_CMD_GET_PW_CONTROL, - TRANSFER_READ, 0); - } - - tmp_reg = cam->params.vc_params.pw_control; - tmp_reg &= ~CPIA2_VC_PW_CTRL_VC_RESET_N; - - cpia2_do_command(cam, CPIA2_CMD_SET_PW_CONTROL, TRANSFER_WRITE,tmp_reg); - - tmp_reg |= CPIA2_VC_PW_CTRL_VC_RESET_N; - cpia2_do_command(cam, CPIA2_CMD_SET_PW_CONTROL, TRANSFER_WRITE,tmp_reg); - - cpia2_do_command(cam, CPIA2_CMD_SET_DEF_JPEG_OPT, TRANSFER_WRITE, 0); - - cpia2_do_command(cam, CPIA2_CMD_GET_USER_MODE, TRANSFER_READ, 0); - DBG("After VC RESET, user mode is 0x%0X\n", - cam->params.vp_params.video_mode); - - return retval; -} - -/****************************************************************************** - * - * cpia2_set_high_power - * - *****************************************************************************/ -static int cpia2_set_high_power(struct camera_data *cam) -{ - int i; - for (i = 0; i <= 50; i++) { - /* Read system status */ - cpia2_do_command(cam,CPIA2_CMD_GET_SYSTEM_CTRL,TRANSFER_READ,0); - - /* If there is an error, clear it */ - if(cam->params.camera_state.system_ctrl & - CPIA2_SYSTEM_CONTROL_V2W_ERR) - cpia2_do_command(cam, CPIA2_CMD_CLEAR_V2W_ERR, - TRANSFER_WRITE, 0); - - /* Try to set high power mode */ - cpia2_do_command(cam, CPIA2_CMD_SET_SYSTEM_CTRL, - TRANSFER_WRITE, 1); - - /* Try to read something in VP to check if everything is awake */ - cpia2_do_command(cam, CPIA2_CMD_GET_VP_SYSTEM_STATE, - TRANSFER_READ, 0); - if (cam->params.vp_params.system_state & - CPIA2_VP_SYSTEMSTATE_HK_ALIVE) { - break; - } else if (i == 50) { - cam->params.camera_state.power_mode = LO_POWER_MODE; - ERR("Camera did not wake up\n"); - return -EIO; - } - } - - DBG("System now in high power state\n"); - cam->params.camera_state.power_mode = HI_POWER_MODE; - return 0; -} - -/****************************************************************************** - * - * cpia2_set_low_power - * - *****************************************************************************/ -int cpia2_set_low_power(struct camera_data *cam) -{ - cam->params.camera_state.power_mode = LO_POWER_MODE; - cpia2_do_command(cam, CPIA2_CMD_SET_SYSTEM_CTRL, TRANSFER_WRITE, 0); - return 0; -} - -/****************************************************************************** - * - * apply_vp_patch - * - *****************************************************************************/ -static int cpia2_send_onebyte_command(struct camera_data *cam, - struct cpia2_command *cmd, - u8 start, u8 datum) -{ - cmd->buffer.block_data[0] = datum; - cmd->start = start; - cmd->reg_count = 1; - return cpia2_send_command(cam, cmd); -} - -static int apply_vp_patch(struct camera_data *cam) -{ - const struct firmware *fw; - const char fw_name[] = FIRMWARE; - int i, ret; - struct cpia2_command cmd; - - ret = request_firmware(&fw, fw_name, &cam->dev->dev); - if (ret) { - printk(KERN_ERR "cpia2: failed to load VP patch \"%s\"\n", - fw_name); - return ret; - } - - cmd.req_mode = CAMERAACCESS_TYPE_REPEAT | CAMERAACCESS_VP; - cmd.direction = TRANSFER_WRITE; - - /* First send the start address... */ - cpia2_send_onebyte_command(cam, &cmd, 0x0A, fw->data[0]); /* hi */ - cpia2_send_onebyte_command(cam, &cmd, 0x0B, fw->data[1]); /* lo */ - - /* ... followed by the data payload */ - for (i = 2; i < fw->size; i += 64) { - cmd.start = 0x0C; /* Data */ - cmd.reg_count = min_t(int, 64, fw->size - i); - memcpy(cmd.buffer.block_data, &fw->data[i], cmd.reg_count); - cpia2_send_command(cam, &cmd); - } - - /* Next send the start address... */ - cpia2_send_onebyte_command(cam, &cmd, 0x0A, fw->data[0]); /* hi */ - cpia2_send_onebyte_command(cam, &cmd, 0x0B, fw->data[1]); /* lo */ - - /* ... followed by the 'goto' command */ - cpia2_send_onebyte_command(cam, &cmd, 0x0D, 1); - - release_firmware(fw); - return 0; -} - -/****************************************************************************** - * - * set_default_user_mode - * - *****************************************************************************/ -static int set_default_user_mode(struct camera_data *cam) -{ - unsigned char user_mode; - unsigned char frame_rate; - int width = cam->params.roi.width; - int height = cam->params.roi.height; - - switch (cam->params.version.sensor_flags) { - case CPIA2_VP_SENSOR_FLAGS_404: - case CPIA2_VP_SENSOR_FLAGS_407: - case CPIA2_VP_SENSOR_FLAGS_409: - case CPIA2_VP_SENSOR_FLAGS_410: - if ((width > STV_IMAGE_QCIF_COLS) - || (height > STV_IMAGE_QCIF_ROWS)) { - user_mode = CPIA2_VP_USER_MODE_CIF; - } else { - user_mode = CPIA2_VP_USER_MODE_QCIFDS; - } - frame_rate = CPIA2_VP_FRAMERATE_30; - break; - case CPIA2_VP_SENSOR_FLAGS_500: - if ((width > STV_IMAGE_CIF_COLS) - || (height > STV_IMAGE_CIF_ROWS)) { - user_mode = CPIA2_VP_USER_MODE_VGA; - } else { - user_mode = CPIA2_VP_USER_MODE_QVGADS; - } - if (cam->params.pnp_id.device_type == DEVICE_STV_672) - frame_rate = CPIA2_VP_FRAMERATE_15; - else - frame_rate = CPIA2_VP_FRAMERATE_30; - break; - default: - LOG("%s: Invalid sensor flag value 0x%0X\n",__func__, - cam->params.version.sensor_flags); - return -EINVAL; - } - - DBG("Sensor flag = 0x%0x, user mode = 0x%0x, frame rate = 0x%X\n", - cam->params.version.sensor_flags, user_mode, frame_rate); - cpia2_do_command(cam, CPIA2_CMD_SET_USER_MODE, TRANSFER_WRITE, - user_mode); - if(cam->params.vp_params.frame_rate > 0 && - frame_rate > cam->params.vp_params.frame_rate) - frame_rate = cam->params.vp_params.frame_rate; - - cpia2_set_fps(cam, frame_rate); - -// if (cam->params.pnp_id.device_type == DEVICE_STV_676) -// cpia2_do_command(cam, -// CPIA2_CMD_SET_VP_SYSTEM_CTRL, -// TRANSFER_WRITE, -// CPIA2_VP_SYSTEMCTRL_HK_CONTROL | -// CPIA2_VP_SYSTEMCTRL_POWER_CONTROL); - - return 0; -} - -/****************************************************************************** - * - * cpia2_match_video_size - * - * return the best match, where 'best' is as always - * the largest that is not bigger than what is requested. - *****************************************************************************/ -int cpia2_match_video_size(int width, int height) -{ - if (width >= STV_IMAGE_VGA_COLS && height >= STV_IMAGE_VGA_ROWS) - return VIDEOSIZE_VGA; - - if (width >= STV_IMAGE_CIF_COLS && height >= STV_IMAGE_CIF_ROWS) - return VIDEOSIZE_CIF; - - if (width >= STV_IMAGE_QVGA_COLS && height >= STV_IMAGE_QVGA_ROWS) - return VIDEOSIZE_QVGA; - - if (width >= 288 && height >= 216) - return VIDEOSIZE_288_216; - - if (width >= 256 && height >= 192) - return VIDEOSIZE_256_192; - - if (width >= 224 && height >= 168) - return VIDEOSIZE_224_168; - - if (width >= 192 && height >= 144) - return VIDEOSIZE_192_144; - - if (width >= STV_IMAGE_QCIF_COLS && height >= STV_IMAGE_QCIF_ROWS) - return VIDEOSIZE_QCIF; - - return -1; -} - -/****************************************************************************** - * - * SetVideoSize - * - *****************************************************************************/ -static int set_vw_size(struct camera_data *cam, int size) -{ - int retval = 0; - - cam->params.vp_params.video_size = size; - - switch (size) { - case VIDEOSIZE_VGA: - DBG("Setting size to VGA\n"); - cam->params.roi.width = STV_IMAGE_VGA_COLS; - cam->params.roi.height = STV_IMAGE_VGA_ROWS; - cam->width = STV_IMAGE_VGA_COLS; - cam->height = STV_IMAGE_VGA_ROWS; - break; - case VIDEOSIZE_CIF: - DBG("Setting size to CIF\n"); - cam->params.roi.width = STV_IMAGE_CIF_COLS; - cam->params.roi.height = STV_IMAGE_CIF_ROWS; - cam->width = STV_IMAGE_CIF_COLS; - cam->height = STV_IMAGE_CIF_ROWS; - break; - case VIDEOSIZE_QVGA: - DBG("Setting size to QVGA\n"); - cam->params.roi.width = STV_IMAGE_QVGA_COLS; - cam->params.roi.height = STV_IMAGE_QVGA_ROWS; - cam->width = STV_IMAGE_QVGA_COLS; - cam->height = STV_IMAGE_QVGA_ROWS; - break; - case VIDEOSIZE_288_216: - cam->params.roi.width = 288; - cam->params.roi.height = 216; - cam->width = 288; - cam->height = 216; - break; - case VIDEOSIZE_256_192: - cam->width = 256; - cam->height = 192; - cam->params.roi.width = 256; - cam->params.roi.height = 192; - break; - case VIDEOSIZE_224_168: - cam->width = 224; - cam->height = 168; - cam->params.roi.width = 224; - cam->params.roi.height = 168; - break; - case VIDEOSIZE_192_144: - cam->width = 192; - cam->height = 144; - cam->params.roi.width = 192; - cam->params.roi.height = 144; - break; - case VIDEOSIZE_QCIF: - DBG("Setting size to QCIF\n"); - cam->params.roi.width = STV_IMAGE_QCIF_COLS; - cam->params.roi.height = STV_IMAGE_QCIF_ROWS; - cam->width = STV_IMAGE_QCIF_COLS; - cam->height = STV_IMAGE_QCIF_ROWS; - break; - default: - retval = -EINVAL; - } - return retval; -} - -/****************************************************************************** - * - * configure_sensor - * - *****************************************************************************/ -static int configure_sensor(struct camera_data *cam, - int req_width, int req_height) -{ - int retval; - - switch (cam->params.version.sensor_flags) { - case CPIA2_VP_SENSOR_FLAGS_404: - case CPIA2_VP_SENSOR_FLAGS_407: - case CPIA2_VP_SENSOR_FLAGS_409: - case CPIA2_VP_SENSOR_FLAGS_410: - retval = config_sensor_410(cam, req_width, req_height); - break; - case CPIA2_VP_SENSOR_FLAGS_500: - retval = config_sensor_500(cam, req_width, req_height); - break; - default: - return -EINVAL; - } - - return retval; -} - -/****************************************************************************** - * - * config_sensor_410 - * - *****************************************************************************/ -static int config_sensor_410(struct camera_data *cam, - int req_width, int req_height) -{ - struct cpia2_command cmd; - int i = 0; - int image_size; - int image_type; - int width = req_width; - int height = req_height; - - /*** - * Make sure size doesn't exceed CIF. - ***/ - if (width > STV_IMAGE_CIF_COLS) - width = STV_IMAGE_CIF_COLS; - if (height > STV_IMAGE_CIF_ROWS) - height = STV_IMAGE_CIF_ROWS; - - image_size = cpia2_match_video_size(width, height); - - DBG("Config 410: width = %d, height = %d\n", width, height); - DBG("Image size returned is %d\n", image_size); - if (image_size >= 0) { - set_vw_size(cam, image_size); - width = cam->params.roi.width; - height = cam->params.roi.height; - - DBG("After set_vw_size(), width = %d, height = %d\n", - width, height); - if (width <= 176 && height <= 144) { - DBG("image type = VIDEOSIZE_QCIF\n"); - image_type = VIDEOSIZE_QCIF; - } - else if (width <= 320 && height <= 240) { - DBG("image type = VIDEOSIZE_QVGA\n"); - image_type = VIDEOSIZE_QVGA; - } - else { - DBG("image type = VIDEOSIZE_CIF\n"); - image_type = VIDEOSIZE_CIF; - } - } else { - ERR("ConfigSensor410 failed\n"); - return -EINVAL; - } - - cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC; - cmd.direction = TRANSFER_WRITE; - - /* VC Format */ - cmd.buffer.registers[i].index = CPIA2_VC_VC_FORMAT; - if (image_type == VIDEOSIZE_CIF) { - cmd.buffer.registers[i++].value = - (u8) (CPIA2_VC_VC_FORMAT_UFIRST | - CPIA2_VC_VC_FORMAT_SHORTLINE); - } else { - cmd.buffer.registers[i++].value = - (u8) CPIA2_VC_VC_FORMAT_UFIRST; - } - - /* VC Clocks */ - cmd.buffer.registers[i].index = CPIA2_VC_VC_CLOCKS; - if (image_type == VIDEOSIZE_QCIF) { - if (cam->params.pnp_id.device_type == DEVICE_STV_672) { - cmd.buffer.registers[i++].value= - (u8)(CPIA2_VC_VC_672_CLOCKS_CIF_DIV_BY_3 | - CPIA2_VC_VC_672_CLOCKS_SCALING | - CPIA2_VC_VC_CLOCKS_LOGDIV2); - DBG("VC_Clocks (0xc4) should be B\n"); - } - else { - cmd.buffer.registers[i++].value= - (u8)(CPIA2_VC_VC_676_CLOCKS_CIF_DIV_BY_3 | - CPIA2_VC_VC_CLOCKS_LOGDIV2); - } - } else { - if (cam->params.pnp_id.device_type == DEVICE_STV_672) { - cmd.buffer.registers[i++].value = - (u8) (CPIA2_VC_VC_672_CLOCKS_CIF_DIV_BY_3 | - CPIA2_VC_VC_CLOCKS_LOGDIV0); - } - else { - cmd.buffer.registers[i++].value = - (u8) (CPIA2_VC_VC_676_CLOCKS_CIF_DIV_BY_3 | - CPIA2_VC_VC_676_CLOCKS_SCALING | - CPIA2_VC_VC_CLOCKS_LOGDIV0); - } - } - DBG("VC_Clocks (0xc4) = 0x%0X\n", cmd.buffer.registers[i-1].value); - - /* Input reqWidth from VC */ - cmd.buffer.registers[i].index = CPIA2_VC_VC_IHSIZE_LO; - if (image_type == VIDEOSIZE_QCIF) - cmd.buffer.registers[i++].value = - (u8) (STV_IMAGE_QCIF_COLS / 4); - else - cmd.buffer.registers[i++].value = - (u8) (STV_IMAGE_CIF_COLS / 4); - - /* Timings */ - cmd.buffer.registers[i].index = CPIA2_VC_VC_XLIM_HI; - if (image_type == VIDEOSIZE_QCIF) - cmd.buffer.registers[i++].value = (u8) 0; - else - cmd.buffer.registers[i++].value = (u8) 1; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_XLIM_LO; - if (image_type == VIDEOSIZE_QCIF) - cmd.buffer.registers[i++].value = (u8) 208; - else - cmd.buffer.registers[i++].value = (u8) 160; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_YLIM_HI; - if (image_type == VIDEOSIZE_QCIF) - cmd.buffer.registers[i++].value = (u8) 0; - else - cmd.buffer.registers[i++].value = (u8) 1; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_YLIM_LO; - if (image_type == VIDEOSIZE_QCIF) - cmd.buffer.registers[i++].value = (u8) 160; - else - cmd.buffer.registers[i++].value = (u8) 64; - - /* Output Image Size */ - cmd.buffer.registers[i].index = CPIA2_VC_VC_OHSIZE; - cmd.buffer.registers[i++].value = cam->params.roi.width / 4; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_OVSIZE; - cmd.buffer.registers[i++].value = cam->params.roi.height / 4; - - /* Cropping */ - cmd.buffer.registers[i].index = CPIA2_VC_VC_HCROP; - if (image_type == VIDEOSIZE_QCIF) - cmd.buffer.registers[i++].value = - (u8) (((STV_IMAGE_QCIF_COLS / 4) - (width / 4)) / 2); - else - cmd.buffer.registers[i++].value = - (u8) (((STV_IMAGE_CIF_COLS / 4) - (width / 4)) / 2); - - cmd.buffer.registers[i].index = CPIA2_VC_VC_VCROP; - if (image_type == VIDEOSIZE_QCIF) - cmd.buffer.registers[i++].value = - (u8) (((STV_IMAGE_QCIF_ROWS / 4) - (height / 4)) / 2); - else - cmd.buffer.registers[i++].value = - (u8) (((STV_IMAGE_CIF_ROWS / 4) - (height / 4)) / 2); - - /* Scaling registers (defaults) */ - cmd.buffer.registers[i].index = CPIA2_VC_VC_HPHASE; - cmd.buffer.registers[i++].value = (u8) 0; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_VPHASE; - cmd.buffer.registers[i++].value = (u8) 0; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_HISPAN; - cmd.buffer.registers[i++].value = (u8) 31; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_VISPAN; - cmd.buffer.registers[i++].value = (u8) 31; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_HICROP; - cmd.buffer.registers[i++].value = (u8) 0; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_VICROP; - cmd.buffer.registers[i++].value = (u8) 0; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_HFRACT; - cmd.buffer.registers[i++].value = (u8) 0x81; /* = 8/1 = 8 (HIBYTE/LOBYTE) */ - - cmd.buffer.registers[i].index = CPIA2_VC_VC_VFRACT; - cmd.buffer.registers[i++].value = (u8) 0x81; /* = 8/1 = 8 (HIBYTE/LOBYTE) */ - - cmd.reg_count = i; - - cpia2_send_command(cam, &cmd); - - return i; -} - - -/****************************************************************************** - * - * config_sensor_500(cam) - * - *****************************************************************************/ -static int config_sensor_500(struct camera_data *cam, - int req_width, int req_height) -{ - struct cpia2_command cmd; - int i = 0; - int image_size = VIDEOSIZE_CIF; - int image_type = VIDEOSIZE_VGA; - int width = req_width; - int height = req_height; - unsigned int device = cam->params.pnp_id.device_type; - - image_size = cpia2_match_video_size(width, height); - - if (width > STV_IMAGE_CIF_COLS || height > STV_IMAGE_CIF_ROWS) - image_type = VIDEOSIZE_VGA; - else if (width > STV_IMAGE_QVGA_COLS || height > STV_IMAGE_QVGA_ROWS) - image_type = VIDEOSIZE_CIF; - else if (width > STV_IMAGE_QCIF_COLS || height > STV_IMAGE_QCIF_ROWS) - image_type = VIDEOSIZE_QVGA; - else - image_type = VIDEOSIZE_QCIF; - - if (image_size >= 0) { - set_vw_size(cam, image_size); - width = cam->params.roi.width; - height = cam->params.roi.height; - } else { - ERR("ConfigSensor500 failed\n"); - return -EINVAL; - } - - DBG("image_size = %d, width = %d, height = %d, type = %d\n", - image_size, width, height, image_type); - - cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC; - cmd.direction = TRANSFER_WRITE; - i = 0; - - /* VC Format */ - cmd.buffer.registers[i].index = CPIA2_VC_VC_FORMAT; - cmd.buffer.registers[i].value = (u8) CPIA2_VC_VC_FORMAT_UFIRST; - if (image_type == VIDEOSIZE_QCIF) - cmd.buffer.registers[i].value |= (u8) CPIA2_VC_VC_FORMAT_DECIMATING; - i++; - - /* VC Clocks */ - cmd.buffer.registers[i].index = CPIA2_VC_VC_CLOCKS; - if (device == DEVICE_STV_672) { - if (image_type == VIDEOSIZE_VGA) - cmd.buffer.registers[i].value = - (u8)CPIA2_VC_VC_CLOCKS_LOGDIV1; - else - cmd.buffer.registers[i].value = - (u8)(CPIA2_VC_VC_672_CLOCKS_SCALING | - CPIA2_VC_VC_CLOCKS_LOGDIV3); - } else { - if (image_type == VIDEOSIZE_VGA) - cmd.buffer.registers[i].value = - (u8)CPIA2_VC_VC_CLOCKS_LOGDIV0; - else - cmd.buffer.registers[i].value = - (u8)(CPIA2_VC_VC_676_CLOCKS_SCALING | - CPIA2_VC_VC_CLOCKS_LOGDIV2); - } - i++; - - DBG("VC_CLOCKS = 0x%X\n", cmd.buffer.registers[i-1].value); - - /* Input width from VP */ - cmd.buffer.registers[i].index = CPIA2_VC_VC_IHSIZE_LO; - if (image_type == VIDEOSIZE_VGA) - cmd.buffer.registers[i].value = - (u8) (STV_IMAGE_VGA_COLS / 4); - else - cmd.buffer.registers[i].value = - (u8) (STV_IMAGE_QVGA_COLS / 4); - i++; - DBG("Input width = %d\n", cmd.buffer.registers[i-1].value); - - /* Timings */ - cmd.buffer.registers[i].index = CPIA2_VC_VC_XLIM_HI; - if (image_type == VIDEOSIZE_VGA) - cmd.buffer.registers[i++].value = (u8) 2; - else - cmd.buffer.registers[i++].value = (u8) 1; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_XLIM_LO; - if (image_type == VIDEOSIZE_VGA) - cmd.buffer.registers[i++].value = (u8) 250; - else if (image_type == VIDEOSIZE_QVGA) - cmd.buffer.registers[i++].value = (u8) 125; - else - cmd.buffer.registers[i++].value = (u8) 160; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_YLIM_HI; - if (image_type == VIDEOSIZE_VGA) - cmd.buffer.registers[i++].value = (u8) 2; - else - cmd.buffer.registers[i++].value = (u8) 1; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_YLIM_LO; - if (image_type == VIDEOSIZE_VGA) - cmd.buffer.registers[i++].value = (u8) 12; - else if (image_type == VIDEOSIZE_QVGA) - cmd.buffer.registers[i++].value = (u8) 64; - else - cmd.buffer.registers[i++].value = (u8) 6; - - /* Output Image Size */ - cmd.buffer.registers[i].index = CPIA2_VC_VC_OHSIZE; - if (image_type == VIDEOSIZE_QCIF) - cmd.buffer.registers[i++].value = STV_IMAGE_CIF_COLS / 4; - else - cmd.buffer.registers[i++].value = width / 4; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_OVSIZE; - if (image_type == VIDEOSIZE_QCIF) - cmd.buffer.registers[i++].value = STV_IMAGE_CIF_ROWS / 4; - else - cmd.buffer.registers[i++].value = height / 4; - - /* Cropping */ - cmd.buffer.registers[i].index = CPIA2_VC_VC_HCROP; - if (image_type == VIDEOSIZE_VGA) - cmd.buffer.registers[i++].value = - (u8) (((STV_IMAGE_VGA_COLS / 4) - (width / 4)) / 2); - else if (image_type == VIDEOSIZE_QVGA) - cmd.buffer.registers[i++].value = - (u8) (((STV_IMAGE_QVGA_COLS / 4) - (width / 4)) / 2); - else if (image_type == VIDEOSIZE_CIF) - cmd.buffer.registers[i++].value = - (u8) (((STV_IMAGE_CIF_COLS / 4) - (width / 4)) / 2); - else /*if (image_type == VIDEOSIZE_QCIF)*/ - cmd.buffer.registers[i++].value = - (u8) (((STV_IMAGE_QCIF_COLS / 4) - (width / 4)) / 2); - - cmd.buffer.registers[i].index = CPIA2_VC_VC_VCROP; - if (image_type == VIDEOSIZE_VGA) - cmd.buffer.registers[i++].value = - (u8) (((STV_IMAGE_VGA_ROWS / 4) - (height / 4)) / 2); - else if (image_type == VIDEOSIZE_QVGA) - cmd.buffer.registers[i++].value = - (u8) (((STV_IMAGE_QVGA_ROWS / 4) - (height / 4)) / 2); - else if (image_type == VIDEOSIZE_CIF) - cmd.buffer.registers[i++].value = - (u8) (((STV_IMAGE_CIF_ROWS / 4) - (height / 4)) / 2); - else /*if (image_type == VIDEOSIZE_QCIF)*/ - cmd.buffer.registers[i++].value = - (u8) (((STV_IMAGE_QCIF_ROWS / 4) - (height / 4)) / 2); - - /* Scaling registers (defaults) */ - cmd.buffer.registers[i].index = CPIA2_VC_VC_HPHASE; - if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF) - cmd.buffer.registers[i++].value = (u8) 36; - else - cmd.buffer.registers[i++].value = (u8) 0; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_VPHASE; - if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF) - cmd.buffer.registers[i++].value = (u8) 32; - else - cmd.buffer.registers[i++].value = (u8) 0; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_HISPAN; - if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF) - cmd.buffer.registers[i++].value = (u8) 26; - else - cmd.buffer.registers[i++].value = (u8) 31; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_VISPAN; - if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF) - cmd.buffer.registers[i++].value = (u8) 21; - else - cmd.buffer.registers[i++].value = (u8) 31; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_HICROP; - cmd.buffer.registers[i++].value = (u8) 0; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_VICROP; - cmd.buffer.registers[i++].value = (u8) 0; - - cmd.buffer.registers[i].index = CPIA2_VC_VC_HFRACT; - if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF) - cmd.buffer.registers[i++].value = (u8) 0x2B; /* 2/11 */ - else - cmd.buffer.registers[i++].value = (u8) 0x81; /* 8/1 */ - - cmd.buffer.registers[i].index = CPIA2_VC_VC_VFRACT; - if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF) - cmd.buffer.registers[i++].value = (u8) 0x13; /* 1/3 */ - else - cmd.buffer.registers[i++].value = (u8) 0x81; /* 8/1 */ - - cmd.reg_count = i; - - cpia2_send_command(cam, &cmd); - - return i; -} - - -/****************************************************************************** - * - * setallproperties - * - * This sets all user changeable properties to the values in cam->params. - *****************************************************************************/ -static int set_all_properties(struct camera_data *cam) -{ - /** - * Don't set target_kb here, it will be set later. - * framerate and user_mode were already set (set_default_user_mode). - **/ - - cpia2_usb_change_streaming_alternate(cam, - cam->params.camera_state.stream_mode); - - cpia2_do_command(cam, - CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION, - TRANSFER_WRITE, cam->params.vp_params.gpio_direction); - cpia2_do_command(cam, CPIA2_CMD_SET_VC_MP_GPIO_DATA, TRANSFER_WRITE, - cam->params.vp_params.gpio_data); - - v4l2_ctrl_handler_setup(&cam->hdl); - - wake_system(cam); - - set_lowlight_boost(cam); - - return 0; -} - -/****************************************************************************** - * - * cpia2_save_camera_state - * - *****************************************************************************/ -void cpia2_save_camera_state(struct camera_data *cam) -{ - cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS, TRANSFER_READ, 0); - cpia2_do_command(cam, CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION, TRANSFER_READ, - 0); - cpia2_do_command(cam, CPIA2_CMD_GET_VC_MP_GPIO_DATA, TRANSFER_READ, 0); - /* Don't get framerate or target_kb. Trust the values we already have */ -} - - -/****************************************************************************** - * - * cpia2_set_flicker_mode - * - *****************************************************************************/ -int cpia2_set_flicker_mode(struct camera_data *cam, int mode) -{ - unsigned char cam_reg; - int err = 0; - - if(cam->params.pnp_id.device_type != DEVICE_STV_672) - return -EINVAL; - - /* Set the appropriate bits in FLICKER_MODES, preserving the rest */ - if((err = cpia2_do_command(cam, CPIA2_CMD_GET_FLICKER_MODES, - TRANSFER_READ, 0))) - return err; - cam_reg = cam->params.flicker_control.cam_register; - - switch(mode) { - case NEVER_FLICKER: - cam_reg |= CPIA2_VP_FLICKER_MODES_NEVER_FLICKER; - cam_reg &= ~CPIA2_VP_FLICKER_MODES_50HZ; - break; - case FLICKER_60: - cam_reg &= ~CPIA2_VP_FLICKER_MODES_NEVER_FLICKER; - cam_reg &= ~CPIA2_VP_FLICKER_MODES_50HZ; - break; - case FLICKER_50: - cam_reg &= ~CPIA2_VP_FLICKER_MODES_NEVER_FLICKER; - cam_reg |= CPIA2_VP_FLICKER_MODES_50HZ; - break; - default: - return -EINVAL; - } - - if((err = cpia2_do_command(cam, CPIA2_CMD_SET_FLICKER_MODES, - TRANSFER_WRITE, cam_reg))) - return err; - - /* Set the appropriate bits in EXP_MODES, preserving the rest */ - if((err = cpia2_do_command(cam, CPIA2_CMD_GET_VP_EXP_MODES, - TRANSFER_READ, 0))) - return err; - cam_reg = cam->params.vp_params.exposure_modes; - - if (mode == NEVER_FLICKER) { - cam_reg |= CPIA2_VP_EXPOSURE_MODES_INHIBIT_FLICKER; - } else { - cam_reg &= ~CPIA2_VP_EXPOSURE_MODES_INHIBIT_FLICKER; - } - - if((err = cpia2_do_command(cam, CPIA2_CMD_SET_VP_EXP_MODES, - TRANSFER_WRITE, cam_reg))) - return err; - - if((err = cpia2_do_command(cam, CPIA2_CMD_REHASH_VP4, - TRANSFER_WRITE, 1))) - return err; - - switch(mode) { - case NEVER_FLICKER: - case FLICKER_60: - case FLICKER_50: - cam->params.flicker_control.flicker_mode_req = mode; - break; - default: - err = -EINVAL; - } - - return err; -} - -/****************************************************************************** - * - * cpia2_set_property_flip - * - *****************************************************************************/ -void cpia2_set_property_flip(struct camera_data *cam, int prop_val) -{ - unsigned char cam_reg; - - cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS, TRANSFER_READ, 0); - cam_reg = cam->params.vp_params.user_effects; - - if (prop_val) - { - cam_reg |= CPIA2_VP_USER_EFFECTS_FLIP; - } - else - { - cam_reg &= ~CPIA2_VP_USER_EFFECTS_FLIP; - } - cam->params.vp_params.user_effects = cam_reg; - cpia2_do_command(cam, CPIA2_CMD_SET_USER_EFFECTS, TRANSFER_WRITE, - cam_reg); -} - -/****************************************************************************** - * - * cpia2_set_property_mirror - * - *****************************************************************************/ -void cpia2_set_property_mirror(struct camera_data *cam, int prop_val) -{ - unsigned char cam_reg; - - cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS, TRANSFER_READ, 0); - cam_reg = cam->params.vp_params.user_effects; - - if (prop_val) - { - cam_reg |= CPIA2_VP_USER_EFFECTS_MIRROR; - } - else - { - cam_reg &= ~CPIA2_VP_USER_EFFECTS_MIRROR; - } - cam->params.vp_params.user_effects = cam_reg; - cpia2_do_command(cam, CPIA2_CMD_SET_USER_EFFECTS, TRANSFER_WRITE, - cam_reg); -} - -/****************************************************************************** - * - * cpia2_set_gpio - * - *****************************************************************************/ -int cpia2_set_gpio(struct camera_data *cam, unsigned char setting) -{ - int ret; - - /* Set the microport direction (register 0x90, should be defined - * already) to 1 (user output), and set the microport data (0x91) to - * the value in the ioctl argument. - */ - - ret = cpia2_do_command(cam, - CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION, - CPIA2_VC_MP_DIR_OUTPUT, - 255); - if (ret < 0) - return ret; - cam->params.vp_params.gpio_direction = 255; - - ret = cpia2_do_command(cam, - CPIA2_CMD_SET_VC_MP_GPIO_DATA, - CPIA2_VC_MP_DIR_OUTPUT, - setting); - if (ret < 0) - return ret; - cam->params.vp_params.gpio_data = setting; - - return 0; -} - -/****************************************************************************** - * - * cpia2_set_fps - * - *****************************************************************************/ -int cpia2_set_fps(struct camera_data *cam, int framerate) -{ - int retval; - - switch(framerate) { - case CPIA2_VP_FRAMERATE_30: - case CPIA2_VP_FRAMERATE_25: - if(cam->params.pnp_id.device_type == DEVICE_STV_672 && - cam->params.version.sensor_flags == - CPIA2_VP_SENSOR_FLAGS_500) { - return -EINVAL; - } - /* Fall through */ - case CPIA2_VP_FRAMERATE_15: - case CPIA2_VP_FRAMERATE_12_5: - case CPIA2_VP_FRAMERATE_7_5: - case CPIA2_VP_FRAMERATE_6_25: - break; - default: - return -EINVAL; - } - - if (cam->params.pnp_id.device_type == DEVICE_STV_672 && - framerate == CPIA2_VP_FRAMERATE_15) - framerate = 0; /* Work around bug in VP4 */ - - retval = cpia2_do_command(cam, - CPIA2_CMD_FRAMERATE_REQ, - TRANSFER_WRITE, - framerate); - - if(retval == 0) - cam->params.vp_params.frame_rate = framerate; - - return retval; -} - -/****************************************************************************** - * - * cpia2_set_brightness - * - *****************************************************************************/ -void cpia2_set_brightness(struct camera_data *cam, unsigned char value) -{ - /*** - * Don't let the register be set to zero - bug in VP4 - flash of full - * brightness - ***/ - if (cam->params.pnp_id.device_type == DEVICE_STV_672 && value == 0) - value++; - DBG("Setting brightness to %d (0x%0x)\n", value, value); - cpia2_do_command(cam, CPIA2_CMD_SET_VP_BRIGHTNESS, TRANSFER_WRITE, value); -} - -/****************************************************************************** - * - * cpia2_set_contrast - * - *****************************************************************************/ -void cpia2_set_contrast(struct camera_data *cam, unsigned char value) -{ - DBG("Setting contrast to %d (0x%0x)\n", value, value); - cpia2_do_command(cam, CPIA2_CMD_SET_CONTRAST, TRANSFER_WRITE, value); -} - -/****************************************************************************** - * - * cpia2_set_saturation - * - *****************************************************************************/ -void cpia2_set_saturation(struct camera_data *cam, unsigned char value) -{ - DBG("Setting saturation to %d (0x%0x)\n", value, value); - cpia2_do_command(cam,CPIA2_CMD_SET_VP_SATURATION, TRANSFER_WRITE,value); -} - -/****************************************************************************** - * - * wake_system - * - *****************************************************************************/ -static void wake_system(struct camera_data *cam) -{ - cpia2_do_command(cam, CPIA2_CMD_SET_WAKEUP, TRANSFER_WRITE, 0); -} - -/****************************************************************************** - * - * set_lowlight_boost - * - * Valid for STV500 sensor only - *****************************************************************************/ -static void set_lowlight_boost(struct camera_data *cam) -{ - struct cpia2_command cmd; - - if (cam->params.pnp_id.device_type != DEVICE_STV_672 || - cam->params.version.sensor_flags != CPIA2_VP_SENSOR_FLAGS_500) - return; - - cmd.direction = TRANSFER_WRITE; - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 3; - cmd.start = CPIA2_VP_RAM_ADDR_H; - - cmd.buffer.block_data[0] = 0; /* High byte of address to write to */ - cmd.buffer.block_data[1] = 0x59; /* Low byte of address to write to */ - cmd.buffer.block_data[2] = 0; /* High byte of data to write */ - - cpia2_send_command(cam, &cmd); - - if (cam->params.vp_params.lowlight_boost) { - cmd.buffer.block_data[0] = 0x02; /* Low byte data to write */ - } else { - cmd.buffer.block_data[0] = 0x06; - } - cmd.start = CPIA2_VP_RAM_DATA; - cmd.reg_count = 1; - cpia2_send_command(cam, &cmd); - - /* Rehash the VP4 values */ - cpia2_do_command(cam, CPIA2_CMD_REHASH_VP4, TRANSFER_WRITE, 1); -} - -/****************************************************************************** - * - * cpia2_set_format - * - * Assumes that new size is already set in param struct. - *****************************************************************************/ -void cpia2_set_format(struct camera_data *cam) -{ - cam->flush = true; - - cpia2_usb_stream_pause(cam); - - /* reset camera to new size */ - cpia2_set_low_power(cam); - cpia2_reset_camera(cam); - cam->flush = false; - - cpia2_dbg_dump_registers(cam); - - cpia2_usb_stream_resume(cam); -} - -/****************************************************************************** - * - * cpia2_dbg_dump_registers - * - *****************************************************************************/ -void cpia2_dbg_dump_registers(struct camera_data *cam) -{ -#ifdef _CPIA2_DEBUG_ - struct cpia2_command cmd; - - if (!(debugs_on & DEBUG_DUMP_REGS)) - return; - - cmd.direction = TRANSFER_READ; - - /* Start with bank 0 (SYSTEM) */ - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; - cmd.reg_count = 3; - cmd.start = 0; - cpia2_send_command(cam, &cmd); - printk(KERN_DEBUG "System Device Hi = 0x%X\n", - cmd.buffer.block_data[0]); - printk(KERN_DEBUG "System Device Lo = 0x%X\n", - cmd.buffer.block_data[1]); - printk(KERN_DEBUG "System_system control = 0x%X\n", - cmd.buffer.block_data[2]); - - /* Bank 1 (VC) */ - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; - cmd.reg_count = 4; - cmd.start = 0x80; - cpia2_send_command(cam, &cmd); - printk(KERN_DEBUG "ASIC_ID = 0x%X\n", - cmd.buffer.block_data[0]); - printk(KERN_DEBUG "ASIC_REV = 0x%X\n", - cmd.buffer.block_data[1]); - printk(KERN_DEBUG "PW_CONTRL = 0x%X\n", - cmd.buffer.block_data[2]); - printk(KERN_DEBUG "WAKEUP = 0x%X\n", - cmd.buffer.block_data[3]); - - cmd.start = 0xA0; /* ST_CTRL */ - cmd.reg_count = 1; - cpia2_send_command(cam, &cmd); - printk(KERN_DEBUG "Stream ctrl = 0x%X\n", - cmd.buffer.block_data[0]); - - cmd.start = 0xA4; /* Stream status */ - cpia2_send_command(cam, &cmd); - printk(KERN_DEBUG "Stream status = 0x%X\n", - cmd.buffer.block_data[0]); - - cmd.start = 0xA8; /* USB status */ - cmd.reg_count = 3; - cpia2_send_command(cam, &cmd); - printk(KERN_DEBUG "USB_CTRL = 0x%X\n", - cmd.buffer.block_data[0]); - printk(KERN_DEBUG "USB_STRM = 0x%X\n", - cmd.buffer.block_data[1]); - printk(KERN_DEBUG "USB_STATUS = 0x%X\n", - cmd.buffer.block_data[2]); - - cmd.start = 0xAF; /* USB settings */ - cmd.reg_count = 1; - cpia2_send_command(cam, &cmd); - printk(KERN_DEBUG "USB settings = 0x%X\n", - cmd.buffer.block_data[0]); - - cmd.start = 0xC0; /* VC stuff */ - cmd.reg_count = 26; - cpia2_send_command(cam, &cmd); - printk(KERN_DEBUG "VC Control = 0x%0X\n", - cmd.buffer.block_data[0]); - printk(KERN_DEBUG "VC Format = 0x%0X\n", - cmd.buffer.block_data[3]); - printk(KERN_DEBUG "VC Clocks = 0x%0X\n", - cmd.buffer.block_data[4]); - printk(KERN_DEBUG "VC IHSize = 0x%0X\n", - cmd.buffer.block_data[5]); - printk(KERN_DEBUG "VC Xlim Hi = 0x%0X\n", - cmd.buffer.block_data[6]); - printk(KERN_DEBUG "VC XLim Lo = 0x%0X\n", - cmd.buffer.block_data[7]); - printk(KERN_DEBUG "VC YLim Hi = 0x%0X\n", - cmd.buffer.block_data[8]); - printk(KERN_DEBUG "VC YLim Lo = 0x%0X\n", - cmd.buffer.block_data[9]); - printk(KERN_DEBUG "VC OHSize = 0x%0X\n", - cmd.buffer.block_data[10]); - printk(KERN_DEBUG "VC OVSize = 0x%0X\n", - cmd.buffer.block_data[11]); - printk(KERN_DEBUG "VC HCrop = 0x%0X\n", - cmd.buffer.block_data[12]); - printk(KERN_DEBUG "VC VCrop = 0x%0X\n", - cmd.buffer.block_data[13]); - printk(KERN_DEBUG "VC HPhase = 0x%0X\n", - cmd.buffer.block_data[14]); - printk(KERN_DEBUG "VC VPhase = 0x%0X\n", - cmd.buffer.block_data[15]); - printk(KERN_DEBUG "VC HIspan = 0x%0X\n", - cmd.buffer.block_data[16]); - printk(KERN_DEBUG "VC VIspan = 0x%0X\n", - cmd.buffer.block_data[17]); - printk(KERN_DEBUG "VC HiCrop = 0x%0X\n", - cmd.buffer.block_data[18]); - printk(KERN_DEBUG "VC ViCrop = 0x%0X\n", - cmd.buffer.block_data[19]); - printk(KERN_DEBUG "VC HiFract = 0x%0X\n", - cmd.buffer.block_data[20]); - printk(KERN_DEBUG "VC ViFract = 0x%0X\n", - cmd.buffer.block_data[21]); - printk(KERN_DEBUG "VC JPeg Opt = 0x%0X\n", - cmd.buffer.block_data[22]); - printk(KERN_DEBUG "VC Creep Per = 0x%0X\n", - cmd.buffer.block_data[23]); - printk(KERN_DEBUG "VC User Sq. = 0x%0X\n", - cmd.buffer.block_data[24]); - printk(KERN_DEBUG "VC Target KB = 0x%0X\n", - cmd.buffer.block_data[25]); - - /*** VP ***/ - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; - cmd.reg_count = 14; - cmd.start = 0; - cpia2_send_command(cam, &cmd); - - printk(KERN_DEBUG "VP Dev Hi = 0x%0X\n", - cmd.buffer.block_data[0]); - printk(KERN_DEBUG "VP Dev Lo = 0x%0X\n", - cmd.buffer.block_data[1]); - printk(KERN_DEBUG "VP Sys State = 0x%0X\n", - cmd.buffer.block_data[2]); - printk(KERN_DEBUG "VP Sys Ctrl = 0x%0X\n", - cmd.buffer.block_data[3]); - printk(KERN_DEBUG "VP Sensor flg = 0x%0X\n", - cmd.buffer.block_data[5]); - printk(KERN_DEBUG "VP Sensor Rev = 0x%0X\n", - cmd.buffer.block_data[6]); - printk(KERN_DEBUG "VP Dev Config = 0x%0X\n", - cmd.buffer.block_data[7]); - printk(KERN_DEBUG "VP GPIO_DIR = 0x%0X\n", - cmd.buffer.block_data[8]); - printk(KERN_DEBUG "VP GPIO_DATA = 0x%0X\n", - cmd.buffer.block_data[9]); - printk(KERN_DEBUG "VP Ram ADDR H = 0x%0X\n", - cmd.buffer.block_data[10]); - printk(KERN_DEBUG "VP Ram ADDR L = 0x%0X\n", - cmd.buffer.block_data[11]); - printk(KERN_DEBUG "VP RAM Data = 0x%0X\n", - cmd.buffer.block_data[12]); - printk(KERN_DEBUG "Do Call = 0x%0X\n", - cmd.buffer.block_data[13]); - - if (cam->params.pnp_id.device_type == DEVICE_STV_672) { - cmd.reg_count = 9; - cmd.start = 0x0E; - cpia2_send_command(cam, &cmd); - printk(KERN_DEBUG "VP Clock Ctrl = 0x%0X\n", - cmd.buffer.block_data[0]); - printk(KERN_DEBUG "VP Patch Rev = 0x%0X\n", - cmd.buffer.block_data[1]); - printk(KERN_DEBUG "VP Vid Mode = 0x%0X\n", - cmd.buffer.block_data[2]); - printk(KERN_DEBUG "VP Framerate = 0x%0X\n", - cmd.buffer.block_data[3]); - printk(KERN_DEBUG "VP UserEffect = 0x%0X\n", - cmd.buffer.block_data[4]); - printk(KERN_DEBUG "VP White Bal = 0x%0X\n", - cmd.buffer.block_data[5]); - printk(KERN_DEBUG "VP WB thresh = 0x%0X\n", - cmd.buffer.block_data[6]); - printk(KERN_DEBUG "VP Exp Modes = 0x%0X\n", - cmd.buffer.block_data[7]); - printk(KERN_DEBUG "VP Exp Target = 0x%0X\n", - cmd.buffer.block_data[8]); - - cmd.reg_count = 1; - cmd.start = 0x1B; - cpia2_send_command(cam, &cmd); - printk(KERN_DEBUG "VP FlickerMds = 0x%0X\n", - cmd.buffer.block_data[0]); - } else { - cmd.reg_count = 8 ; - cmd.start = 0x0E; - cpia2_send_command(cam, &cmd); - printk(KERN_DEBUG "VP Clock Ctrl = 0x%0X\n", - cmd.buffer.block_data[0]); - printk(KERN_DEBUG "VP Patch Rev = 0x%0X\n", - cmd.buffer.block_data[1]); - printk(KERN_DEBUG "VP Vid Mode = 0x%0X\n", - cmd.buffer.block_data[5]); - printk(KERN_DEBUG "VP Framerate = 0x%0X\n", - cmd.buffer.block_data[6]); - printk(KERN_DEBUG "VP UserEffect = 0x%0X\n", - cmd.buffer.block_data[7]); - - cmd.reg_count = 1; - cmd.start = CPIA2_VP5_EXPOSURE_TARGET; - cpia2_send_command(cam, &cmd); - printk(KERN_DEBUG "VP5 Exp Target= 0x%0X\n", - cmd.buffer.block_data[0]); - - cmd.reg_count = 4; - cmd.start = 0x3A; - cpia2_send_command(cam, &cmd); - printk(KERN_DEBUG "VP5 MY Black = 0x%0X\n", - cmd.buffer.block_data[0]); - printk(KERN_DEBUG "VP5 MCY Range = 0x%0X\n", - cmd.buffer.block_data[1]); - printk(KERN_DEBUG "VP5 MYCEILING = 0x%0X\n", - cmd.buffer.block_data[2]); - printk(KERN_DEBUG "VP5 MCUV Sat = 0x%0X\n", - cmd.buffer.block_data[3]); - } -#endif -} - -/****************************************************************************** - * - * reset_camera_struct - * - * Sets all values to the defaults - *****************************************************************************/ -static void reset_camera_struct(struct camera_data *cam) -{ - /*** - * The following parameter values are the defaults from the register map. - ***/ - cam->params.vp_params.lowlight_boost = 0; - - /* FlickerModes */ - cam->params.flicker_control.flicker_mode_req = NEVER_FLICKER; - - /* jpeg params */ - cam->params.compression.jpeg_options = CPIA2_VC_VC_JPEG_OPT_DEFAULT; - cam->params.compression.creep_period = 2; - cam->params.compression.user_squeeze = 20; - cam->params.compression.inhibit_htables = false; - - /* gpio params */ - cam->params.vp_params.gpio_direction = 0; /* write, the default safe mode */ - cam->params.vp_params.gpio_data = 0; - - /* Target kb params */ - cam->params.vc_params.quality = 100; - - /*** - * Set Sensor FPS as fast as possible. - ***/ - if(cam->params.pnp_id.device_type == DEVICE_STV_672) { - if(cam->params.version.sensor_flags == CPIA2_VP_SENSOR_FLAGS_500) - cam->params.vp_params.frame_rate = CPIA2_VP_FRAMERATE_15; - else - cam->params.vp_params.frame_rate = CPIA2_VP_FRAMERATE_30; - } else { - cam->params.vp_params.frame_rate = CPIA2_VP_FRAMERATE_30; - } - - /*** - * Set default video mode as large as possible : - * for vga sensor set to vga, for cif sensor set to CIF. - ***/ - if (cam->params.version.sensor_flags == CPIA2_VP_SENSOR_FLAGS_500) { - cam->sensor_type = CPIA2_SENSOR_500; - cam->video_size = VIDEOSIZE_VGA; - cam->params.roi.width = STV_IMAGE_VGA_COLS; - cam->params.roi.height = STV_IMAGE_VGA_ROWS; - } else { - cam->sensor_type = CPIA2_SENSOR_410; - cam->video_size = VIDEOSIZE_CIF; - cam->params.roi.width = STV_IMAGE_CIF_COLS; - cam->params.roi.height = STV_IMAGE_CIF_ROWS; - } - - cam->width = cam->params.roi.width; - cam->height = cam->params.roi.height; -} - -/****************************************************************************** - * - * cpia2_init_camera_struct - * - * Initializes camera struct, does not call reset to fill in defaults. - *****************************************************************************/ -struct camera_data *cpia2_init_camera_struct(struct usb_interface *intf) -{ - struct camera_data *cam; - - cam = kzalloc(sizeof(*cam), GFP_KERNEL); - - if (!cam) { - ERR("couldn't kmalloc cpia2 struct\n"); - return NULL; - } - - cam->v4l2_dev.release = cpia2_camera_release; - if (v4l2_device_register(&intf->dev, &cam->v4l2_dev) < 0) { - v4l2_err(&cam->v4l2_dev, "couldn't register v4l2_device\n"); - kfree(cam); - return NULL; - } - - mutex_init(&cam->v4l2_lock); - init_waitqueue_head(&cam->wq_stream); - - return cam; -} - -/****************************************************************************** - * - * cpia2_init_camera - * - * Initializes camera. - *****************************************************************************/ -int cpia2_init_camera(struct camera_data *cam) -{ - DBG("Start\n"); - - cam->mmapped = false; - - /* Get sensor and asic types before reset. */ - cpia2_set_high_power(cam); - cpia2_get_version_info(cam); - if (cam->params.version.asic_id != CPIA2_ASIC_672) { - ERR("Device IO error (asicID has incorrect value of 0x%X\n", - cam->params.version.asic_id); - return -ENODEV; - } - - /* Set GPIO direction and data to a safe state. */ - cpia2_do_command(cam, CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION, - TRANSFER_WRITE, 0); - cpia2_do_command(cam, CPIA2_CMD_SET_VC_MP_GPIO_DATA, - TRANSFER_WRITE, 0); - - /* resetting struct requires version info for sensor and asic types */ - reset_camera_struct(cam); - - cpia2_set_low_power(cam); - - DBG("End\n"); - - return 0; -} - -/****************************************************************************** - * - * cpia2_allocate_buffers - * - *****************************************************************************/ -int cpia2_allocate_buffers(struct camera_data *cam) -{ - int i; - - if(!cam->buffers) { - u32 size = cam->num_frames*sizeof(struct framebuf); - cam->buffers = kmalloc(size, GFP_KERNEL); - if(!cam->buffers) { - ERR("couldn't kmalloc frame buffer structures\n"); - return -ENOMEM; - } - } - - if(!cam->frame_buffer) { - cam->frame_buffer = rvmalloc(cam->frame_size*cam->num_frames); - if (!cam->frame_buffer) { - ERR("couldn't vmalloc frame buffer data area\n"); - kfree(cam->buffers); - cam->buffers = NULL; - return -ENOMEM; - } - } - - for(i=0; i<cam->num_frames-1; ++i) { - cam->buffers[i].next = &cam->buffers[i+1]; - cam->buffers[i].data = cam->frame_buffer +i*cam->frame_size; - cam->buffers[i].status = FRAME_EMPTY; - cam->buffers[i].length = 0; - cam->buffers[i].max_length = 0; - cam->buffers[i].num = i; - } - cam->buffers[i].next = cam->buffers; - cam->buffers[i].data = cam->frame_buffer +i*cam->frame_size; - cam->buffers[i].status = FRAME_EMPTY; - cam->buffers[i].length = 0; - cam->buffers[i].max_length = 0; - cam->buffers[i].num = i; - cam->curbuff = cam->buffers; - cam->workbuff = cam->curbuff->next; - DBG("buffers=%p, curbuff=%p, workbuff=%p\n", cam->buffers, cam->curbuff, - cam->workbuff); - return 0; -} - -/****************************************************************************** - * - * cpia2_free_buffers - * - *****************************************************************************/ -void cpia2_free_buffers(struct camera_data *cam) -{ - if(cam->buffers) { - kfree(cam->buffers); - cam->buffers = NULL; - } - if(cam->frame_buffer) { - rvfree(cam->frame_buffer, cam->frame_size*cam->num_frames); - cam->frame_buffer = NULL; - } -} - -/****************************************************************************** - * - * cpia2_read - * - *****************************************************************************/ -long cpia2_read(struct camera_data *cam, - char __user *buf, unsigned long count, int noblock) -{ - struct framebuf *frame; - - if (!count) - return 0; - - if (!buf) { - ERR("%s: buffer NULL\n",__func__); - return -EINVAL; - } - - if (!cam) { - ERR("%s: Internal error, camera_data NULL!\n",__func__); - return -EINVAL; - } - - if (!cam->streaming) { - /* Start streaming */ - cpia2_usb_stream_start(cam, - cam->params.camera_state.stream_mode); - } - - /* Copy cam->curbuff in case it changes while we're processing */ - frame = cam->curbuff; - if (noblock && frame->status != FRAME_READY) { - return -EAGAIN; - } - - if (frame->status != FRAME_READY) { - mutex_unlock(&cam->v4l2_lock); - wait_event_interruptible(cam->wq_stream, - !video_is_registered(&cam->vdev) || - (frame = cam->curbuff)->status == FRAME_READY); - mutex_lock(&cam->v4l2_lock); - if (signal_pending(current)) - return -ERESTARTSYS; - if (!video_is_registered(&cam->vdev)) - return 0; - } - - /* copy data to user space */ - if (frame->length > count) - return -EFAULT; - if (copy_to_user(buf, frame->data, frame->length)) - return -EFAULT; - - count = frame->length; - - frame->status = FRAME_EMPTY; - - return count; -} - -/****************************************************************************** - * - * cpia2_poll - * - *****************************************************************************/ -unsigned int cpia2_poll(struct camera_data *cam, struct file *filp, - poll_table *wait) -{ - unsigned int status = v4l2_ctrl_poll(filp, wait); - - if ((poll_requested_events(wait) & (POLLIN | POLLRDNORM)) && - !cam->streaming) { - /* Start streaming */ - cpia2_usb_stream_start(cam, - cam->params.camera_state.stream_mode); - } - - poll_wait(filp, &cam->wq_stream, wait); - - if (cam->curbuff->status == FRAME_READY) - status |= POLLIN | POLLRDNORM; - - return status; -} - -/****************************************************************************** - * - * cpia2_remap_buffer - * - *****************************************************************************/ -int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma) -{ - const char *adr = (const char *)vma->vm_start; - unsigned long size = vma->vm_end-vma->vm_start; - unsigned long start_offset = vma->vm_pgoff << PAGE_SHIFT; - unsigned long start = (unsigned long) adr; - unsigned long page, pos; - - DBG("mmap offset:%ld size:%ld\n", start_offset, size); - - if (!video_is_registered(&cam->vdev)) - return -ENODEV; - - if (size > cam->frame_size*cam->num_frames || - (start_offset % cam->frame_size) != 0 || - (start_offset+size > cam->frame_size*cam->num_frames)) - return -EINVAL; - - pos = ((unsigned long) (cam->frame_buffer)) + start_offset; - while (size > 0) { - page = kvirt_to_pa(pos); - if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - - cam->mmapped = true; - return 0; -} diff --git a/drivers/media/video/cpia2/cpia2_registers.h b/drivers/media/video/cpia2/cpia2_registers.h deleted file mode 100644 index 3bbec514a967..000000000000 --- a/drivers/media/video/cpia2/cpia2_registers.h +++ /dev/null @@ -1,476 +0,0 @@ -/**************************************************************************** - * - * Filename: cpia2registers.h - * - * Copyright 2001, STMicrolectronics, Inc. - * - * Description: - * Definitions for the CPia2 register set - * - * 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. - * - ****************************************************************************/ - -#ifndef CPIA2_REGISTER_HEADER -#define CPIA2_REGISTER_HEADER - -/*** - * System register set (Bank 0) - ***/ -#define CPIA2_SYSTEM_DEVICE_HI 0x00 -#define CPIA2_SYSTEM_DEVICE_LO 0x01 - -#define CPIA2_SYSTEM_SYSTEM_CONTROL 0x02 -#define CPIA2_SYSTEM_CONTROL_LOW_POWER 0x00 -#define CPIA2_SYSTEM_CONTROL_HIGH_POWER 0x01 -#define CPIA2_SYSTEM_CONTROL_SUSPEND 0x02 -#define CPIA2_SYSTEM_CONTROL_V2W_ERR 0x10 -#define CPIA2_SYSTEM_CONTROL_RB_ERR 0x10 -#define CPIA2_SYSTEM_CONTROL_CLEAR_ERR 0x80 - -#define CPIA2_SYSTEM_INT_PACKET_CTRL 0x04 -#define CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_SW_XX 0x01 -#define CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_EOF 0x02 -#define CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_INT1 0x04 - -#define CPIA2_SYSTEM_CACHE_CTRL 0x05 -#define CPIA2_SYSTEM_CACHE_CTRL_CACHE_RESET 0x01 -#define CPIA2_SYSTEM_CACHE_CTRL_CACHE_FLUSH 0x02 - -#define CPIA2_SYSTEM_SERIAL_CTRL 0x06 -#define CPIA2_SYSTEM_SERIAL_CTRL_NULL_CMD 0x00 -#define CPIA2_SYSTEM_SERIAL_CTRL_START_CMD 0x01 -#define CPIA2_SYSTEM_SERIAL_CTRL_STOP_CMD 0x02 -#define CPIA2_SYSTEM_SERIAL_CTRL_WRITE_CMD 0x03 -#define CPIA2_SYSTEM_SERIAL_CTRL_READ_ACK_CMD 0x04 -#define CPIA2_SYSTEM_SERIAL_CTRL_READ_NACK_CMD 0x05 - -#define CPIA2_SYSTEM_SERIAL_DATA 0x07 - -#define CPIA2_SYSTEM_VP_SERIAL_ADDR 0x08 - -/*** - * I2C addresses for various devices in CPiA2 - ***/ -#define CPIA2_SYSTEM_VP_SERIAL_ADDR_SENSOR 0x20 -#define CPIA2_SYSTEM_VP_SERIAL_ADDR_VP 0x88 -#define CPIA2_SYSTEM_VP_SERIAL_ADDR_676_VP 0x8A - -#define CPIA2_SYSTEM_SPARE_REG1 0x09 -#define CPIA2_SYSTEM_SPARE_REG2 0x0A -#define CPIA2_SYSTEM_SPARE_REG3 0x0B - -#define CPIA2_SYSTEM_MC_PORT_0 0x0C -#define CPIA2_SYSTEM_MC_PORT_1 0x0D -#define CPIA2_SYSTEM_MC_PORT_2 0x0E -#define CPIA2_SYSTEM_MC_PORT_3 0x0F - -#define CPIA2_SYSTEM_STATUS_PKT 0x20 -#define CPIA2_SYSTEM_STATUS_PKT_END 0x27 - -#define CPIA2_SYSTEM_DESCRIP_VID_HI 0x30 -#define CPIA2_SYSTEM_DESCRIP_VID_LO 0x31 -#define CPIA2_SYSTEM_DESCRIP_PID_HI 0x32 -#define CPIA2_SYSTEM_DESCRIP_PID_LO 0x33 - -#define CPIA2_SYSTEM_FW_VERSION_HI 0x34 -#define CPIA2_SYSTEM_FW_VERSION_LO 0x35 - -#define CPIA2_SYSTEM_CACHE_START_INDEX 0x80 -#define CPIA2_SYSTEM_CACHE_MAX_WRITES 0x10 - -/*** - * VC register set (Bank 1) - ***/ -#define CPIA2_VC_ASIC_ID 0x80 - -#define CPIA2_VC_ASIC_REV 0x81 - -#define CPIA2_VC_PW_CTRL 0x82 -#define CPIA2_VC_PW_CTRL_COLDSTART 0x01 -#define CPIA2_VC_PW_CTRL_CP_CLK_EN 0x02 -#define CPIA2_VC_PW_CTRL_VP_RESET_N 0x04 -#define CPIA2_VC_PW_CTRL_VC_CLK_EN 0x08 -#define CPIA2_VC_PW_CTRL_VC_RESET_N 0x10 -#define CPIA2_VC_PW_CTRL_GOTO_SUSPEND 0x20 -#define CPIA2_VC_PW_CTRL_UDC_SUSPEND 0x40 -#define CPIA2_VC_PW_CTRL_PWR_DOWN 0x80 - -#define CPIA2_VC_WAKEUP 0x83 -#define CPIA2_VC_WAKEUP_SW_ENABLE 0x01 -#define CPIA2_VC_WAKEUP_XX_ENABLE 0x02 -#define CPIA2_VC_WAKEUP_SW_ATWAKEUP 0x04 -#define CPIA2_VC_WAKEUP_XX_ATWAKEUP 0x08 - -#define CPIA2_VC_CLOCK_CTRL 0x84 -#define CPIA2_VC_CLOCK_CTRL_TESTUP72 0x01 - -#define CPIA2_VC_INT_ENABLE 0x88 -#define CPIA2_VC_INT_ENABLE_XX_IE 0x01 -#define CPIA2_VC_INT_ENABLE_SW_IE 0x02 -#define CPIA2_VC_INT_ENABLE_VC_IE 0x04 -#define CPIA2_VC_INT_ENABLE_USBDATA_IE 0x08 -#define CPIA2_VC_INT_ENABLE_USBSETUP_IE 0x10 -#define CPIA2_VC_INT_ENABLE_USBCFG_IE 0x20 - -#define CPIA2_VC_INT_FLAG 0x89 -#define CPIA2_VC_INT_ENABLE_XX_FLAG 0x01 -#define CPIA2_VC_INT_ENABLE_SW_FLAG 0x02 -#define CPIA2_VC_INT_ENABLE_VC_FLAG 0x04 -#define CPIA2_VC_INT_ENABLE_USBDATA_FLAG 0x08 -#define CPIA2_VC_INT_ENABLE_USBSETUP_FLAG 0x10 -#define CPIA2_VC_INT_ENABLE_USBCFG_FLAG 0x20 -#define CPIA2_VC_INT_ENABLE_SET_RESET_BIT 0x80 - -#define CPIA2_VC_INT_STATE 0x8A -#define CPIA2_VC_INT_STATE_XX_STATE 0x01 -#define CPIA2_VC_INT_STATE_SW_STATE 0x02 - -#define CPIA2_VC_MP_DIR 0x90 -#define CPIA2_VC_MP_DIR_INPUT 0x00 -#define CPIA2_VC_MP_DIR_OUTPUT 0x01 - -#define CPIA2_VC_MP_DATA 0x91 - -#define CPIA2_VC_DP_CTRL 0x98 -#define CPIA2_VC_DP_CTRL_MODE_0 0x00 -#define CPIA2_VC_DP_CTRL_MODE_A 0x01 -#define CPIA2_VC_DP_CTRL_MODE_B 0x02 -#define CPIA2_VC_DP_CTRL_MODE_C 0x03 -#define CPIA2_VC_DP_CTRL_FAKE_FST 0x04 - -#define CPIA2_VC_AD_CTRL 0x99 -#define CPIA2_VC_AD_CTRL_SRC_0 0x00 -#define CPIA2_VC_AD_CTRL_SRC_DIGI_A 0x01 -#define CPIA2_VC_AD_CTRL_SRC_REG 0x02 -#define CPIA2_VC_AD_CTRL_DST_USB 0x00 -#define CPIA2_VC_AD_CTRL_DST_REG 0x04 - -#define CPIA2_VC_AD_TEST_IN 0x9B - -#define CPIA2_VC_AD_TEST_OUT 0x9C - -#define CPIA2_VC_AD_STATUS 0x9D -#define CPIA2_VC_AD_STATUS_EMPTY 0x01 -#define CPIA2_VC_AD_STATUS_FULL 0x02 - -#define CPIA2_VC_DP_DATA 0x9E - -#define CPIA2_VC_ST_CTRL 0xA0 -#define CPIA2_VC_ST_CTRL_SRC_VC 0x00 -#define CPIA2_VC_ST_CTRL_SRC_DP 0x01 -#define CPIA2_VC_ST_CTRL_SRC_REG 0x02 - -#define CPIA2_VC_ST_CTRL_RAW_SELECT 0x04 - -#define CPIA2_VC_ST_CTRL_DST_USB 0x00 -#define CPIA2_VC_ST_CTRL_DST_DP 0x08 -#define CPIA2_VC_ST_CTRL_DST_REG 0x10 - -#define CPIA2_VC_ST_CTRL_FIFO_ENABLE 0x20 -#define CPIA2_VC_ST_CTRL_EOF_DETECT 0x40 - -#define CPIA2_VC_ST_TEST 0xA1 -#define CPIA2_VC_ST_TEST_MODE_MANUAL 0x00 -#define CPIA2_VC_ST_TEST_MODE_INCREMENT 0x02 - -#define CPIA2_VC_ST_TEST_AUTO_FILL 0x08 - -#define CPIA2_VC_ST_TEST_REPEAT_FIFO 0x10 - -#define CPIA2_VC_ST_TEST_IN 0xA2 - -#define CPIA2_VC_ST_TEST_OUT 0xA3 - -#define CPIA2_VC_ST_STATUS 0xA4 -#define CPIA2_VC_ST_STATUS_EMPTY 0x01 -#define CPIA2_VC_ST_STATUS_FULL 0x02 - -#define CPIA2_VC_ST_FRAME_DETECT_1 0xA5 - -#define CPIA2_VC_ST_FRAME_DETECT_2 0xA6 - -#define CPIA2_VC_USB_CTRL 0xA8 -#define CPIA2_VC_USB_CTRL_CMD_STALLED 0x01 -#define CPIA2_VC_USB_CTRL_CMD_READY 0x02 -#define CPIA2_VC_USB_CTRL_CMD_STATUS 0x04 -#define CPIA2_VC_USB_CTRL_CMD_STATUS_DIR 0x08 -#define CPIA2_VC_USB_CTRL_CMD_NO_CLASH 0x10 -#define CPIA2_VC_USB_CTRL_CMD_MICRO_ACCESS 0x80 - -#define CPIA2_VC_USB_STRM 0xA9 -#define CPIA2_VC_USB_STRM_ISO_ENABLE 0x01 -#define CPIA2_VC_USB_STRM_BLK_ENABLE 0x02 -#define CPIA2_VC_USB_STRM_INT_ENABLE 0x04 -#define CPIA2_VC_USB_STRM_AUD_ENABLE 0x08 - -#define CPIA2_VC_USB_STATUS 0xAA -#define CPIA2_VC_USB_STATUS_CMD_IN_PROGRESS 0x01 -#define CPIA2_VC_USB_STATUS_CMD_STATUS_STALL 0x02 -#define CPIA2_VC_USB_STATUS_CMD_HANDSHAKE 0x04 -#define CPIA2_VC_USB_STATUS_CMD_OVERRIDE 0x08 -#define CPIA2_VC_USB_STATUS_CMD_FIFO_BUSY 0x10 -#define CPIA2_VC_USB_STATUS_BULK_REPEAT_TXN 0x20 -#define CPIA2_VC_USB_STATUS_CONFIG_DONE 0x40 -#define CPIA2_VC_USB_STATUS_USB_SUSPEND 0x80 - -#define CPIA2_VC_USB_CMDW 0xAB - -#define CPIA2_VC_USB_DATARW 0xAC - -#define CPIA2_VC_USB_INFO 0xAD - -#define CPIA2_VC_USB_CONFIG 0xAE - -#define CPIA2_VC_USB_SETTINGS 0xAF -#define CPIA2_VC_USB_SETTINGS_CONFIG_MASK 0x03 -#define CPIA2_VC_USB_SETTINGS_INTERFACE_MASK 0x0C -#define CPIA2_VC_USB_SETTINGS_ALTERNATE_MASK 0x70 - -#define CPIA2_VC_USB_ISOLIM 0xB0 - -#define CPIA2_VC_USB_ISOFAILS 0xB1 - -#define CPIA2_VC_USB_ISOMAXPKTHI 0xB2 - -#define CPIA2_VC_USB_ISOMAXPKTLO 0xB3 - -#define CPIA2_VC_V2W_CTRL 0xB8 -#define CPIA2_VC_V2W_SELECT 0x01 - -#define CPIA2_VC_V2W_SCL 0xB9 - -#define CPIA2_VC_V2W_SDA 0xBA - -#define CPIA2_VC_VC_CTRL 0xC0 -#define CPIA2_VC_VC_CTRL_RUN 0x01 -#define CPIA2_VC_VC_CTRL_SINGLESHOT 0x02 -#define CPIA2_VC_VC_CTRL_IDLING 0x04 -#define CPIA2_VC_VC_CTRL_INHIBIT_H_TABLES 0x10 -#define CPIA2_VC_VC_CTRL_INHIBIT_Q_TABLES 0x20 -#define CPIA2_VC_VC_CTRL_INHIBIT_PRIVATE 0x40 - -#define CPIA2_VC_VC_RESTART_IVAL_HI 0xC1 - -#define CPIA2_VC_VC_RESTART_IVAL_LO 0xC2 - -#define CPIA2_VC_VC_FORMAT 0xC3 -#define CPIA2_VC_VC_FORMAT_UFIRST 0x01 -#define CPIA2_VC_VC_FORMAT_MONO 0x02 -#define CPIA2_VC_VC_FORMAT_DECIMATING 0x04 -#define CPIA2_VC_VC_FORMAT_SHORTLINE 0x08 -#define CPIA2_VC_VC_FORMAT_SELFTEST 0x10 - -#define CPIA2_VC_VC_CLOCKS 0xC4 -#define CPIA2_VC_VC_CLOCKS_CLKDIV_MASK 0x03 -#define CPIA2_VC_VC_672_CLOCKS_CIF_DIV_BY_3 0x04 -#define CPIA2_VC_VC_672_CLOCKS_SCALING 0x08 -#define CPIA2_VC_VC_CLOCKS_LOGDIV0 0x00 -#define CPIA2_VC_VC_CLOCKS_LOGDIV1 0x01 -#define CPIA2_VC_VC_CLOCKS_LOGDIV2 0x02 -#define CPIA2_VC_VC_CLOCKS_LOGDIV3 0x03 -#define CPIA2_VC_VC_676_CLOCKS_CIF_DIV_BY_3 0x08 -#define CPIA2_VC_VC_676_CLOCKS_SCALING 0x10 - -#define CPIA2_VC_VC_IHSIZE_LO 0xC5 - -#define CPIA2_VC_VC_XLIM_HI 0xC6 - -#define CPIA2_VC_VC_XLIM_LO 0xC7 - -#define CPIA2_VC_VC_YLIM_HI 0xC8 - -#define CPIA2_VC_VC_YLIM_LO 0xC9 - -#define CPIA2_VC_VC_OHSIZE 0xCA - -#define CPIA2_VC_VC_OVSIZE 0xCB - -#define CPIA2_VC_VC_HCROP 0xCC - -#define CPIA2_VC_VC_VCROP 0xCD - -#define CPIA2_VC_VC_HPHASE 0xCE - -#define CPIA2_VC_VC_VPHASE 0xCF - -#define CPIA2_VC_VC_HISPAN 0xD0 - -#define CPIA2_VC_VC_VISPAN 0xD1 - -#define CPIA2_VC_VC_HICROP 0xD2 - -#define CPIA2_VC_VC_VICROP 0xD3 - -#define CPIA2_VC_VC_HFRACT 0xD4 -#define CPIA2_VC_VC_HFRACT_DEN_MASK 0x0F -#define CPIA2_VC_VC_HFRACT_NUM_MASK 0xF0 - -#define CPIA2_VC_VC_VFRACT 0xD5 -#define CPIA2_VC_VC_VFRACT_DEN_MASK 0x0F -#define CPIA2_VC_VC_VFRACT_NUM_MASK 0xF0 - -#define CPIA2_VC_VC_JPEG_OPT 0xD6 -#define CPIA2_VC_VC_JPEG_OPT_DOUBLE_SQUEEZE 0x01 -#define CPIA2_VC_VC_JPEG_OPT_NO_DC_AUTO_SQUEEZE 0x02 -#define CPIA2_VC_VC_JPEG_OPT_AUTO_SQUEEZE 0x04 -#define CPIA2_VC_VC_JPEG_OPT_DEFAULT (CPIA2_VC_VC_JPEG_OPT_DOUBLE_SQUEEZE|\ - CPIA2_VC_VC_JPEG_OPT_AUTO_SQUEEZE) - - -#define CPIA2_VC_VC_CREEP_PERIOD 0xD7 -#define CPIA2_VC_VC_USER_SQUEEZE 0xD8 -#define CPIA2_VC_VC_TARGET_KB 0xD9 - -#define CPIA2_VC_VC_AUTO_SQUEEZE 0xE6 - - -/*** - * VP register set (Bank 2) - ***/ -#define CPIA2_VP_DEVICEH 0 -#define CPIA2_VP_DEVICEL 1 - -#define CPIA2_VP_SYSTEMSTATE 0x02 -#define CPIA2_VP_SYSTEMSTATE_HK_ALIVE 0x01 - -#define CPIA2_VP_SYSTEMCTRL 0x03 -#define CPIA2_VP_SYSTEMCTRL_REQ_CLEAR_ERROR 0x80 -#define CPIA2_VP_SYSTEMCTRL_POWER_DOWN_PLL 0x20 -#define CPIA2_VP_SYSTEMCTRL_REQ_SUSPEND_STATE 0x10 -#define CPIA2_VP_SYSTEMCTRL_REQ_SERIAL_WAKEUP 0x08 -#define CPIA2_VP_SYSTEMCTRL_REQ_AUTOLOAD 0x04 -#define CPIA2_VP_SYSTEMCTRL_HK_CONTROL 0x02 -#define CPIA2_VP_SYSTEMCTRL_POWER_CONTROL 0x01 - -#define CPIA2_VP_SENSOR_FLAGS 0x05 -#define CPIA2_VP_SENSOR_FLAGS_404 0x01 -#define CPIA2_VP_SENSOR_FLAGS_407 0x02 -#define CPIA2_VP_SENSOR_FLAGS_409 0x04 -#define CPIA2_VP_SENSOR_FLAGS_410 0x08 -#define CPIA2_VP_SENSOR_FLAGS_500 0x10 - -#define CPIA2_VP_SENSOR_REV 0x06 - -#define CPIA2_VP_DEVICE_CONFIG 0x07 -#define CPIA2_VP_DEVICE_CONFIG_SERIAL_BRIDGE 0x01 - -#define CPIA2_VP_GPIO_DIRECTION 0x08 -#define CPIA2_VP_GPIO_READ 0xFF -#define CPIA2_VP_GPIO_WRITE 0x00 - -#define CPIA2_VP_GPIO_DATA 0x09 - -#define CPIA2_VP_RAM_ADDR_H 0x0A -#define CPIA2_VP_RAM_ADDR_L 0x0B -#define CPIA2_VP_RAM_DATA 0x0C - -#define CPIA2_VP_PATCH_REV 0x0F - -#define CPIA2_VP4_USER_MODE 0x10 -#define CPIA2_VP5_USER_MODE 0x13 -#define CPIA2_VP_USER_MODE_CIF 0x01 -#define CPIA2_VP_USER_MODE_QCIFDS 0x02 -#define CPIA2_VP_USER_MODE_QCIFPTC 0x04 -#define CPIA2_VP_USER_MODE_QVGADS 0x08 -#define CPIA2_VP_USER_MODE_QVGAPTC 0x10 -#define CPIA2_VP_USER_MODE_VGA 0x20 - -#define CPIA2_VP4_FRAMERATE_REQUEST 0x11 -#define CPIA2_VP5_FRAMERATE_REQUEST 0x14 -#define CPIA2_VP_FRAMERATE_60 0x80 -#define CPIA2_VP_FRAMERATE_50 0x40 -#define CPIA2_VP_FRAMERATE_30 0x20 -#define CPIA2_VP_FRAMERATE_25 0x10 -#define CPIA2_VP_FRAMERATE_15 0x08 -#define CPIA2_VP_FRAMERATE_12_5 0x04 -#define CPIA2_VP_FRAMERATE_7_5 0x02 -#define CPIA2_VP_FRAMERATE_6_25 0x01 - -#define CPIA2_VP4_USER_EFFECTS 0x12 -#define CPIA2_VP5_USER_EFFECTS 0x15 -#define CPIA2_VP_USER_EFFECTS_COLBARS 0x01 -#define CPIA2_VP_USER_EFFECTS_COLBARS_GRAD 0x02 -#define CPIA2_VP_USER_EFFECTS_MIRROR 0x04 -#define CPIA2_VP_USER_EFFECTS_FLIP 0x40 // VP5 only - -/* NOTE: CPIA2_VP_EXPOSURE_MODES shares the same register as VP5 User - * Effects */ -#define CPIA2_VP_EXPOSURE_MODES 0x15 -#define CPIA2_VP_EXPOSURE_MODES_INHIBIT_FLICKER 0x20 -#define CPIA2_VP_EXPOSURE_MODES_COMPILE_EXP 0x10 - -#define CPIA2_VP4_EXPOSURE_TARGET 0x16 // VP4 -#define CPIA2_VP5_EXPOSURE_TARGET 0x20 // VP5 - -#define CPIA2_VP_FLICKER_MODES 0x1B -#define CPIA2_VP_FLICKER_MODES_50HZ 0x80 -#define CPIA2_VP_FLICKER_MODES_CUSTOM_FLT_FFREQ 0x40 -#define CPIA2_VP_FLICKER_MODES_NEVER_FLICKER 0x20 -#define CPIA2_VP_FLICKER_MODES_INHIBIT_RUB 0x10 -#define CPIA2_VP_FLICKER_MODES_ADJUST_LINE_FREQ 0x08 -#define CPIA2_VP_FLICKER_MODES_CUSTOM_INT_FFREQ 0x04 - -#define CPIA2_VP_UMISC 0x1D -#define CPIA2_VP_UMISC_FORCE_MONO 0x80 -#define CPIA2_VP_UMISC_FORCE_ID_MASK 0x40 -#define CPIA2_VP_UMISC_INHIBIT_AUTO_FGS 0x20 -#define CPIA2_VP_UMISC_INHIBIT_AUTO_DIMS 0x08 -#define CPIA2_VP_UMISC_OPT_FOR_SENSOR_DS 0x04 -#define CPIA2_VP_UMISC_INHIBIT_AUTO_MODE_INT 0x02 - -#define CPIA2_VP5_ANTIFLKRSETUP 0x22 //34 - -#define CPIA2_VP_INTERPOLATION 0x24 -#define CPIA2_VP_INTERPOLATION_EVEN_FIRST 0x40 -#define CPIA2_VP_INTERPOLATION_HJOG 0x20 -#define CPIA2_VP_INTERPOLATION_VJOG 0x10 - -#define CPIA2_VP_GAMMA 0x25 -#define CPIA2_VP_DEFAULT_GAMMA 0x10 - -#define CPIA2_VP_YRANGE 0x26 - -#define CPIA2_VP_SATURATION 0x27 - -#define CPIA2_VP5_MYBLACK_LEVEL 0x3A //58 -#define CPIA2_VP5_MCYRANGE 0x3B //59 -#define CPIA2_VP5_MYCEILING 0x3C //60 -#define CPIA2_VP5_MCUVSATURATION 0x3D //61 - - -#define CPIA2_VP_REHASH_VALUES 0x60 - - -/*** - * Common sensor registers - ***/ -#define CPIA2_SENSOR_DEVICE_H 0x00 -#define CPIA2_SENSOR_DEVICE_L 0x01 - -#define CPIA2_SENSOR_DATA_FORMAT 0x16 -#define CPIA2_SENSOR_DATA_FORMAT_HMIRROR 0x08 -#define CPIA2_SENSOR_DATA_FORMAT_VMIRROR 0x10 - -#define CPIA2_SENSOR_CR1 0x76 -#define CPIA2_SENSOR_CR1_STAND_BY 0x01 -#define CPIA2_SENSOR_CR1_DOWN_RAMP_GEN 0x02 -#define CPIA2_SENSOR_CR1_DOWN_COLUMN_ADC 0x04 -#define CPIA2_SENSOR_CR1_DOWN_CAB_REGULATOR 0x08 -#define CPIA2_SENSOR_CR1_DOWN_AUDIO_REGULATOR 0x10 -#define CPIA2_SENSOR_CR1_DOWN_VRT_AMP 0x20 -#define CPIA2_SENSOR_CR1_DOWN_BAND_GAP 0x40 - -#endif diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c deleted file mode 100644 index 95b5d6e7cdc4..000000000000 --- a/drivers/media/video/cpia2/cpia2_usb.c +++ /dev/null @@ -1,955 +0,0 @@ -/**************************************************************************** - * - * Filename: cpia2_usb.c - * - * Copyright 2001, STMicrolectronics, Inc. - * Contact: steve.miller@st.com - * - * Description: - * This is a USB driver for CPia2 based video cameras. - * The infrastructure of this driver is based on the cpia usb driver by - * Jochen Scharrlach and Johannes Erdfeldt. - * - * 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. - * - * Stripped of 2.4 stuff ready for main kernel submit by - * Alan Cox <alan@lxorguk.ukuu.org.uk> - ****************************************************************************/ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/module.h> - -#include "cpia2.h" - -static int frame_sizes[] = { - 0, // USBIF_CMDONLY - 0, // USBIF_BULK - 128, // USBIF_ISO_1 - 384, // USBIF_ISO_2 - 640, // USBIF_ISO_3 - 768, // USBIF_ISO_4 - 896, // USBIF_ISO_5 - 1023, // USBIF_ISO_6 -}; - -#define FRAMES_PER_DESC 10 -#define FRAME_SIZE_PER_DESC frame_sizes[cam->cur_alt] - -static void process_frame(struct camera_data *cam); -static void cpia2_usb_complete(struct urb *urb); -static int cpia2_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id); -static void cpia2_usb_disconnect(struct usb_interface *intf); -static int cpia2_usb_suspend(struct usb_interface *intf, pm_message_t message); -static int cpia2_usb_resume(struct usb_interface *intf); - -static void free_sbufs(struct camera_data *cam); -static void add_APPn(struct camera_data *cam); -static void add_COM(struct camera_data *cam); -static int submit_urbs(struct camera_data *cam); -static int set_alternate(struct camera_data *cam, unsigned int alt); -static int configure_transfer_mode(struct camera_data *cam, unsigned int alt); - -static struct usb_device_id cpia2_id_table[] = { - {USB_DEVICE(0x0553, 0x0100)}, - {USB_DEVICE(0x0553, 0x0140)}, - {USB_DEVICE(0x0553, 0x0151)}, /* STV0676 */ - {} /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(usb, cpia2_id_table); - -static struct usb_driver cpia2_driver = { - .name = "cpia2", - .probe = cpia2_usb_probe, - .disconnect = cpia2_usb_disconnect, - .suspend = cpia2_usb_suspend, - .resume = cpia2_usb_resume, - .reset_resume = cpia2_usb_resume, - .id_table = cpia2_id_table -}; - - -/****************************************************************************** - * - * process_frame - * - *****************************************************************************/ -static void process_frame(struct camera_data *cam) -{ - static int frame_count; - - unsigned char *inbuff = cam->workbuff->data; - - DBG("Processing frame #%d, current:%d\n", - cam->workbuff->num, cam->curbuff->num); - - if(cam->workbuff->length > cam->workbuff->max_length) - cam->workbuff->max_length = cam->workbuff->length; - - if ((inbuff[0] == 0xFF) && (inbuff[1] == 0xD8)) { - frame_count++; - } else { - cam->workbuff->status = FRAME_ERROR; - DBG("Start of frame not found\n"); - return; - } - - /*** - * Now the output buffer should have a JPEG image in it. - ***/ - if(!cam->first_image_seen) { - /* Always skip the first image after streaming - * starts. It is almost certainly corrupt. */ - cam->first_image_seen = 1; - cam->workbuff->status = FRAME_EMPTY; - return; - } - if (cam->workbuff->length > 3) { - if(cam->mmapped && - cam->workbuff->length < cam->workbuff->max_length) { - /* No junk in the buffers */ - memset(cam->workbuff->data+cam->workbuff->length, - 0, cam->workbuff->max_length- - cam->workbuff->length); - } - cam->workbuff->max_length = cam->workbuff->length; - cam->workbuff->status = FRAME_READY; - - if(!cam->mmapped && cam->num_frames > 2) { - /* During normal reading, the most recent - * frame will be read. If the current frame - * hasn't started reading yet, it will never - * be read, so mark it empty. If the buffer is - * mmapped, or we have few buffers, we need to - * wait for the user to free the buffer. - * - * NOTE: This is not entirely foolproof with 3 - * buffers, but it would take an EXTREMELY - * overloaded system to cause problems (possible - * image data corruption). Basically, it would - * need to take more time to execute cpia2_read - * than it would for the camera to send - * cam->num_frames-2 frames before problems - * could occur. - */ - cam->curbuff->status = FRAME_EMPTY; - } - cam->curbuff = cam->workbuff; - cam->workbuff = cam->workbuff->next; - DBG("Changed buffers, work:%d, current:%d\n", - cam->workbuff->num, cam->curbuff->num); - return; - } else { - DBG("Not enough data for an image.\n"); - } - - cam->workbuff->status = FRAME_ERROR; - return; -} - -/****************************************************************************** - * - * add_APPn - * - * Adds a user specified APPn record - *****************************************************************************/ -static void add_APPn(struct camera_data *cam) -{ - if(cam->APP_len > 0) { - cam->workbuff->data[cam->workbuff->length++] = 0xFF; - cam->workbuff->data[cam->workbuff->length++] = 0xE0+cam->APPn; - cam->workbuff->data[cam->workbuff->length++] = 0; - cam->workbuff->data[cam->workbuff->length++] = cam->APP_len+2; - memcpy(cam->workbuff->data+cam->workbuff->length, - cam->APP_data, cam->APP_len); - cam->workbuff->length += cam->APP_len; - } -} - -/****************************************************************************** - * - * add_COM - * - * Adds a user specified COM record - *****************************************************************************/ -static void add_COM(struct camera_data *cam) -{ - if(cam->COM_len > 0) { - cam->workbuff->data[cam->workbuff->length++] = 0xFF; - cam->workbuff->data[cam->workbuff->length++] = 0xFE; - cam->workbuff->data[cam->workbuff->length++] = 0; - cam->workbuff->data[cam->workbuff->length++] = cam->COM_len+2; - memcpy(cam->workbuff->data+cam->workbuff->length, - cam->COM_data, cam->COM_len); - cam->workbuff->length += cam->COM_len; - } -} - -/****************************************************************************** - * - * cpia2_usb_complete - * - * callback when incoming packet is received - *****************************************************************************/ -static void cpia2_usb_complete(struct urb *urb) -{ - int i; - unsigned char *cdata; - static int frame_ready = false; - struct camera_data *cam = (struct camera_data *) urb->context; - - if (urb->status!=0) { - if (!(urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN)) - { - DBG("urb->status = %d!\n", urb->status); - } - DBG("Stopping streaming\n"); - return; - } - - if (!cam->streaming || !video_is_registered(&cam->vdev)) { - LOG("Will now stop the streaming: streaming = %d, present=%d\n", - cam->streaming, video_is_registered(&cam->vdev)); - return; - } - - /*** - * Packet collater - ***/ - //DBG("Collating %d packets\n", urb->number_of_packets); - for (i = 0; i < urb->number_of_packets; i++) { - u16 checksum, iso_checksum; - int j; - int n = urb->iso_frame_desc[i].actual_length; - int st = urb->iso_frame_desc[i].status; - - if(cam->workbuff->status == FRAME_READY) { - struct framebuf *ptr; - /* Try to find an available buffer */ - DBG("workbuff full, searching\n"); - for (ptr = cam->workbuff->next; - ptr != cam->workbuff; - ptr = ptr->next) - { - if (ptr->status == FRAME_EMPTY) { - ptr->status = FRAME_READING; - ptr->length = 0; - break; - } - } - if (ptr == cam->workbuff) - break; /* No READING or EMPTY buffers left */ - - cam->workbuff = ptr; - } - - if (cam->workbuff->status == FRAME_EMPTY || - cam->workbuff->status == FRAME_ERROR) { - cam->workbuff->status = FRAME_READING; - cam->workbuff->length = 0; - } - - //DBG(" Packet %d length = %d, status = %d\n", i, n, st); - cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - - if (st) { - LOG("cpia2 data error: [%d] len=%d, status = %d\n", - i, n, st); - if(!ALLOW_CORRUPT) - cam->workbuff->status = FRAME_ERROR; - continue; - } - - if(n<=2) - continue; - - checksum = 0; - for(j=0; j<n-2; ++j) - checksum += cdata[j]; - iso_checksum = cdata[j] + cdata[j+1]*256; - if(checksum != iso_checksum) { - LOG("checksum mismatch: [%d] len=%d, calculated = %x, checksum = %x\n", - i, n, (int)checksum, (int)iso_checksum); - if(!ALLOW_CORRUPT) { - cam->workbuff->status = FRAME_ERROR; - continue; - } - } - n -= 2; - - if(cam->workbuff->status != FRAME_READING) { - if((0xFF == cdata[0] && 0xD8 == cdata[1]) || - (0xD8 == cdata[0] && 0xFF == cdata[1] && - 0 != cdata[2])) { - /* frame is skipped, but increment total - * frame count anyway */ - cam->frame_count++; - } - DBG("workbuff not reading, status=%d\n", - cam->workbuff->status); - continue; - } - - if (cam->frame_size < cam->workbuff->length + n) { - ERR("buffer overflow! length: %d, n: %d\n", - cam->workbuff->length, n); - cam->workbuff->status = FRAME_ERROR; - if(cam->workbuff->length > cam->workbuff->max_length) - cam->workbuff->max_length = - cam->workbuff->length; - continue; - } - - if (cam->workbuff->length == 0) { - int data_offset; - if ((0xD8 == cdata[0]) && (0xFF == cdata[1])) { - data_offset = 1; - } else if((0xFF == cdata[0]) && (0xD8 == cdata[1]) - && (0xFF == cdata[2])) { - data_offset = 2; - } else { - DBG("Ignoring packet, not beginning!\n"); - continue; - } - DBG("Start of frame pattern found\n"); - do_gettimeofday(&cam->workbuff->timestamp); - cam->workbuff->seq = cam->frame_count++; - cam->workbuff->data[0] = 0xFF; - cam->workbuff->data[1] = 0xD8; - cam->workbuff->length = 2; - add_APPn(cam); - add_COM(cam); - memcpy(cam->workbuff->data+cam->workbuff->length, - cdata+data_offset, n-data_offset); - cam->workbuff->length += n-data_offset; - } else if (cam->workbuff->length > 0) { - memcpy(cam->workbuff->data + cam->workbuff->length, - cdata, n); - cam->workbuff->length += n; - } - - if ((cam->workbuff->length >= 3) && - (cam->workbuff->data[cam->workbuff->length - 3] == 0xFF) && - (cam->workbuff->data[cam->workbuff->length - 2] == 0xD9) && - (cam->workbuff->data[cam->workbuff->length - 1] == 0xFF)) { - frame_ready = true; - cam->workbuff->data[cam->workbuff->length - 1] = 0; - cam->workbuff->length -= 1; - } else if ((cam->workbuff->length >= 2) && - (cam->workbuff->data[cam->workbuff->length - 2] == 0xFF) && - (cam->workbuff->data[cam->workbuff->length - 1] == 0xD9)) { - frame_ready = true; - } - - if (frame_ready) { - DBG("Workbuff image size = %d\n",cam->workbuff->length); - process_frame(cam); - - frame_ready = false; - - if (waitqueue_active(&cam->wq_stream)) - wake_up_interruptible(&cam->wq_stream); - } - } - - if(cam->streaming) { - /* resubmit */ - urb->dev = cam->dev; - if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0) - ERR("%s: usb_submit_urb ret %d!\n", __func__, i); - } -} - -/****************************************************************************** - * - * configure_transfer_mode - * - *****************************************************************************/ -static int configure_transfer_mode(struct camera_data *cam, unsigned int alt) -{ - static unsigned char iso_regs[8][4] = { - {0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00}, - {0xB9, 0x00, 0x00, 0x7E}, - {0xB9, 0x00, 0x01, 0x7E}, - {0xB9, 0x00, 0x02, 0x7E}, - {0xB9, 0x00, 0x02, 0xFE}, - {0xB9, 0x00, 0x03, 0x7E}, - {0xB9, 0x00, 0x03, 0xFD} - }; - struct cpia2_command cmd; - unsigned char reg; - - if (!video_is_registered(&cam->vdev)) - return -ENODEV; - - /*** - * Write the isoc registers according to the alternate selected - ***/ - cmd.direction = TRANSFER_WRITE; - cmd.buffer.block_data[0] = iso_regs[alt][0]; - cmd.buffer.block_data[1] = iso_regs[alt][1]; - cmd.buffer.block_data[2] = iso_regs[alt][2]; - cmd.buffer.block_data[3] = iso_regs[alt][3]; - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; - cmd.start = CPIA2_VC_USB_ISOLIM; - cmd.reg_count = 4; - cpia2_send_command(cam, &cmd); - - /*** - * Enable relevant streams before starting polling. - * First read USB Stream Config Register. - ***/ - cmd.direction = TRANSFER_READ; - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; - cmd.start = CPIA2_VC_USB_STRM; - cmd.reg_count = 1; - cpia2_send_command(cam, &cmd); - reg = cmd.buffer.block_data[0]; - - /* Clear iso, bulk, and int */ - reg &= ~(CPIA2_VC_USB_STRM_BLK_ENABLE | - CPIA2_VC_USB_STRM_ISO_ENABLE | - CPIA2_VC_USB_STRM_INT_ENABLE); - - if (alt == USBIF_BULK) { - DBG("Enabling bulk xfer\n"); - reg |= CPIA2_VC_USB_STRM_BLK_ENABLE; /* Enable Bulk */ - cam->xfer_mode = XFER_BULK; - } else if (alt >= USBIF_ISO_1) { - DBG("Enabling ISOC xfer\n"); - reg |= CPIA2_VC_USB_STRM_ISO_ENABLE; - cam->xfer_mode = XFER_ISOC; - } - - cmd.buffer.block_data[0] = reg; - cmd.direction = TRANSFER_WRITE; - cmd.start = CPIA2_VC_USB_STRM; - cmd.reg_count = 1; - cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; - cpia2_send_command(cam, &cmd); - - return 0; -} - -/****************************************************************************** - * - * cpia2_usb_change_streaming_alternate - * - *****************************************************************************/ -int cpia2_usb_change_streaming_alternate(struct camera_data *cam, - unsigned int alt) -{ - int ret = 0; - - if(alt < USBIF_ISO_1 || alt > USBIF_ISO_6) - return -EINVAL; - - if(alt == cam->params.camera_state.stream_mode) - return 0; - - cpia2_usb_stream_pause(cam); - - configure_transfer_mode(cam, alt); - - cam->params.camera_state.stream_mode = alt; - - /* Reset the camera to prevent image quality degradation */ - cpia2_reset_camera(cam); - - cpia2_usb_stream_resume(cam); - - return ret; -} - -/****************************************************************************** - * - * set_alternate - * - *****************************************************************************/ -static int set_alternate(struct camera_data *cam, unsigned int alt) -{ - int ret = 0; - - if(alt == cam->cur_alt) - return 0; - - if (cam->cur_alt != USBIF_CMDONLY) { - DBG("Changing from alt %d to %d\n", cam->cur_alt, USBIF_CMDONLY); - ret = usb_set_interface(cam->dev, cam->iface, USBIF_CMDONLY); - if (ret != 0) - return ret; - } - if (alt != USBIF_CMDONLY) { - DBG("Changing from alt %d to %d\n", USBIF_CMDONLY, alt); - ret = usb_set_interface(cam->dev, cam->iface, alt); - if (ret != 0) - return ret; - } - - cam->old_alt = cam->cur_alt; - cam->cur_alt = alt; - - return ret; -} - -/****************************************************************************** - * - * free_sbufs - * - * Free all cam->sbuf[]. All non-NULL .data and .urb members that are non-NULL - * are assumed to be allocated. Non-NULL .urb members are also assumed to be - * submitted (and must therefore be killed before they are freed). - *****************************************************************************/ -static void free_sbufs(struct camera_data *cam) -{ - int i; - - for (i = 0; i < NUM_SBUF; i++) { - if(cam->sbuf[i].urb) { - usb_kill_urb(cam->sbuf[i].urb); - usb_free_urb(cam->sbuf[i].urb); - cam->sbuf[i].urb = NULL; - } - if(cam->sbuf[i].data) { - kfree(cam->sbuf[i].data); - cam->sbuf[i].data = NULL; - } - } -} - -/******* -* Convenience functions -*******/ -/**************************************************************************** - * - * write_packet - * - ***************************************************************************/ -static int write_packet(struct usb_device *udev, - u8 request, u8 * registers, u16 start, size_t size) -{ - if (!registers || size <= 0) - return -EINVAL; - - return usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), - request, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - start, /* value */ - 0, /* index */ - registers, /* buffer */ - size, - HZ); -} - -/**************************************************************************** - * - * read_packet - * - ***************************************************************************/ -static int read_packet(struct usb_device *udev, - u8 request, u8 * registers, u16 start, size_t size) -{ - if (!registers || size <= 0) - return -EINVAL; - - return usb_control_msg(udev, - usb_rcvctrlpipe(udev, 0), - request, - USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE, - start, /* value */ - 0, /* index */ - registers, /* buffer */ - size, - HZ); -} - -/****************************************************************************** - * - * cpia2_usb_transfer_cmd - * - *****************************************************************************/ -int cpia2_usb_transfer_cmd(struct camera_data *cam, - void *registers, - u8 request, u8 start, u8 count, u8 direction) -{ - int err = 0; - struct usb_device *udev = cam->dev; - - if (!udev) { - ERR("%s: Internal driver error: udev is NULL\n", __func__); - return -EINVAL; - } - - if (!registers) { - ERR("%s: Internal driver error: register array is NULL\n", __func__); - return -EINVAL; - } - - if (direction == TRANSFER_READ) { - err = read_packet(udev, request, (u8 *)registers, start, count); - if (err > 0) - err = 0; - } else if (direction == TRANSFER_WRITE) { - err =write_packet(udev, request, (u8 *)registers, start, count); - if (err < 0) { - LOG("Control message failed, err val = %d\n", err); - LOG("Message: request = 0x%0X, start = 0x%0X\n", - request, start); - LOG("Message: count = %d, register[0] = 0x%0X\n", - count, ((unsigned char *) registers)[0]); - } else - err=0; - } else { - LOG("Unexpected first byte of direction: %d\n", - direction); - return -EINVAL; - } - - if(err != 0) - LOG("Unexpected error: %d\n", err); - return err; -} - - -/****************************************************************************** - * - * submit_urbs - * - *****************************************************************************/ -static int submit_urbs(struct camera_data *cam) -{ - struct urb *urb; - int fx, err, i, j; - - for(i=0; i<NUM_SBUF; ++i) { - if (cam->sbuf[i].data) - continue; - cam->sbuf[i].data = - kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); - if (!cam->sbuf[i].data) { - while (--i >= 0) { - kfree(cam->sbuf[i].data); - cam->sbuf[i].data = NULL; - } - return -ENOMEM; - } - } - - /* We double buffer the Isoc lists, and also know the polling - * interval is every frame (1 == (1 << (bInterval -1))). - */ - for(i=0; i<NUM_SBUF; ++i) { - if(cam->sbuf[i].urb) { - continue; - } - urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); - if (!urb) { - ERR("%s: usb_alloc_urb error!\n", __func__); - for (j = 0; j < i; j++) - usb_free_urb(cam->sbuf[j].urb); - return -ENOMEM; - } - - cam->sbuf[i].urb = urb; - urb->dev = cam->dev; - urb->context = cam; - urb->pipe = usb_rcvisocpipe(cam->dev, 1 /*ISOC endpoint*/); - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = cam->sbuf[i].data; - urb->complete = cpia2_usb_complete; - urb->number_of_packets = FRAMES_PER_DESC; - urb->interval = 1; - urb->transfer_buffer_length = - FRAME_SIZE_PER_DESC * FRAMES_PER_DESC; - - for (fx = 0; fx < FRAMES_PER_DESC; fx++) { - urb->iso_frame_desc[fx].offset = - FRAME_SIZE_PER_DESC * fx; - urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC; - } - } - - - /* Queue the ISO urbs, and resubmit in the completion handler */ - for(i=0; i<NUM_SBUF; ++i) { - err = usb_submit_urb(cam->sbuf[i].urb, GFP_KERNEL); - if (err) { - ERR("usb_submit_urb[%d]() = %d\n", i, err); - return err; - } - } - - return 0; -} - -/****************************************************************************** - * - * cpia2_usb_stream_start - * - *****************************************************************************/ -int cpia2_usb_stream_start(struct camera_data *cam, unsigned int alternate) -{ - int ret; - int old_alt; - - if(cam->streaming) - return 0; - - if (cam->flush) { - int i; - DBG("Flushing buffers\n"); - for(i=0; i<cam->num_frames; ++i) { - cam->buffers[i].status = FRAME_EMPTY; - cam->buffers[i].length = 0; - } - cam->curbuff = &cam->buffers[0]; - cam->workbuff = cam->curbuff->next; - cam->flush = false; - } - - old_alt = cam->params.camera_state.stream_mode; - cam->params.camera_state.stream_mode = 0; - ret = cpia2_usb_change_streaming_alternate(cam, alternate); - if (ret < 0) { - int ret2; - ERR("cpia2_usb_change_streaming_alternate() = %d!\n", ret); - cam->params.camera_state.stream_mode = old_alt; - ret2 = set_alternate(cam, USBIF_CMDONLY); - if (ret2 < 0) { - ERR("cpia2_usb_change_streaming_alternate(%d) =%d has already " - "failed. Then tried to call " - "set_alternate(USBIF_CMDONLY) = %d.\n", - alternate, ret, ret2); - } - } else { - cam->frame_count = 0; - cam->streaming = 1; - ret = cpia2_usb_stream_resume(cam); - } - return ret; -} - -/****************************************************************************** - * - * cpia2_usb_stream_pause - * - *****************************************************************************/ -int cpia2_usb_stream_pause(struct camera_data *cam) -{ - int ret = 0; - if(cam->streaming) { - free_sbufs(cam); - ret = set_alternate(cam, USBIF_CMDONLY); - } - return ret; -} - -/****************************************************************************** - * - * cpia2_usb_stream_resume - * - *****************************************************************************/ -int cpia2_usb_stream_resume(struct camera_data *cam) -{ - int ret = 0; - if(cam->streaming) { - cam->first_image_seen = 0; - ret = set_alternate(cam, cam->params.camera_state.stream_mode); - if(ret == 0) { - /* for some reason the user effects need to be set - again when starting streaming. */ - cpia2_do_command(cam, CPIA2_CMD_SET_USER_EFFECTS, TRANSFER_WRITE, - cam->params.vp_params.user_effects); - ret = submit_urbs(cam); - } - } - return ret; -} - -/****************************************************************************** - * - * cpia2_usb_stream_stop - * - *****************************************************************************/ -int cpia2_usb_stream_stop(struct camera_data *cam) -{ - int ret; - - ret = cpia2_usb_stream_pause(cam); - cam->streaming = 0; - configure_transfer_mode(cam, 0); - return ret; -} - -/****************************************************************************** - * - * cpia2_usb_probe - * - * Probe and initialize. - *****************************************************************************/ -static int cpia2_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct usb_interface_descriptor *interface; - struct camera_data *cam; - int ret; - - /* A multi-config CPiA2 camera? */ - if (udev->descriptor.bNumConfigurations != 1) - return -ENODEV; - interface = &intf->cur_altsetting->desc; - - /* If we get to this point, we found a CPiA2 camera */ - LOG("CPiA2 USB camera found\n"); - - cam = cpia2_init_camera_struct(intf); - if (cam == NULL) - return -ENOMEM; - - cam->dev = udev; - cam->iface = interface->bInterfaceNumber; - - ret = set_alternate(cam, USBIF_CMDONLY); - if (ret < 0) { - ERR("%s: usb_set_interface error (ret = %d)\n", __func__, ret); - kfree(cam); - return ret; - } - - - if((ret = cpia2_init_camera(cam)) < 0) { - ERR("%s: failed to initialize cpia2 camera (ret = %d)\n", __func__, ret); - kfree(cam); - return ret; - } - LOG(" CPiA Version: %d.%02d (%d.%d)\n", - cam->params.version.firmware_revision_hi, - cam->params.version.firmware_revision_lo, - cam->params.version.asic_id, - cam->params.version.asic_rev); - LOG(" CPiA PnP-ID: %04x:%04x:%04x\n", - cam->params.pnp_id.vendor, - cam->params.pnp_id.product, - cam->params.pnp_id.device_revision); - LOG(" SensorID: %d.(version %d)\n", - cam->params.version.sensor_flags, - cam->params.version.sensor_rev); - - usb_set_intfdata(intf, cam); - - ret = cpia2_register_camera(cam); - if (ret < 0) { - ERR("%s: Failed to register cpia2 camera (ret = %d)\n", __func__, ret); - kfree(cam); - return ret; - } - - return 0; -} - -/****************************************************************************** - * - * cpia2_disconnect - * - *****************************************************************************/ -static void cpia2_usb_disconnect(struct usb_interface *intf) -{ - struct camera_data *cam = usb_get_intfdata(intf); - usb_set_intfdata(intf, NULL); - - DBG("Stopping stream\n"); - cpia2_usb_stream_stop(cam); - - mutex_lock(&cam->v4l2_lock); - DBG("Unregistering camera\n"); - cpia2_unregister_camera(cam); - v4l2_device_disconnect(&cam->v4l2_dev); - mutex_unlock(&cam->v4l2_lock); - v4l2_device_put(&cam->v4l2_dev); - - if(cam->buffers) { - DBG("Wakeup waiting processes\n"); - cam->curbuff->status = FRAME_READY; - cam->curbuff->length = 0; - if (waitqueue_active(&cam->wq_stream)) - wake_up_interruptible(&cam->wq_stream); - } - - DBG("Releasing interface\n"); - usb_driver_release_interface(&cpia2_driver, intf); - - LOG("CPiA2 camera disconnected.\n"); -} - -static int cpia2_usb_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct camera_data *cam = usb_get_intfdata(intf); - - mutex_lock(&cam->v4l2_lock); - if (cam->streaming) { - cpia2_usb_stream_stop(cam); - cam->streaming = 1; - } - mutex_unlock(&cam->v4l2_lock); - - dev_info(&intf->dev, "going into suspend..\n"); - return 0; -} - -/* Resume device - start device. */ -static int cpia2_usb_resume(struct usb_interface *intf) -{ - struct camera_data *cam = usb_get_intfdata(intf); - - mutex_lock(&cam->v4l2_lock); - v4l2_ctrl_handler_setup(&cam->hdl); - if (cam->streaming) { - cam->streaming = 0; - cpia2_usb_stream_start(cam, - cam->params.camera_state.stream_mode); - } - mutex_unlock(&cam->v4l2_lock); - - dev_info(&intf->dev, "coming out of suspend..\n"); - return 0; -} - -/****************************************************************************** - * - * usb_cpia2_init - * - *****************************************************************************/ -int cpia2_usb_init(void) -{ - return usb_register(&cpia2_driver); -} - -/****************************************************************************** - * - * usb_cpia_cleanup - * - *****************************************************************************/ -void cpia2_usb_cleanup(void) -{ - schedule_timeout(2 * HZ); - usb_deregister(&cpia2_driver); -} diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c deleted file mode 100644 index 5ca6f44b4c63..000000000000 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ /dev/null @@ -1,1267 +0,0 @@ -/**************************************************************************** - * - * Filename: cpia2_v4l.c - * - * Copyright 2001, STMicrolectronics, Inc. - * Contact: steve.miller@st.com - * Copyright 2001,2005, Scott J. Bertin <scottbertin@yahoo.com> - * - * Description: - * This is a USB driver for CPia2 based video cameras. - * The infrastructure of this driver is based on the cpia usb driver by - * Jochen Scharrlach and Johannes Erdfeldt. - * - * 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. - * - * Stripped of 2.4 stuff ready for main kernel submit by - * Alan Cox <alan@lxorguk.ukuu.org.uk> - ****************************************************************************/ - -#define CPIA_VERSION "3.0.1" - -#include <linux/module.h> -#include <linux/time.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/videodev2.h> -#include <linux/stringify.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-event.h> - -#include "cpia2.h" - -static int video_nr = -1; -module_param(video_nr, int, 0); -MODULE_PARM_DESC(video_nr, "video device to register (0=/dev/video0, etc)"); - -static int buffer_size = 68 * 1024; -module_param(buffer_size, int, 0); -MODULE_PARM_DESC(buffer_size, "Size for each frame buffer in bytes (default 68k)"); - -static int num_buffers = 3; -module_param(num_buffers, int, 0); -MODULE_PARM_DESC(num_buffers, "Number of frame buffers (1-" - __stringify(VIDEO_MAX_FRAME) ", default 3)"); - -static int alternate = DEFAULT_ALT; -module_param(alternate, int, 0); -MODULE_PARM_DESC(alternate, "USB Alternate (" __stringify(USBIF_ISO_1) "-" - __stringify(USBIF_ISO_6) ", default " - __stringify(DEFAULT_ALT) ")"); - -static int flicker_mode; -module_param(flicker_mode, int, 0); -MODULE_PARM_DESC(flicker_mode, "Flicker frequency (0 (disabled), " __stringify(50) " or " - __stringify(60) ", default 0)"); - -MODULE_AUTHOR("Steve Miller (STMicroelectronics) <steve.miller@st.com>"); -MODULE_DESCRIPTION("V4L-driver for STMicroelectronics CPiA2 based cameras"); -MODULE_SUPPORTED_DEVICE("video"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(CPIA_VERSION); - -#define ABOUT "V4L-Driver for Vision CPiA2 based cameras" -#define CPIA2_CID_USB_ALT (V4L2_CID_USER_BASE | 0xf000) - -/****************************************************************************** - * - * cpia2_open - * - *****************************************************************************/ -static int cpia2_open(struct file *file) -{ - struct camera_data *cam = video_drvdata(file); - int retval; - - if (mutex_lock_interruptible(&cam->v4l2_lock)) - return -ERESTARTSYS; - retval = v4l2_fh_open(file); - if (retval) - goto open_unlock; - - if (v4l2_fh_is_singular_file(file)) { - if (cpia2_allocate_buffers(cam)) { - v4l2_fh_release(file); - retval = -ENOMEM; - goto open_unlock; - } - - /* reset the camera */ - if (cpia2_reset_camera(cam) < 0) { - v4l2_fh_release(file); - retval = -EIO; - goto open_unlock; - } - - cam->APP_len = 0; - cam->COM_len = 0; - } - - cpia2_dbg_dump_registers(cam); -open_unlock: - mutex_unlock(&cam->v4l2_lock); - return retval; -} - -/****************************************************************************** - * - * cpia2_close - * - *****************************************************************************/ -static int cpia2_close(struct file *file) -{ - struct video_device *dev = video_devdata(file); - struct camera_data *cam = video_get_drvdata(dev); - - mutex_lock(&cam->v4l2_lock); - if (video_is_registered(&cam->vdev) && v4l2_fh_is_singular_file(file)) { - cpia2_usb_stream_stop(cam); - - /* save camera state for later open */ - cpia2_save_camera_state(cam); - - cpia2_set_low_power(cam); - cpia2_free_buffers(cam); - } - - if (cam->stream_fh == file->private_data) { - cam->stream_fh = NULL; - cam->mmapped = 0; - } - mutex_unlock(&cam->v4l2_lock); - return v4l2_fh_release(file); -} - -/****************************************************************************** - * - * cpia2_v4l_read - * - *****************************************************************************/ -static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count, - loff_t *off) -{ - struct camera_data *cam = video_drvdata(file); - int noblock = file->f_flags&O_NONBLOCK; - ssize_t ret; - - if(!cam) - return -EINVAL; - - if (mutex_lock_interruptible(&cam->v4l2_lock)) - return -ERESTARTSYS; - ret = cpia2_read(cam, buf, count, noblock); - mutex_unlock(&cam->v4l2_lock); - return ret; -} - - -/****************************************************************************** - * - * cpia2_v4l_poll - * - *****************************************************************************/ -static unsigned int cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait) -{ - struct camera_data *cam = video_drvdata(filp); - unsigned int res; - - mutex_lock(&cam->v4l2_lock); - res = cpia2_poll(cam, filp, wait); - mutex_unlock(&cam->v4l2_lock); - return res; -} - - -static int sync(struct camera_data *cam, int frame_nr) -{ - struct framebuf *frame = &cam->buffers[frame_nr]; - - while (1) { - if (frame->status == FRAME_READY) - return 0; - - if (!cam->streaming) { - frame->status = FRAME_READY; - frame->length = 0; - return 0; - } - - mutex_unlock(&cam->v4l2_lock); - wait_event_interruptible(cam->wq_stream, - !cam->streaming || - frame->status == FRAME_READY); - mutex_lock(&cam->v4l2_lock); - if (signal_pending(current)) - return -ERESTARTSYS; - if (!video_is_registered(&cam->vdev)) - return -ENOTTY; - } -} - -/****************************************************************************** - * - * ioctl_querycap - * - * V4L2 device capabilities - * - *****************************************************************************/ - -static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *vc) -{ - struct camera_data *cam = video_drvdata(file); - - strcpy(vc->driver, "cpia2"); - - if (cam->params.pnp_id.product == 0x151) - strcpy(vc->card, "QX5 Microscope"); - else - strcpy(vc->card, "CPiA2 Camera"); - switch (cam->params.pnp_id.device_type) { - case DEVICE_STV_672: - strcat(vc->card, " (672/"); - break; - case DEVICE_STV_676: - strcat(vc->card, " (676/"); - break; - default: - strcat(vc->card, " (XXX/"); - break; - } - switch (cam->params.version.sensor_flags) { - case CPIA2_VP_SENSOR_FLAGS_404: - strcat(vc->card, "404)"); - break; - case CPIA2_VP_SENSOR_FLAGS_407: - strcat(vc->card, "407)"); - break; - case CPIA2_VP_SENSOR_FLAGS_409: - strcat(vc->card, "409)"); - break; - case CPIA2_VP_SENSOR_FLAGS_410: - strcat(vc->card, "410)"); - break; - case CPIA2_VP_SENSOR_FLAGS_500: - strcat(vc->card, "500)"); - break; - default: - strcat(vc->card, "XXX)"); - break; - } - - if (usb_make_path(cam->dev, vc->bus_info, sizeof(vc->bus_info)) <0) - memset(vc->bus_info,0, sizeof(vc->bus_info)); - - vc->device_caps = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - vc->capabilities = vc->device_caps | - V4L2_CAP_DEVICE_CAPS; - - return 0; -} - -/****************************************************************************** - * - * ioctl_input - * - * V4L2 input get/set/enumerate - * - *****************************************************************************/ - -static int cpia2_enum_input(struct file *file, void *fh, struct v4l2_input *i) -{ - if (i->index) - return -EINVAL; - strcpy(i->name, "Camera"); - i->type = V4L2_INPUT_TYPE_CAMERA; - return 0; -} - -static int cpia2_g_input(struct file *file, void *fh, unsigned int *i) -{ - *i = 0; - return 0; -} - -static int cpia2_s_input(struct file *file, void *fh, unsigned int i) -{ - return i ? -EINVAL : 0; -} - -/****************************************************************************** - * - * ioctl_enum_fmt - * - * V4L2 format enumerate - * - *****************************************************************************/ - -static int cpia2_enum_fmt_vid_cap(struct file *file, void *fh, - struct v4l2_fmtdesc *f) -{ - int index = f->index; - - if (index < 0 || index > 1) - return -EINVAL; - - memset(f, 0, sizeof(*f)); - f->index = index; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - f->flags = V4L2_FMT_FLAG_COMPRESSED; - switch(index) { - case 0: - strcpy(f->description, "MJPEG"); - f->pixelformat = V4L2_PIX_FMT_MJPEG; - break; - case 1: - strcpy(f->description, "JPEG"); - f->pixelformat = V4L2_PIX_FMT_JPEG; - break; - default: - return -EINVAL; - } - - return 0; -} - -/****************************************************************************** - * - * ioctl_try_fmt - * - * V4L2 format try - * - *****************************************************************************/ - -static int cpia2_try_fmt_vid_cap(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct camera_data *cam = video_drvdata(file); - - if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG && - f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) - return -EINVAL; - - f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = cam->frame_size; - f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; - f->fmt.pix.priv = 0; - - switch (cpia2_match_video_size(f->fmt.pix.width, f->fmt.pix.height)) { - case VIDEOSIZE_VGA: - f->fmt.pix.width = 640; - f->fmt.pix.height = 480; - break; - case VIDEOSIZE_CIF: - f->fmt.pix.width = 352; - f->fmt.pix.height = 288; - break; - case VIDEOSIZE_QVGA: - f->fmt.pix.width = 320; - f->fmt.pix.height = 240; - break; - case VIDEOSIZE_288_216: - f->fmt.pix.width = 288; - f->fmt.pix.height = 216; - break; - case VIDEOSIZE_256_192: - f->fmt.pix.width = 256; - f->fmt.pix.height = 192; - break; - case VIDEOSIZE_224_168: - f->fmt.pix.width = 224; - f->fmt.pix.height = 168; - break; - case VIDEOSIZE_192_144: - f->fmt.pix.width = 192; - f->fmt.pix.height = 144; - break; - case VIDEOSIZE_QCIF: - default: - f->fmt.pix.width = 176; - f->fmt.pix.height = 144; - break; - } - - return 0; -} - -/****************************************************************************** - * - * ioctl_set_fmt - * - * V4L2 format set - * - *****************************************************************************/ - -static int cpia2_s_fmt_vid_cap(struct file *file, void *_fh, - struct v4l2_format *f) -{ - struct camera_data *cam = video_drvdata(file); - int err, frame; - - err = cpia2_try_fmt_vid_cap(file, _fh, f); - if(err != 0) - return err; - - cam->pixelformat = f->fmt.pix.pixelformat; - - /* NOTE: This should be set to 1 for MJPEG, but some apps don't handle - * the missing Huffman table properly. */ - cam->params.compression.inhibit_htables = 0; - /*f->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG;*/ - - /* we set the video window to something smaller or equal to what - * is requested by the user??? - */ - DBG("Requested width = %d, height = %d\n", - f->fmt.pix.width, f->fmt.pix.height); - if (f->fmt.pix.width != cam->width || - f->fmt.pix.height != cam->height) { - cam->width = f->fmt.pix.width; - cam->height = f->fmt.pix.height; - cam->params.roi.width = f->fmt.pix.width; - cam->params.roi.height = f->fmt.pix.height; - cpia2_set_format(cam); - } - - for (frame = 0; frame < cam->num_frames; ++frame) { - if (cam->buffers[frame].status == FRAME_READING) - if ((err = sync(cam, frame)) < 0) - return err; - - cam->buffers[frame].status = FRAME_EMPTY; - } - - return 0; -} - -/****************************************************************************** - * - * ioctl_get_fmt - * - * V4L2 format get - * - *****************************************************************************/ - -static int cpia2_g_fmt_vid_cap(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct camera_data *cam = video_drvdata(file); - - f->fmt.pix.width = cam->width; - f->fmt.pix.height = cam->height; - f->fmt.pix.pixelformat = cam->pixelformat; - f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = cam->frame_size; - f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; - f->fmt.pix.priv = 0; - - return 0; -} - -/****************************************************************************** - * - * ioctl_cropcap - * - * V4L2 query cropping capabilities - * NOTE: cropping is currently disabled - * - *****************************************************************************/ - -static int cpia2_cropcap(struct file *file, void *fh, struct v4l2_cropcap *c) -{ - struct camera_data *cam = video_drvdata(file); - - if (c->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - c->bounds.left = 0; - c->bounds.top = 0; - c->bounds.width = cam->width; - c->bounds.height = cam->height; - c->defrect.left = 0; - c->defrect.top = 0; - c->defrect.width = cam->width; - c->defrect.height = cam->height; - c->pixelaspect.numerator = 1; - c->pixelaspect.denominator = 1; - - return 0; -} - -struct framerate_info { - int value; - struct v4l2_fract period; -}; - -static const struct framerate_info framerate_controls[] = { - { CPIA2_VP_FRAMERATE_6_25, { 4, 25 } }, - { CPIA2_VP_FRAMERATE_7_5, { 2, 15 } }, - { CPIA2_VP_FRAMERATE_12_5, { 2, 25 } }, - { CPIA2_VP_FRAMERATE_15, { 1, 15 } }, - { CPIA2_VP_FRAMERATE_25, { 1, 25 } }, - { CPIA2_VP_FRAMERATE_30, { 1, 30 } }, -}; - -static int cpia2_g_parm(struct file *file, void *fh, struct v4l2_streamparm *p) -{ - struct camera_data *cam = video_drvdata(file); - struct v4l2_captureparm *cap = &p->parm.capture; - int i; - - if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - cap->capability = V4L2_CAP_TIMEPERFRAME; - cap->readbuffers = cam->num_frames; - for (i = 0; i < ARRAY_SIZE(framerate_controls); i++) - if (cam->params.vp_params.frame_rate == framerate_controls[i].value) { - cap->timeperframe = framerate_controls[i].period; - break; - } - return 0; -} - -static int cpia2_s_parm(struct file *file, void *fh, struct v4l2_streamparm *p) -{ - struct camera_data *cam = video_drvdata(file); - struct v4l2_captureparm *cap = &p->parm.capture; - struct v4l2_fract tpf = cap->timeperframe; - int max = ARRAY_SIZE(framerate_controls) - 1; - int ret; - int i; - - ret = cpia2_g_parm(file, fh, p); - if (ret || !tpf.denominator || !tpf.numerator) - return ret; - - /* Maximum 15 fps for this model */ - if (cam->params.pnp_id.device_type == DEVICE_STV_672 && - cam->params.version.sensor_flags == CPIA2_VP_SENSOR_FLAGS_500) - max -= 2; - for (i = 0; i <= max; i++) { - struct v4l2_fract f1 = tpf; - struct v4l2_fract f2 = framerate_controls[i].period; - - f1.numerator *= f2.denominator; - f2.numerator *= f1.denominator; - if (f1.numerator >= f2.numerator) - break; - } - if (i > max) - i = max; - cap->timeperframe = framerate_controls[i].period; - return cpia2_set_fps(cam, framerate_controls[i].value); -} - -static const struct { - u32 width; - u32 height; -} cpia2_framesizes[] = { - { 640, 480 }, - { 352, 288 }, - { 320, 240 }, - { 288, 216 }, - { 256, 192 }, - { 224, 168 }, - { 192, 144 }, - { 176, 144 }, -}; - -static int cpia2_enum_framesizes(struct file *file, void *fh, - struct v4l2_frmsizeenum *fsize) -{ - - if (fsize->pixel_format != V4L2_PIX_FMT_MJPEG && - fsize->pixel_format != V4L2_PIX_FMT_JPEG) - return -EINVAL; - if (fsize->index >= ARRAY_SIZE(cpia2_framesizes)) - return -EINVAL; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - fsize->discrete.width = cpia2_framesizes[fsize->index].width; - fsize->discrete.height = cpia2_framesizes[fsize->index].height; - - return 0; -} - -static int cpia2_enum_frameintervals(struct file *file, void *fh, - struct v4l2_frmivalenum *fival) -{ - struct camera_data *cam = video_drvdata(file); - int max = ARRAY_SIZE(framerate_controls) - 1; - int i; - - if (fival->pixel_format != V4L2_PIX_FMT_MJPEG && - fival->pixel_format != V4L2_PIX_FMT_JPEG) - return -EINVAL; - - /* Maximum 15 fps for this model */ - if (cam->params.pnp_id.device_type == DEVICE_STV_672 && - cam->params.version.sensor_flags == CPIA2_VP_SENSOR_FLAGS_500) - max -= 2; - if (fival->index > max) - return -EINVAL; - for (i = 0; i < ARRAY_SIZE(cpia2_framesizes); i++) - if (fival->width == cpia2_framesizes[i].width && - fival->height == cpia2_framesizes[i].height) - break; - if (i == ARRAY_SIZE(cpia2_framesizes)) - return -EINVAL; - fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; - fival->discrete = framerate_controls[fival->index].period; - return 0; -} - -/****************************************************************************** - * - * ioctl_s_ctrl - * - * V4L2 set the value of a control variable - * - *****************************************************************************/ - -static int cpia2_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct camera_data *cam = - container_of(ctrl->handler, struct camera_data, hdl); - static const int flicker_table[] = { - NEVER_FLICKER, - FLICKER_50, - FLICKER_60, - }; - - DBG("Set control id:%d, value:%d\n", ctrl->id, ctrl->val); - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - cpia2_set_brightness(cam, ctrl->val); - break; - case V4L2_CID_CONTRAST: - cpia2_set_contrast(cam, ctrl->val); - break; - case V4L2_CID_SATURATION: - cpia2_set_saturation(cam, ctrl->val); - break; - case V4L2_CID_HFLIP: - cpia2_set_property_mirror(cam, ctrl->val); - break; - case V4L2_CID_VFLIP: - cpia2_set_property_flip(cam, ctrl->val); - break; - case V4L2_CID_POWER_LINE_FREQUENCY: - return cpia2_set_flicker_mode(cam, flicker_table[ctrl->val]); - case V4L2_CID_ILLUMINATORS_1: - return cpia2_set_gpio(cam, (cam->top_light->val << 6) | - (cam->bottom_light->val << 7)); - case V4L2_CID_JPEG_ACTIVE_MARKER: - cam->params.compression.inhibit_htables = - !(ctrl->val & V4L2_JPEG_ACTIVE_MARKER_DHT); - break; - case V4L2_CID_JPEG_COMPRESSION_QUALITY: - cam->params.vc_params.quality = ctrl->val; - break; - case CPIA2_CID_USB_ALT: - cam->params.camera_state.stream_mode = ctrl->val; - break; - default: - return -EINVAL; - } - - return 0; -} - -/****************************************************************************** - * - * ioctl_g_jpegcomp - * - * V4L2 get the JPEG compression parameters - * - *****************************************************************************/ - -static int cpia2_g_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompression *parms) -{ - struct camera_data *cam = video_drvdata(file); - - memset(parms, 0, sizeof(*parms)); - - parms->quality = 80; // TODO: Can this be made meaningful? - - parms->jpeg_markers = V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI; - if(!cam->params.compression.inhibit_htables) { - parms->jpeg_markers |= V4L2_JPEG_MARKER_DHT; - } - - parms->APPn = cam->APPn; - parms->APP_len = cam->APP_len; - if(cam->APP_len > 0) { - memcpy(parms->APP_data, cam->APP_data, cam->APP_len); - parms->jpeg_markers |= V4L2_JPEG_MARKER_APP; - } - - parms->COM_len = cam->COM_len; - if(cam->COM_len > 0) { - memcpy(parms->COM_data, cam->COM_data, cam->COM_len); - parms->jpeg_markers |= JPEG_MARKER_COM; - } - - DBG("G_JPEGCOMP APP_len:%d COM_len:%d\n", - parms->APP_len, parms->COM_len); - - return 0; -} - -/****************************************************************************** - * - * ioctl_s_jpegcomp - * - * V4L2 set the JPEG compression parameters - * NOTE: quality and some jpeg_markers are ignored. - * - *****************************************************************************/ - -static int cpia2_s_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompression *parms) -{ - struct camera_data *cam = video_drvdata(file); - - DBG("S_JPEGCOMP APP_len:%d COM_len:%d\n", - parms->APP_len, parms->COM_len); - - cam->params.compression.inhibit_htables = - !(parms->jpeg_markers & V4L2_JPEG_MARKER_DHT); - parms->jpeg_markers &= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI | - V4L2_JPEG_MARKER_DHT; - - if(parms->APP_len != 0) { - if(parms->APP_len > 0 && - parms->APP_len <= sizeof(cam->APP_data) && - parms->APPn >= 0 && parms->APPn <= 15) { - cam->APPn = parms->APPn; - cam->APP_len = parms->APP_len; - memcpy(cam->APP_data, parms->APP_data, parms->APP_len); - } else { - LOG("Bad APPn Params n=%d len=%d\n", - parms->APPn, parms->APP_len); - return -EINVAL; - } - } else { - cam->APP_len = 0; - } - - if(parms->COM_len != 0) { - if(parms->COM_len > 0 && - parms->COM_len <= sizeof(cam->COM_data)) { - cam->COM_len = parms->COM_len; - memcpy(cam->COM_data, parms->COM_data, parms->COM_len); - } else { - LOG("Bad COM_len=%d\n", parms->COM_len); - return -EINVAL; - } - } - - return 0; -} - -/****************************************************************************** - * - * ioctl_reqbufs - * - * V4L2 Initiate memory mapping. - * NOTE: The user's request is ignored. For now the buffers are fixed. - * - *****************************************************************************/ - -static int cpia2_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *req) -{ - struct camera_data *cam = video_drvdata(file); - - if(req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - req->memory != V4L2_MEMORY_MMAP) - return -EINVAL; - - DBG("REQBUFS requested:%d returning:%d\n", req->count, cam->num_frames); - req->count = cam->num_frames; - memset(&req->reserved, 0, sizeof(req->reserved)); - - return 0; -} - -/****************************************************************************** - * - * ioctl_querybuf - * - * V4L2 Query memory buffer status. - * - *****************************************************************************/ - -static int cpia2_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf) -{ - struct camera_data *cam = video_drvdata(file); - - if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - buf->index > cam->num_frames) - return -EINVAL; - - buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer; - buf->length = cam->frame_size; - - buf->memory = V4L2_MEMORY_MMAP; - - if(cam->mmapped) - buf->flags = V4L2_BUF_FLAG_MAPPED; - else - buf->flags = 0; - - switch (cam->buffers[buf->index].status) { - case FRAME_EMPTY: - case FRAME_ERROR: - case FRAME_READING: - buf->bytesused = 0; - buf->flags = V4L2_BUF_FLAG_QUEUED; - break; - case FRAME_READY: - buf->bytesused = cam->buffers[buf->index].length; - buf->timestamp = cam->buffers[buf->index].timestamp; - buf->sequence = cam->buffers[buf->index].seq; - buf->flags = V4L2_BUF_FLAG_DONE; - break; - } - - DBG("QUERYBUF index:%d offset:%d flags:%d seq:%d bytesused:%d\n", - buf->index, buf->m.offset, buf->flags, buf->sequence, - buf->bytesused); - - return 0; -} - -/****************************************************************************** - * - * ioctl_qbuf - * - * V4L2 User is freeing buffer - * - *****************************************************************************/ - -static int cpia2_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) -{ - struct camera_data *cam = video_drvdata(file); - - if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - buf->memory != V4L2_MEMORY_MMAP || - buf->index > cam->num_frames) - return -EINVAL; - - DBG("QBUF #%d\n", buf->index); - - if(cam->buffers[buf->index].status == FRAME_READY) - cam->buffers[buf->index].status = FRAME_EMPTY; - - return 0; -} - -/****************************************************************************** - * - * find_earliest_filled_buffer - * - * Helper for ioctl_dqbuf. Find the next ready buffer. - * - *****************************************************************************/ - -static int find_earliest_filled_buffer(struct camera_data *cam) -{ - int i; - int found = -1; - for (i=0; i<cam->num_frames; i++) { - if(cam->buffers[i].status == FRAME_READY) { - if(found < 0) { - found = i; - } else { - /* find which buffer is earlier */ - struct timeval *tv1, *tv2; - tv1 = &cam->buffers[i].timestamp; - tv2 = &cam->buffers[found].timestamp; - if(tv1->tv_sec < tv2->tv_sec || - (tv1->tv_sec == tv2->tv_sec && - tv1->tv_usec < tv2->tv_usec)) - found = i; - } - } - } - return found; -} - -/****************************************************************************** - * - * ioctl_dqbuf - * - * V4L2 User is asking for a filled buffer. - * - *****************************************************************************/ - -static int cpia2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) -{ - struct camera_data *cam = video_drvdata(file); - int frame; - - if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - buf->memory != V4L2_MEMORY_MMAP) - return -EINVAL; - - frame = find_earliest_filled_buffer(cam); - - if(frame < 0 && file->f_flags&O_NONBLOCK) - return -EAGAIN; - - if(frame < 0) { - /* Wait for a frame to become available */ - struct framebuf *cb=cam->curbuff; - mutex_unlock(&cam->v4l2_lock); - wait_event_interruptible(cam->wq_stream, - !video_is_registered(&cam->vdev) || - (cb=cam->curbuff)->status == FRAME_READY); - mutex_lock(&cam->v4l2_lock); - if (signal_pending(current)) - return -ERESTARTSYS; - if (!video_is_registered(&cam->vdev)) - return -ENOTTY; - frame = cb->num; - } - - - buf->index = frame; - buf->bytesused = cam->buffers[buf->index].length; - buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE; - buf->field = V4L2_FIELD_NONE; - buf->timestamp = cam->buffers[buf->index].timestamp; - buf->sequence = cam->buffers[buf->index].seq; - buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer; - buf->length = cam->frame_size; - buf->reserved2 = 0; - buf->reserved = 0; - memset(&buf->timecode, 0, sizeof(buf->timecode)); - - DBG("DQBUF #%d status:%d seq:%d length:%d\n", buf->index, - cam->buffers[buf->index].status, buf->sequence, buf->bytesused); - - return 0; -} - -static int cpia2_streamon(struct file *file, void *fh, enum v4l2_buf_type type) -{ - struct camera_data *cam = video_drvdata(file); - int ret = -EINVAL; - - DBG("VIDIOC_STREAMON, streaming=%d\n", cam->streaming); - if (!cam->mmapped || type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (!cam->streaming) { - ret = cpia2_usb_stream_start(cam, - cam->params.camera_state.stream_mode); - if (!ret) - v4l2_ctrl_grab(cam->usb_alt, true); - } - return ret; -} - -static int cpia2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) -{ - struct camera_data *cam = video_drvdata(file); - int ret = -EINVAL; - - DBG("VIDIOC_STREAMOFF, streaming=%d\n", cam->streaming); - if (!cam->mmapped || type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (cam->streaming) { - ret = cpia2_usb_stream_stop(cam); - if (!ret) - v4l2_ctrl_grab(cam->usb_alt, false); - } - return ret; -} - -/****************************************************************************** - * - * cpia2_mmap - * - *****************************************************************************/ -static int cpia2_mmap(struct file *file, struct vm_area_struct *area) -{ - struct camera_data *cam = video_drvdata(file); - int retval; - - if (mutex_lock_interruptible(&cam->v4l2_lock)) - return -ERESTARTSYS; - retval = cpia2_remap_buffer(cam, area); - - if(!retval) - cam->stream_fh = file->private_data; - mutex_unlock(&cam->v4l2_lock); - return retval; -} - -/****************************************************************************** - * - * reset_camera_struct_v4l - * - * Sets all values to the defaults - *****************************************************************************/ -static void reset_camera_struct_v4l(struct camera_data *cam) -{ - cam->width = cam->params.roi.width; - cam->height = cam->params.roi.height; - - cam->frame_size = buffer_size; - cam->num_frames = num_buffers; - - /* Flicker modes */ - cam->params.flicker_control.flicker_mode_req = flicker_mode; - - /* stream modes */ - cam->params.camera_state.stream_mode = alternate; - - cam->pixelformat = V4L2_PIX_FMT_JPEG; -} - -static const struct v4l2_ioctl_ops cpia2_ioctl_ops = { - .vidioc_querycap = cpia2_querycap, - .vidioc_enum_input = cpia2_enum_input, - .vidioc_g_input = cpia2_g_input, - .vidioc_s_input = cpia2_s_input, - .vidioc_enum_fmt_vid_cap = cpia2_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = cpia2_g_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = cpia2_s_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = cpia2_try_fmt_vid_cap, - .vidioc_g_jpegcomp = cpia2_g_jpegcomp, - .vidioc_s_jpegcomp = cpia2_s_jpegcomp, - .vidioc_cropcap = cpia2_cropcap, - .vidioc_reqbufs = cpia2_reqbufs, - .vidioc_querybuf = cpia2_querybuf, - .vidioc_qbuf = cpia2_qbuf, - .vidioc_dqbuf = cpia2_dqbuf, - .vidioc_streamon = cpia2_streamon, - .vidioc_streamoff = cpia2_streamoff, - .vidioc_s_parm = cpia2_s_parm, - .vidioc_g_parm = cpia2_g_parm, - .vidioc_enum_framesizes = cpia2_enum_framesizes, - .vidioc_enum_frameintervals = cpia2_enum_frameintervals, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -/*** - * The v4l video device structure initialized for this device - ***/ -static const struct v4l2_file_operations cpia2_fops = { - .owner = THIS_MODULE, - .open = cpia2_open, - .release = cpia2_close, - .read = cpia2_v4l_read, - .poll = cpia2_v4l_poll, - .unlocked_ioctl = video_ioctl2, - .mmap = cpia2_mmap, -}; - -static struct video_device cpia2_template = { - /* I could not find any place for the old .initialize initializer?? */ - .name = "CPiA2 Camera", - .fops = &cpia2_fops, - .ioctl_ops = &cpia2_ioctl_ops, - .release = video_device_release_empty, -}; - -void cpia2_camera_release(struct v4l2_device *v4l2_dev) -{ - struct camera_data *cam = - container_of(v4l2_dev, struct camera_data, v4l2_dev); - - v4l2_ctrl_handler_free(&cam->hdl); - v4l2_device_unregister(&cam->v4l2_dev); - kfree(cam); -} - -static const struct v4l2_ctrl_ops cpia2_ctrl_ops = { - .s_ctrl = cpia2_s_ctrl, -}; - -/****************************************************************************** - * - * cpia2_register_camera - * - *****************************************************************************/ -int cpia2_register_camera(struct camera_data *cam) -{ - struct v4l2_ctrl_handler *hdl = &cam->hdl; - struct v4l2_ctrl_config cpia2_usb_alt = { - .ops = &cpia2_ctrl_ops, - .id = CPIA2_CID_USB_ALT, - .name = "USB Alternate", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = USBIF_ISO_1, - .max = USBIF_ISO_6, - .step = 1, - }; - int ret; - - v4l2_ctrl_handler_init(hdl, 12); - v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops, - V4L2_CID_BRIGHTNESS, - cam->params.pnp_id.device_type == DEVICE_STV_672 ? 1 : 0, - 255, 1, DEFAULT_BRIGHTNESS); - v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops, - V4L2_CID_CONTRAST, 0, 255, 1, DEFAULT_CONTRAST); - v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops, - V4L2_CID_SATURATION, 0, 255, 1, DEFAULT_SATURATION); - v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops, - V4L2_CID_HFLIP, 0, 1, 1, 0); - v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops, - V4L2_CID_JPEG_ACTIVE_MARKER, 0, - V4L2_JPEG_ACTIVE_MARKER_DHT, 0, - V4L2_JPEG_ACTIVE_MARKER_DHT); - v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops, - V4L2_CID_JPEG_COMPRESSION_QUALITY, 1, - 100, 1, 100); - cpia2_usb_alt.def = alternate; - cam->usb_alt = v4l2_ctrl_new_custom(hdl, &cpia2_usb_alt, NULL); - /* VP5 Only */ - if (cam->params.pnp_id.device_type != DEVICE_STV_672) - v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops, - V4L2_CID_VFLIP, 0, 1, 1, 0); - /* Flicker control only valid for 672 */ - if (cam->params.pnp_id.device_type == DEVICE_STV_672) - v4l2_ctrl_new_std_menu(hdl, &cpia2_ctrl_ops, - V4L2_CID_POWER_LINE_FREQUENCY, - V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0); - /* Light control only valid for the QX5 Microscope */ - if (cam->params.pnp_id.product == 0x151) { - cam->top_light = v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops, - V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0); - cam->bottom_light = v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops, - V4L2_CID_ILLUMINATORS_2, 0, 1, 1, 0); - v4l2_ctrl_cluster(2, &cam->top_light); - } - - if (hdl->error) { - ret = hdl->error; - v4l2_ctrl_handler_free(hdl); - return ret; - } - - cam->vdev = cpia2_template; - video_set_drvdata(&cam->vdev, cam); - cam->vdev.lock = &cam->v4l2_lock; - cam->vdev.ctrl_handler = hdl; - cam->vdev.v4l2_dev = &cam->v4l2_dev; - set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags); - - reset_camera_struct_v4l(cam); - - /* register v4l device */ - if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { - ERR("video_register_device failed\n"); - return -ENODEV; - } - - return 0; -} - -/****************************************************************************** - * - * cpia2_unregister_camera - * - *****************************************************************************/ -void cpia2_unregister_camera(struct camera_data *cam) -{ - video_unregister_device(&cam->vdev); -} - -/****************************************************************************** - * - * check_parameters - * - * Make sure that all user-supplied parameters are sensible - *****************************************************************************/ -static void __init check_parameters(void) -{ - if(buffer_size < PAGE_SIZE) { - buffer_size = PAGE_SIZE; - LOG("buffer_size too small, setting to %d\n", buffer_size); - } else if(buffer_size > 1024*1024) { - /* arbitrary upper limiit */ - buffer_size = 1024*1024; - LOG("buffer_size ridiculously large, setting to %d\n", - buffer_size); - } else { - buffer_size += PAGE_SIZE-1; - buffer_size &= ~(PAGE_SIZE-1); - } - - if(num_buffers < 1) { - num_buffers = 1; - LOG("num_buffers too small, setting to %d\n", num_buffers); - } else if(num_buffers > VIDEO_MAX_FRAME) { - num_buffers = VIDEO_MAX_FRAME; - LOG("num_buffers too large, setting to %d\n", num_buffers); - } - - if(alternate < USBIF_ISO_1 || alternate > USBIF_ISO_6) { - alternate = DEFAULT_ALT; - LOG("alternate specified is invalid, using %d\n", alternate); - } - - if (flicker_mode != 0 && flicker_mode != FLICKER_50 && flicker_mode != FLICKER_60) { - flicker_mode = 0; - LOG("Flicker mode specified is invalid, using %d\n", - flicker_mode); - } - - DBG("Using %d buffers, each %d bytes, alternate=%d\n", - num_buffers, buffer_size, alternate); -} - -/************ Module Stuff ***************/ - - -/****************************************************************************** - * - * cpia2_init/module_init - * - *****************************************************************************/ -static int __init cpia2_init(void) -{ - LOG("%s v%s\n", - ABOUT, CPIA_VERSION); - check_parameters(); - cpia2_usb_init(); - return 0; -} - - -/****************************************************************************** - * - * cpia2_exit/module_exit - * - *****************************************************************************/ -static void __exit cpia2_exit(void) -{ - cpia2_usb_cleanup(); - schedule_timeout(2 * HZ); -} - -module_init(cpia2_init); -module_exit(cpia2_exit); diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig deleted file mode 100644 index 446f692aabb7..000000000000 --- a/drivers/media/video/cx231xx/Kconfig +++ /dev/null @@ -1,51 +0,0 @@ -config VIDEO_CX231XX - tristate "Conexant cx231xx USB video capture support" - depends on VIDEO_DEV && I2C - select VIDEO_TUNER - select VIDEO_TVEEPROM - depends on RC_CORE - select VIDEOBUF_VMALLOC - select VIDEO_CX25840 - select VIDEO_CX2341X - - ---help--- - This is a video4linux driver for Conexant 231xx USB based TV cards. - - To compile this driver as a module, choose M here: the - module will be called cx231xx - -config VIDEO_CX231XX_RC - bool "Conexant cx231xx Remote Controller additional support" - depends on RC_CORE - depends on VIDEO_CX231XX - default y - ---help--- - cx231xx hardware has a builtin RX/TX support. However, a few - designs opted to not use it, but, instead, some other hardware. - This module enables the usage of those other hardware, like the - ones used with ISDB-T boards. - - On most cases, all you need for IR is mceusb module. - -config VIDEO_CX231XX_ALSA - tristate "Conexant Cx231xx ALSA audio module" - depends on VIDEO_CX231XX && SND - select SND_PCM - - ---help--- - This is an ALSA driver for Cx231xx USB based TV cards. - - To compile this driver as a module, choose M here: the - module will be called cx231xx-alsa - -config VIDEO_CX231XX_DVB - tristate "DVB/ATSC Support for Cx231xx based TV cards" - depends on VIDEO_CX231XX && DVB_CORE && DVB_CAPTURE_DRIVERS - select VIDEOBUF_DVB - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE - select DVB_MB86A20S if !DVB_FE_CUSTOMISE - - ---help--- - This adds support for DVB cards based on the - Conexant cx231xx chips. diff --git a/drivers/media/video/cx231xx/Makefile b/drivers/media/video/cx231xx/Makefile deleted file mode 100644 index 1d40fce77601..000000000000 --- a/drivers/media/video/cx231xx/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -cx231xx-y += cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o -cx231xx-y += cx231xx-avcore.o cx231xx-417.o cx231xx-pcb-cfg.o cx231xx-vbi.o -cx231xx-$(CONFIG_VIDEO_CX231XX_RC) += cx231xx-input.o - -cx231xx-alsa-objs := cx231xx-audio.o - -obj-$(CONFIG_VIDEO_CX231XX) += cx231xx.o -obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o -obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o - -ccflags-y += -Idrivers/media/video -ccflags-y += -Idrivers/media/tuners -ccflags-y += -Idrivers/media/dvb-core -ccflags-y += -Idrivers/media/dvb-frontends -ccflags-y += -Idrivers/media/usb/dvb-usb diff --git a/drivers/media/video/cx231xx/cx231xx-417.c b/drivers/media/video/cx231xx/cx231xx-417.c deleted file mode 100644 index b024e5197a75..000000000000 --- a/drivers/media/video/cx231xx/cx231xx-417.c +++ /dev/null @@ -1,2197 +0,0 @@ -/* - * - * Support for a cx23417 mpeg encoder via cx231xx host port. - * - * (c) 2004 Jelle Foks <jelle@foks.us> - * (c) 2004 Gerd Knorr <kraxel@bytesex.org> - * (c) 2008 Steven Toth <stoth@linuxtv.org> - * - CX23885/7/8 support - * - * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/), - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; 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 <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/init.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/firmware.h> -#include <linux/vmalloc.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <media/cx2341x.h> -#include <linux/usb.h> - -#include "cx231xx.h" -/*#include "cx23885-ioctl.h"*/ - -#define CX231xx_FIRM_IMAGE_SIZE 376836 -#define CX231xx_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw" - -/* for polaris ITVC */ -#define ITVC_WRITE_DIR 0x03FDFC00 -#define ITVC_READ_DIR 0x0001FC00 - -#define MCI_MEMORY_DATA_BYTE0 0x00 -#define MCI_MEMORY_DATA_BYTE1 0x08 -#define MCI_MEMORY_DATA_BYTE2 0x10 -#define MCI_MEMORY_DATA_BYTE3 0x18 - -#define MCI_MEMORY_ADDRESS_BYTE2 0x20 -#define MCI_MEMORY_ADDRESS_BYTE1 0x28 -#define MCI_MEMORY_ADDRESS_BYTE0 0x30 - -#define MCI_REGISTER_DATA_BYTE0 0x40 -#define MCI_REGISTER_DATA_BYTE1 0x48 -#define MCI_REGISTER_DATA_BYTE2 0x50 -#define MCI_REGISTER_DATA_BYTE3 0x58 - -#define MCI_REGISTER_ADDRESS_BYTE0 0x60 -#define MCI_REGISTER_ADDRESS_BYTE1 0x68 - -#define MCI_REGISTER_MODE 0x70 - -/* Read and write modes for polaris ITVC */ -#define MCI_MODE_REGISTER_READ 0x000 -#define MCI_MODE_REGISTER_WRITE 0x100 -#define MCI_MODE_MEMORY_READ 0x000 -#define MCI_MODE_MEMORY_WRITE 0x4000 - -static unsigned int mpegbufs = 8; -module_param(mpegbufs, int, 0644); -MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32"); -static unsigned int mpeglines = 128; -module_param(mpeglines, int, 0644); -MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32"); -static unsigned int mpeglinesize = 512; -module_param(mpeglinesize, int, 0644); -MODULE_PARM_DESC(mpeglinesize, - "number of bytes in each line of an MPEG buffer, range 512-1024"); - -static unsigned int v4l_debug = 1; -module_param(v4l_debug, int, 0644); -MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages"); -struct cx231xx_dmaqueue *dma_qq; -#define dprintk(level, fmt, arg...)\ - do { if (v4l_debug >= level) \ - printk(KERN_INFO "%s: " fmt, \ - (dev) ? dev->name : "cx231xx[?]", ## arg); \ - } while (0) - -static struct cx231xx_tvnorm cx231xx_tvnorms[] = { - { - .name = "NTSC-M", - .id = V4L2_STD_NTSC_M, - }, { - .name = "NTSC-JP", - .id = V4L2_STD_NTSC_M_JP, - }, { - .name = "PAL-BG", - .id = V4L2_STD_PAL_BG, - }, { - .name = "PAL-DK", - .id = V4L2_STD_PAL_DK, - }, { - .name = "PAL-I", - .id = V4L2_STD_PAL_I, - }, { - .name = "PAL-M", - .id = V4L2_STD_PAL_M, - }, { - .name = "PAL-N", - .id = V4L2_STD_PAL_N, - }, { - .name = "PAL-Nc", - .id = V4L2_STD_PAL_Nc, - }, { - .name = "PAL-60", - .id = V4L2_STD_PAL_60, - }, { - .name = "SECAM-L", - .id = V4L2_STD_SECAM_L, - }, { - .name = "SECAM-DK", - .id = V4L2_STD_SECAM_DK, - } -}; - -/* ------------------------------------------------------------------ */ -enum cx231xx_capture_type { - CX231xx_MPEG_CAPTURE, - CX231xx_RAW_CAPTURE, - CX231xx_RAW_PASSTHRU_CAPTURE -}; -enum cx231xx_capture_bits { - CX231xx_RAW_BITS_NONE = 0x00, - CX231xx_RAW_BITS_YUV_CAPTURE = 0x01, - CX231xx_RAW_BITS_PCM_CAPTURE = 0x02, - CX231xx_RAW_BITS_VBI_CAPTURE = 0x04, - CX231xx_RAW_BITS_PASSTHRU_CAPTURE = 0x08, - CX231xx_RAW_BITS_TO_HOST_CAPTURE = 0x10 -}; -enum cx231xx_capture_end { - CX231xx_END_AT_GOP, /* stop at the end of gop, generate irq */ - CX231xx_END_NOW, /* stop immediately, no irq */ -}; -enum cx231xx_framerate { - CX231xx_FRAMERATE_NTSC_30, /* NTSC: 30fps */ - CX231xx_FRAMERATE_PAL_25 /* PAL: 25fps */ -}; -enum cx231xx_stream_port { - CX231xx_OUTPUT_PORT_MEMORY, - CX231xx_OUTPUT_PORT_STREAMING, - CX231xx_OUTPUT_PORT_SERIAL -}; -enum cx231xx_data_xfer_status { - CX231xx_MORE_BUFFERS_FOLLOW, - CX231xx_LAST_BUFFER, -}; -enum cx231xx_picture_mask { - CX231xx_PICTURE_MASK_NONE, - CX231xx_PICTURE_MASK_I_FRAMES, - CX231xx_PICTURE_MASK_I_P_FRAMES = 0x3, - CX231xx_PICTURE_MASK_ALL_FRAMES = 0x7, -}; -enum cx231xx_vbi_mode_bits { - CX231xx_VBI_BITS_SLICED, - CX231xx_VBI_BITS_RAW, -}; -enum cx231xx_vbi_insertion_bits { - CX231xx_VBI_BITS_INSERT_IN_XTENSION_USR_DATA, - CX231xx_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1, - CX231xx_VBI_BITS_SEPARATE_STREAM = 0x2 << 1, - CX231xx_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1, - CX231xx_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1, -}; -enum cx231xx_dma_unit { - CX231xx_DMA_BYTES, - CX231xx_DMA_FRAMES, -}; -enum cx231xx_dma_transfer_status_bits { - CX231xx_DMA_TRANSFER_BITS_DONE = 0x01, - CX231xx_DMA_TRANSFER_BITS_ERROR = 0x04, - CX231xx_DMA_TRANSFER_BITS_LL_ERROR = 0x10, -}; -enum cx231xx_pause { - CX231xx_PAUSE_ENCODING, - CX231xx_RESUME_ENCODING, -}; -enum cx231xx_copyright { - CX231xx_COPYRIGHT_OFF, - CX231xx_COPYRIGHT_ON, -}; -enum cx231xx_notification_type { - CX231xx_NOTIFICATION_REFRESH, -}; -enum cx231xx_notification_status { - CX231xx_NOTIFICATION_OFF, - CX231xx_NOTIFICATION_ON, -}; -enum cx231xx_notification_mailbox { - CX231xx_NOTIFICATION_NO_MAILBOX = -1, -}; -enum cx231xx_field1_lines { - CX231xx_FIELD1_SAA7114 = 0x00EF, /* 239 */ - CX231xx_FIELD1_SAA7115 = 0x00F0, /* 240 */ - CX231xx_FIELD1_MICRONAS = 0x0105, /* 261 */ -}; -enum cx231xx_field2_lines { - CX231xx_FIELD2_SAA7114 = 0x00EF, /* 239 */ - CX231xx_FIELD2_SAA7115 = 0x00F0, /* 240 */ - CX231xx_FIELD2_MICRONAS = 0x0106, /* 262 */ -}; -enum cx231xx_custom_data_type { - CX231xx_CUSTOM_EXTENSION_USR_DATA, - CX231xx_CUSTOM_PRIVATE_PACKET, -}; -enum cx231xx_mute { - CX231xx_UNMUTE, - CX231xx_MUTE, -}; -enum cx231xx_mute_video_mask { - CX231xx_MUTE_VIDEO_V_MASK = 0x0000FF00, - CX231xx_MUTE_VIDEO_U_MASK = 0x00FF0000, - CX231xx_MUTE_VIDEO_Y_MASK = 0xFF000000, -}; -enum cx231xx_mute_video_shift { - CX231xx_MUTE_VIDEO_V_SHIFT = 8, - CX231xx_MUTE_VIDEO_U_SHIFT = 16, - CX231xx_MUTE_VIDEO_Y_SHIFT = 24, -}; - -/* defines below are from ivtv-driver.h */ -#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF - -/* Firmware API commands */ -#define IVTV_API_STD_TIMEOUT 500 - -/* Registers */ -/* IVTV_REG_OFFSET */ -#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8) -#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC) -#define IVTV_REG_SPU (0x9050) -#define IVTV_REG_HW_BLOCKS (0x9054) -#define IVTV_REG_VPU (0x9058) -#define IVTV_REG_APU (0xA064) - -/* - * Bit definitions for MC417_RWD and MC417_OEN registers - * - * bits 31-16 - *+-----------+ - *| Reserved | - *|+-----------+ - *| bit 15 bit 14 bit 13 bit 12 bit 11 bit 10 bit 9 bit 8 - *|+-------+-------+-------+-------+-------+-------+-------+-------+ - *|| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0| - *|+-------+-------+-------+-------+-------+-------+-------+-------+ - *| bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 - *|+-------+-------+-------+-------+-------+-------+-------+-------+ - *||MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0| - *|+-------+-------+-------+-------+-------+-------+-------+-------+ - */ -#define MC417_MIWR 0x8000 -#define MC417_MIRD 0x4000 -#define MC417_MICS 0x2000 -#define MC417_MIRDY 0x1000 -#define MC417_MIADDR 0x0F00 -#define MC417_MIDATA 0x00FF - - -/* Bit definitions for MC417_CTL register **** - *bits 31-6 bits 5-4 bit 3 bits 2-1 Bit 0 - *+--------+-------------+--------+--------------+------------+ - *|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN| - *+--------+-------------+--------+--------------+------------+ - */ -#define MC417_SPD_CTL(x) (((x) << 4) & 0x00000030) -#define MC417_GPIO_SEL(x) (((x) << 1) & 0x00000006) -#define MC417_UART_GPIO_EN 0x00000001 - -/* Values for speed control */ -#define MC417_SPD_CTL_SLOW 0x1 -#define MC417_SPD_CTL_MEDIUM 0x0 -#define MC417_SPD_CTL_FAST 0x3 /* b'1x, but we use b'11 */ - -/* Values for GPIO select */ -#define MC417_GPIO_SEL_GPIO3 0x3 -#define MC417_GPIO_SEL_GPIO2 0x2 -#define MC417_GPIO_SEL_GPIO1 0x1 -#define MC417_GPIO_SEL_GPIO0 0x0 - - -#define CX23417_GPIO_MASK 0xFC0003FF -static int setITVCReg(struct cx231xx *dev, u32 gpio_direction, u32 value) -{ - int status = 0; - u32 _gpio_direction = 0; - - _gpio_direction = _gpio_direction & CX23417_GPIO_MASK; - _gpio_direction = _gpio_direction|gpio_direction; - status = cx231xx_send_gpio_cmd(dev, _gpio_direction, - (u8 *)&value, 4, 0, 0); - return status; -} -static int getITVCReg(struct cx231xx *dev, u32 gpio_direction, u32 *pValue) -{ - int status = 0; - u32 _gpio_direction = 0; - - _gpio_direction = _gpio_direction & CX23417_GPIO_MASK; - _gpio_direction = _gpio_direction|gpio_direction; - - status = cx231xx_send_gpio_cmd(dev, _gpio_direction, - (u8 *)pValue, 4, 0, 1); - return status; -} - -static int waitForMciComplete(struct cx231xx *dev) -{ - u32 gpio; - u32 gpio_driection = 0; - u8 count = 0; - getITVCReg(dev, gpio_driection, &gpio); - - while (!(gpio&0x020000)) { - msleep(10); - - getITVCReg(dev, gpio_driection, &gpio); - - if (count++ > 100) { - dprintk(3, "ERROR: Timeout - gpio=%x\n", gpio); - return -1; - } - } - return 0; -} - -static int mc417_register_write(struct cx231xx *dev, u16 address, u32 value) -{ - u32 temp; - int status = 0; - - temp = 0x82|MCI_REGISTER_DATA_BYTE0|((value&0x000000FF)<<8); - temp = temp<<10; - status = setITVCReg(dev, ITVC_WRITE_DIR, temp); - if (status < 0) - return status; - temp = temp|((0x05)<<10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /*write data byte 1;*/ - temp = 0x82|MCI_REGISTER_DATA_BYTE1|(value&0x0000FF00); - temp = temp<<10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp|((0x05)<<10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /*write data byte 2;*/ - temp = 0x82|MCI_REGISTER_DATA_BYTE2|((value&0x00FF0000)>>8); - temp = temp<<10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp|((0x05)<<10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /*write data byte 3;*/ - temp = 0x82|MCI_REGISTER_DATA_BYTE3|((value&0xFF000000)>>16); - temp = temp<<10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp|((0x05)<<10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /*write address byte 0;*/ - temp = 0x82|MCI_REGISTER_ADDRESS_BYTE0|((address&0x000000FF)<<8); - temp = temp<<10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp|((0x05)<<10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /*write address byte 1;*/ - temp = 0x82|MCI_REGISTER_ADDRESS_BYTE1|(address&0x0000FF00); - temp = temp<<10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp|((0x05)<<10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /*Write that the mode is write.*/ - temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_WRITE; - temp = temp<<10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp|((0x05)<<10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - return waitForMciComplete(dev); -} - -static int mc417_register_read(struct cx231xx *dev, u16 address, u32 *value) -{ - /*write address byte 0;*/ - u32 temp; - u32 return_value = 0; - int ret = 0; - - temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE0 | ((address & 0x00FF) << 8); - temp = temp << 10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp | ((0x05) << 10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /*write address byte 1;*/ - temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE1 | (address & 0xFF00); - temp = temp << 10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp | ((0x05) << 10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /*write that the mode is read;*/ - temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_READ; - temp = temp << 10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp | ((0x05) << 10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /*wait for the MIRDY line to be asserted , - signalling that the read is done;*/ - ret = waitForMciComplete(dev); - - /*switch the DATA- GPIO to input mode;*/ - - /*Read data byte 0;*/ - temp = (0x82 | MCI_REGISTER_DATA_BYTE0) << 10; - setITVCReg(dev, ITVC_READ_DIR, temp); - temp = ((0x81 | MCI_REGISTER_DATA_BYTE0) << 10); - setITVCReg(dev, ITVC_READ_DIR, temp); - getITVCReg(dev, ITVC_READ_DIR, &temp); - return_value |= ((temp & 0x03FC0000) >> 18); - setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10)); - - /* Read data byte 1;*/ - temp = (0x82 | MCI_REGISTER_DATA_BYTE1) << 10; - setITVCReg(dev, ITVC_READ_DIR, temp); - temp = ((0x81 | MCI_REGISTER_DATA_BYTE1) << 10); - setITVCReg(dev, ITVC_READ_DIR, temp); - getITVCReg(dev, ITVC_READ_DIR, &temp); - - return_value |= ((temp & 0x03FC0000) >> 10); - setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10)); - - /*Read data byte 2;*/ - temp = (0x82 | MCI_REGISTER_DATA_BYTE2) << 10; - setITVCReg(dev, ITVC_READ_DIR, temp); - temp = ((0x81 | MCI_REGISTER_DATA_BYTE2) << 10); - setITVCReg(dev, ITVC_READ_DIR, temp); - getITVCReg(dev, ITVC_READ_DIR, &temp); - return_value |= ((temp & 0x03FC0000) >> 2); - setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10)); - - /*Read data byte 3;*/ - temp = (0x82 | MCI_REGISTER_DATA_BYTE3) << 10; - setITVCReg(dev, ITVC_READ_DIR, temp); - temp = ((0x81 | MCI_REGISTER_DATA_BYTE3) << 10); - setITVCReg(dev, ITVC_READ_DIR, temp); - getITVCReg(dev, ITVC_READ_DIR, &temp); - return_value |= ((temp & 0x03FC0000) << 6); - setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10)); - - *value = return_value; - - - return ret; -} - -static int mc417_memory_write(struct cx231xx *dev, u32 address, u32 value) -{ - /*write data byte 0;*/ - - u32 temp; - int ret = 0; - - temp = 0x82 | MCI_MEMORY_DATA_BYTE0|((value & 0x000000FF) << 8); - temp = temp << 10; - ret = setITVCReg(dev, ITVC_WRITE_DIR, temp); - if (ret < 0) - return ret; - temp = temp | ((0x05) << 10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /*write data byte 1;*/ - temp = 0x82 | MCI_MEMORY_DATA_BYTE1 | (value & 0x0000FF00); - temp = temp << 10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp | ((0x05) << 10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /*write data byte 2;*/ - temp = 0x82|MCI_MEMORY_DATA_BYTE2|((value&0x00FF0000)>>8); - temp = temp<<10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp|((0x05)<<10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /*write data byte 3;*/ - temp = 0x82|MCI_MEMORY_DATA_BYTE3|((value&0xFF000000)>>16); - temp = temp<<10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp|((0x05)<<10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /* write address byte 2;*/ - temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE | - ((address & 0x003F0000)>>8); - temp = temp<<10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp|((0x05)<<10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /* write address byte 1;*/ - temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00); - temp = temp<<10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp|((0x05)<<10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /* write address byte 0;*/ - temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0|((address & 0x00FF)<<8); - temp = temp<<10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp|((0x05)<<10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /*wait for MIRDY line;*/ - waitForMciComplete(dev); - - return 0; -} - -static int mc417_memory_read(struct cx231xx *dev, u32 address, u32 *value) -{ - u32 temp = 0; - u32 return_value = 0; - int ret = 0; - - /*write address byte 2;*/ - temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_READ | - ((address & 0x003F0000)>>8); - temp = temp<<10; - ret = setITVCReg(dev, ITVC_WRITE_DIR, temp); - if (ret < 0) - return ret; - temp = temp|((0x05)<<10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /*write address byte 1*/ - temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00); - temp = temp<<10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp|((0x05)<<10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /*write address byte 0*/ - temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF)<<8); - temp = temp<<10; - setITVCReg(dev, ITVC_WRITE_DIR, temp); - temp = temp|((0x05)<<10); - setITVCReg(dev, ITVC_WRITE_DIR, temp); - - /*Wait for MIRDY line*/ - ret = waitForMciComplete(dev); - - - /*Read data byte 3;*/ - temp = (0x82|MCI_MEMORY_DATA_BYTE3)<<10; - setITVCReg(dev, ITVC_READ_DIR, temp); - temp = ((0x81|MCI_MEMORY_DATA_BYTE3)<<10); - setITVCReg(dev, ITVC_READ_DIR, temp); - getITVCReg(dev, ITVC_READ_DIR, &temp); - return_value |= ((temp&0x03FC0000)<<6); - setITVCReg(dev, ITVC_READ_DIR, (0x87<<10)); - - /*Read data byte 2;*/ - temp = (0x82|MCI_MEMORY_DATA_BYTE2)<<10; - setITVCReg(dev, ITVC_READ_DIR, temp); - temp = ((0x81|MCI_MEMORY_DATA_BYTE2)<<10); - setITVCReg(dev, ITVC_READ_DIR, temp); - getITVCReg(dev, ITVC_READ_DIR, &temp); - return_value |= ((temp&0x03FC0000)>>2); - setITVCReg(dev, ITVC_READ_DIR, (0x87<<10)); - - /* Read data byte 1;*/ - temp = (0x82|MCI_MEMORY_DATA_BYTE1)<<10; - setITVCReg(dev, ITVC_READ_DIR, temp); - temp = ((0x81|MCI_MEMORY_DATA_BYTE1)<<10); - setITVCReg(dev, ITVC_READ_DIR, temp); - getITVCReg(dev, ITVC_READ_DIR, &temp); - return_value |= ((temp&0x03FC0000)>>10); - setITVCReg(dev, ITVC_READ_DIR, (0x87<<10)); - - /*Read data byte 0;*/ - temp = (0x82|MCI_MEMORY_DATA_BYTE0)<<10; - setITVCReg(dev, ITVC_READ_DIR, temp); - temp = ((0x81|MCI_MEMORY_DATA_BYTE0)<<10); - setITVCReg(dev, ITVC_READ_DIR, temp); - getITVCReg(dev, ITVC_READ_DIR, &temp); - return_value |= ((temp&0x03FC0000)>>18); - setITVCReg(dev, ITVC_READ_DIR, (0x87<<10)); - - *value = return_value; - return ret; -} - -/* ------------------------------------------------------------------ */ - -/* MPEG encoder API */ -static char *cmd_to_str(int cmd) -{ - switch (cmd) { - case CX2341X_ENC_PING_FW: - return "PING_FW"; - case CX2341X_ENC_START_CAPTURE: - return "START_CAPTURE"; - case CX2341X_ENC_STOP_CAPTURE: - return "STOP_CAPTURE"; - case CX2341X_ENC_SET_AUDIO_ID: - return "SET_AUDIO_ID"; - case CX2341X_ENC_SET_VIDEO_ID: - return "SET_VIDEO_ID"; - case CX2341X_ENC_SET_PCR_ID: - return "SET_PCR_PID"; - case CX2341X_ENC_SET_FRAME_RATE: - return "SET_FRAME_RATE"; - case CX2341X_ENC_SET_FRAME_SIZE: - return "SET_FRAME_SIZE"; - case CX2341X_ENC_SET_BIT_RATE: - return "SET_BIT_RATE"; - case CX2341X_ENC_SET_GOP_PROPERTIES: - return "SET_GOP_PROPERTIES"; - case CX2341X_ENC_SET_ASPECT_RATIO: - return "SET_ASPECT_RATIO"; - case CX2341X_ENC_SET_DNR_FILTER_MODE: - return "SET_DNR_FILTER_PROPS"; - case CX2341X_ENC_SET_DNR_FILTER_PROPS: - return "SET_DNR_FILTER_PROPS"; - case CX2341X_ENC_SET_CORING_LEVELS: - return "SET_CORING_LEVELS"; - case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE: - return "SET_SPATIAL_FILTER_TYPE"; - case CX2341X_ENC_SET_VBI_LINE: - return "SET_VBI_LINE"; - case CX2341X_ENC_SET_STREAM_TYPE: - return "SET_STREAM_TYPE"; - case CX2341X_ENC_SET_OUTPUT_PORT: - return "SET_OUTPUT_PORT"; - case CX2341X_ENC_SET_AUDIO_PROPERTIES: - return "SET_AUDIO_PROPERTIES"; - case CX2341X_ENC_HALT_FW: - return "HALT_FW"; - case CX2341X_ENC_GET_VERSION: - return "GET_VERSION"; - case CX2341X_ENC_SET_GOP_CLOSURE: - return "SET_GOP_CLOSURE"; - case CX2341X_ENC_GET_SEQ_END: - return "GET_SEQ_END"; - case CX2341X_ENC_SET_PGM_INDEX_INFO: - return "SET_PGM_INDEX_INFO"; - case CX2341X_ENC_SET_VBI_CONFIG: - return "SET_VBI_CONFIG"; - case CX2341X_ENC_SET_DMA_BLOCK_SIZE: - return "SET_DMA_BLOCK_SIZE"; - case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10: - return "GET_PREV_DMA_INFO_MB_10"; - case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9: - return "GET_PREV_DMA_INFO_MB_9"; - case CX2341X_ENC_SCHED_DMA_TO_HOST: - return "SCHED_DMA_TO_HOST"; - case CX2341X_ENC_INITIALIZE_INPUT: - return "INITIALIZE_INPUT"; - case CX2341X_ENC_SET_FRAME_DROP_RATE: - return "SET_FRAME_DROP_RATE"; - case CX2341X_ENC_PAUSE_ENCODER: - return "PAUSE_ENCODER"; - case CX2341X_ENC_REFRESH_INPUT: - return "REFRESH_INPUT"; - case CX2341X_ENC_SET_COPYRIGHT: - return "SET_COPYRIGHT"; - case CX2341X_ENC_SET_EVENT_NOTIFICATION: - return "SET_EVENT_NOTIFICATION"; - case CX2341X_ENC_SET_NUM_VSYNC_LINES: - return "SET_NUM_VSYNC_LINES"; - case CX2341X_ENC_SET_PLACEHOLDER: - return "SET_PLACEHOLDER"; - case CX2341X_ENC_MUTE_VIDEO: - return "MUTE_VIDEO"; - case CX2341X_ENC_MUTE_AUDIO: - return "MUTE_AUDIO"; - case CX2341X_ENC_MISC: - return "MISC"; - default: - return "UNKNOWN"; - } -} - -static int cx231xx_mbox_func(void *priv, - u32 command, - int in, - int out, - u32 data[CX2341X_MBOX_MAX_DATA]) -{ - struct cx231xx *dev = priv; - unsigned long timeout; - u32 value, flag, retval = 0; - int i; - - dprintk(3, "%s: command(0x%X) = %s\n", __func__, command, - cmd_to_str(command)); - - /* this may not be 100% safe if we can't read any memory location - without side effects */ - mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value); - if (value != 0x12345678) { - dprintk(3, - "Firmware and/or mailbox pointer not initialized " - "or corrupted, signature = 0x%x, cmd = %s\n", value, - cmd_to_str(command)); - return -1; - } - - /* This read looks at 32 bits, but flag is only 8 bits. - * Seems we also bail if CMD or TIMEOUT bytes are set??? - */ - mc417_memory_read(dev, dev->cx23417_mailbox, &flag); - if (flag) { - dprintk(3, "ERROR: Mailbox appears to be in use " - "(%x), cmd = %s\n", flag, cmd_to_str(command)); - return -1; - } - - flag |= 1; /* tell 'em we're working on it */ - mc417_memory_write(dev, dev->cx23417_mailbox, flag); - - /* write command + args + fill remaining with zeros */ - /* command code */ - mc417_memory_write(dev, dev->cx23417_mailbox + 1, command); - mc417_memory_write(dev, dev->cx23417_mailbox + 3, - IVTV_API_STD_TIMEOUT); /* timeout */ - for (i = 0; i < in; i++) { - mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]); - dprintk(3, "API Input %d = %d\n", i, data[i]); - } - for (; i < CX2341X_MBOX_MAX_DATA; i++) - mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0); - - flag |= 3; /* tell 'em we're done writing */ - mc417_memory_write(dev, dev->cx23417_mailbox, flag); - - /* wait for firmware to handle the API command */ - timeout = jiffies + msecs_to_jiffies(10); - for (;;) { - mc417_memory_read(dev, dev->cx23417_mailbox, &flag); - if (0 != (flag & 4)) - break; - if (time_after(jiffies, timeout)) { - dprintk(3, "ERROR: API Mailbox timeout\n"); - return -1; - } - udelay(10); - } - - /* read output values */ - for (i = 0; i < out; i++) { - mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i); - dprintk(3, "API Output %d = %d\n", i, data[i]); - } - - mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval); - dprintk(3, "API result = %d\n", retval); - - flag = 0; - mc417_memory_write(dev, dev->cx23417_mailbox, flag); - - return retval; -} - -/* We don't need to call the API often, so using just one - * mailbox will probably suffice - */ -static int cx231xx_api_cmd(struct cx231xx *dev, - u32 command, - u32 inputcnt, - u32 outputcnt, - ...) -{ - u32 data[CX2341X_MBOX_MAX_DATA]; - va_list vargs; - int i, err; - - dprintk(3, "%s() cmds = 0x%08x\n", __func__, command); - - va_start(vargs, outputcnt); - for (i = 0; i < inputcnt; i++) - data[i] = va_arg(vargs, int); - - err = cx231xx_mbox_func(dev, command, inputcnt, outputcnt, data); - for (i = 0; i < outputcnt; i++) { - int *vptr = va_arg(vargs, int *); - *vptr = data[i]; - } - va_end(vargs); - - return err; -} - -static int cx231xx_find_mailbox(struct cx231xx *dev) -{ - u32 signature[4] = { - 0x12345678, 0x34567812, 0x56781234, 0x78123456 - }; - int signaturecnt = 0; - u32 value; - int i; - int ret = 0; - - dprintk(2, "%s()\n", __func__); - - for (i = 0; i < 0x100; i++) {/*CX231xx_FIRM_IMAGE_SIZE*/ - ret = mc417_memory_read(dev, i, &value); - if (ret < 0) - return ret; - if (value == signature[signaturecnt]) - signaturecnt++; - else - signaturecnt = 0; - if (4 == signaturecnt) { - dprintk(1, "Mailbox signature found at 0x%x\n", i+1); - return i+1; - } - } - dprintk(3, "Mailbox signature values not found!\n"); - return -1; -} - -static void mciWriteMemoryToGPIO(struct cx231xx *dev, u32 address, u32 value, - u32 *p_fw_image) -{ - - u32 temp = 0; - int i = 0; - - temp = 0x82|MCI_MEMORY_DATA_BYTE0|((value&0x000000FF)<<8); - temp = temp<<10; - *p_fw_image = temp; - p_fw_image++; - temp = temp|((0x05)<<10); - *p_fw_image = temp; - p_fw_image++; - - /*write data byte 1;*/ - temp = 0x82|MCI_MEMORY_DATA_BYTE1|(value&0x0000FF00); - temp = temp<<10; - *p_fw_image = temp; - p_fw_image++; - temp = temp|((0x05)<<10); - *p_fw_image = temp; - p_fw_image++; - - /*write data byte 2;*/ - temp = 0x82|MCI_MEMORY_DATA_BYTE2|((value&0x00FF0000)>>8); - temp = temp<<10; - *p_fw_image = temp; - p_fw_image++; - temp = temp|((0x05)<<10); - *p_fw_image = temp; - p_fw_image++; - - /*write data byte 3;*/ - temp = 0x82|MCI_MEMORY_DATA_BYTE3|((value&0xFF000000)>>16); - temp = temp<<10; - *p_fw_image = temp; - p_fw_image++; - temp = temp|((0x05)<<10); - *p_fw_image = temp; - p_fw_image++; - - /* write address byte 2;*/ - temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE | - ((address & 0x003F0000)>>8); - temp = temp<<10; - *p_fw_image = temp; - p_fw_image++; - temp = temp|((0x05)<<10); - *p_fw_image = temp; - p_fw_image++; - - /* write address byte 1;*/ - temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00); - temp = temp<<10; - *p_fw_image = temp; - p_fw_image++; - temp = temp|((0x05)<<10); - *p_fw_image = temp; - p_fw_image++; - - /* write address byte 0;*/ - temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0|((address & 0x00FF)<<8); - temp = temp<<10; - *p_fw_image = temp; - p_fw_image++; - temp = temp|((0x05)<<10); - *p_fw_image = temp; - p_fw_image++; - - for (i = 0; i < 6; i++) { - *p_fw_image = 0xFFFFFFFF; - p_fw_image++; - } -} - - -static int cx231xx_load_firmware(struct cx231xx *dev) -{ - static const unsigned char magic[8] = { - 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa - }; - const struct firmware *firmware; - int i, retval = 0; - u32 value = 0; - u32 gpio_output = 0; - /*u32 checksum = 0;*/ - /*u32 *dataptr;*/ - u32 transfer_size = 0; - u32 fw_data = 0; - u32 address = 0; - /*u32 current_fw[800];*/ - u32 *p_current_fw, *p_fw; - u32 *p_fw_data; - int frame = 0; - u16 _buffer_size = 4096; - u8 *p_buffer; - - p_current_fw = vmalloc(1884180 * 4); - p_fw = p_current_fw; - if (p_current_fw == NULL) { - dprintk(2, "FAIL!!!\n"); - return -1; - } - - p_buffer = vmalloc(4096); - if (p_buffer == NULL) { - dprintk(2, "FAIL!!!\n"); - return -1; - } - - dprintk(2, "%s()\n", __func__); - - /* Save GPIO settings before reset of APU */ - retval |= mc417_memory_read(dev, 0x9020, &gpio_output); - retval |= mc417_memory_read(dev, 0x900C, &value); - - retval = mc417_register_write(dev, - IVTV_REG_VPU, 0xFFFFFFED); - retval |= mc417_register_write(dev, - IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); - retval |= mc417_register_write(dev, - IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800); - retval |= mc417_register_write(dev, - IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A); - retval |= mc417_register_write(dev, - IVTV_REG_APU, 0); - - if (retval != 0) { - printk(KERN_ERR "%s: Error with mc417_register_write\n", - __func__); - return -1; - } - - retval = request_firmware(&firmware, CX231xx_FIRM_IMAGE_NAME, - &dev->udev->dev); - - if (retval != 0) { - printk(KERN_ERR - "ERROR: Hotplug firmware request failed (%s).\n", - CX231xx_FIRM_IMAGE_NAME); - printk(KERN_ERR "Please fix your hotplug setup, the board will " - "not work without firmware loaded!\n"); - return -1; - } - - if (firmware->size != CX231xx_FIRM_IMAGE_SIZE) { - printk(KERN_ERR "ERROR: Firmware size mismatch " - "(have %zd, expected %d)\n", - firmware->size, CX231xx_FIRM_IMAGE_SIZE); - release_firmware(firmware); - return -1; - } - - if (0 != memcmp(firmware->data, magic, 8)) { - printk(KERN_ERR - "ERROR: Firmware magic mismatch, wrong file?\n"); - release_firmware(firmware); - return -1; - } - - initGPIO(dev); - - /* transfer to the chip */ - dprintk(2, "Loading firmware to GPIO...\n"); - p_fw_data = (u32 *)firmware->data; - dprintk(2, "firmware->size=%zd\n", firmware->size); - for (transfer_size = 0; transfer_size < firmware->size; - transfer_size += 4) { - fw_data = *p_fw_data; - - mciWriteMemoryToGPIO(dev, address, fw_data, p_current_fw); - address = address + 1; - p_current_fw += 20; - p_fw_data += 1; - } - - /*download the firmware by ep5-out*/ - - for (frame = 0; frame < (int)(CX231xx_FIRM_IMAGE_SIZE*20/_buffer_size); - frame++) { - for (i = 0; i < _buffer_size; i++) { - *(p_buffer + i) = (u8)(*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x000000FF); - i++; - *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x0000FF00) >> 8); - i++; - *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x00FF0000) >> 16); - i++; - *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0xFF000000) >> 24); - } - cx231xx_ep5_bulkout(dev, p_buffer, _buffer_size); - } - - p_current_fw = p_fw; - vfree(p_current_fw); - p_current_fw = NULL; - uninitGPIO(dev); - release_firmware(firmware); - dprintk(1, "Firmware upload successful.\n"); - - retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS, - IVTV_CMD_HW_BLOCKS_RST); - if (retval < 0) { - printk(KERN_ERR "%s: Error with mc417_register_write\n", - __func__); - return retval; - } - /* F/W power up disturbs the GPIOs, restore state */ - retval |= mc417_register_write(dev, 0x9020, gpio_output); - retval |= mc417_register_write(dev, 0x900C, value); - - retval |= mc417_register_read(dev, IVTV_REG_VPU, &value); - retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8); - - if (retval < 0) { - printk(KERN_ERR "%s: Error with mc417_register_write\n", - __func__); - return retval; - } - return 0; -} - -static void cx231xx_417_check_encoder(struct cx231xx *dev) -{ - u32 status, seq; - - status = 0; - seq = 0; - cx231xx_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq); - dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq); -} - -static void cx231xx_codec_settings(struct cx231xx *dev) -{ - dprintk(1, "%s()\n", __func__); - - /* assign frame size */ - cx231xx_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, - dev->ts1.height, dev->ts1.width); - - dev->mpeg_params.width = dev->ts1.width; - dev->mpeg_params.height = dev->ts1.height; - - cx2341x_update(dev, cx231xx_mbox_func, NULL, &dev->mpeg_params); - - cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1); - cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1); -} - -static int cx231xx_initialize_codec(struct cx231xx *dev) -{ - int version; - int retval; - u32 i; - u32 val = 0; - - dprintk(1, "%s()\n", __func__); - cx231xx_disable656(dev); - retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ - if (retval < 0) { - dprintk(2, "%s() PING OK\n", __func__); - retval = cx231xx_load_firmware(dev); - if (retval < 0) { - printk(KERN_ERR "%s() f/w load failed\n", __func__); - return retval; - } - retval = cx231xx_find_mailbox(dev); - if (retval < 0) { - printk(KERN_ERR "%s() mailbox < 0, error\n", - __func__); - return -1; - } - dev->cx23417_mailbox = retval; - retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); - if (retval < 0) { - printk(KERN_ERR - "ERROR: cx23417 firmware ping failed!\n"); - return -1; - } - retval = cx231xx_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, - &version); - if (retval < 0) { - printk(KERN_ERR "ERROR: cx23417 firmware get encoder :" - "version failed!\n"); - return -1; - } - dprintk(1, "cx23417 firmware version is 0x%08x\n", version); - msleep(200); - } - - for (i = 0; i < 1; i++) { - retval = mc417_register_read(dev, 0x20f8, &val); - dprintk(3, "***before enable656() VIM Capture Lines =%d ***\n", - val); - if (retval < 0) - return retval; - } - - cx231xx_enable656(dev); - /* stop mpeg capture */ - cx231xx_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, - 3, 0, 1, 3, 4); - - cx231xx_codec_settings(dev); - msleep(60); - -/* cx231xx_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0, - CX231xx_FIELD1_SAA7115, CX231xx_FIELD2_SAA7115); - cx231xx_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0, - CX231xx_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0); -*/ - -#if 0 - /* TODO */ - u32 data[7]; - - /* Setup to capture VBI */ - data[0] = 0x0001BD00; - data[1] = 1; /* frames per interrupt */ - data[2] = 4; /* total bufs */ - data[3] = 0x91559155; /* start codes */ - data[4] = 0x206080C0; /* stop codes */ - data[5] = 6; /* lines */ - data[6] = 64; /* BPL */ - - cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1], - data[2], data[3], data[4], data[5], data[6]); - - for (i = 2; i <= 24; i++) { - int valid; - - valid = ((i >= 19) && (i <= 21)); - cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i, - valid, 0 , 0, 0); - cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, - i | 0x80000000, valid, 0, 0, 0); - } -#endif -/* cx231xx_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX231xx_UNMUTE); - msleep(60); -*/ - /* initialize the video input */ - retval = cx231xx_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); - if (retval < 0) - return retval; - msleep(60); - - /* Enable VIP style pixel invalidation so we work with scaled mode */ - mc417_memory_write(dev, 2120, 0x00000080); - - /* start capturing to the host interface */ - retval = cx231xx_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, - CX231xx_MPEG_CAPTURE, CX231xx_RAW_BITS_NONE); - if (retval < 0) - return retval; - msleep(10); - - for (i = 0; i < 1; i++) { - mc417_register_read(dev, 0x20f8, &val); - dprintk(3, "***VIM Capture Lines =%d ***\n", val); - } - - return 0; -} - -/* ------------------------------------------------------------------ */ - -static int bb_buf_setup(struct videobuf_queue *q, - unsigned int *count, unsigned int *size) -{ - struct cx231xx_fh *fh = q->priv_data; - - fh->dev->ts1.ts_packet_size = mpeglinesize; - fh->dev->ts1.ts_packet_count = mpeglines; - - *size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count; - *count = mpegbufs; - - return 0; -} -static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) -{ - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; - unsigned long flags = 0; - - if (in_interrupt()) - BUG(); - - spin_lock_irqsave(&dev->video_mode.slock, flags); - if (dev->USE_ISO) { - if (dev->video_mode.isoc_ctl.buf == buf) - dev->video_mode.isoc_ctl.buf = NULL; - } else { - if (dev->video_mode.bulk_ctl.buf == buf) - dev->video_mode.bulk_ctl.buf = NULL; - } - spin_unlock_irqrestore(&dev->video_mode.slock, flags); - videobuf_waiton(vq, &buf->vb, 0, 0); - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *urb, - struct cx231xx_dmaqueue *dma_q) -{ - void *vbuf; - struct cx231xx_buffer *buf; - u32 tail_data = 0; - char *p_data; - - if (dma_q->mpeg_buffer_done == 0) { - if (list_empty(&dma_q->active)) - return; - - buf = list_entry(dma_q->active.next, - struct cx231xx_buffer, vb.queue); - dev->video_mode.isoc_ctl.buf = buf; - dma_q->mpeg_buffer_done = 1; - } - /* Fill buffer */ - buf = dev->video_mode.isoc_ctl.buf; - vbuf = videobuf_to_vmalloc(&buf->vb); - - if ((dma_q->mpeg_buffer_completed+len) < - mpeglines*mpeglinesize) { - if (dma_q->add_ps_package_head == - CX231XX_NEED_ADD_PS_PACKAGE_HEAD) { - memcpy(vbuf+dma_q->mpeg_buffer_completed, - dma_q->ps_head, 3); - dma_q->mpeg_buffer_completed = - dma_q->mpeg_buffer_completed + 3; - dma_q->add_ps_package_head = - CX231XX_NONEED_PS_PACKAGE_HEAD; - } - memcpy(vbuf+dma_q->mpeg_buffer_completed, data, len); - dma_q->mpeg_buffer_completed = - dma_q->mpeg_buffer_completed + len; - } else { - dma_q->mpeg_buffer_done = 0; - - tail_data = - mpeglines*mpeglinesize - dma_q->mpeg_buffer_completed; - memcpy(vbuf+dma_q->mpeg_buffer_completed, - data, tail_data); - - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - do_gettimeofday(&buf->vb.ts); - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); - dma_q->mpeg_buffer_completed = 0; - - if (len - tail_data > 0) { - p_data = data + tail_data; - dma_q->left_data_count = len - tail_data; - memcpy(dma_q->p_left_data, - p_data, len - tail_data); - } - - } - - return; -} - -static void buffer_filled(char *data, int len, struct urb *urb, - struct cx231xx_dmaqueue *dma_q) -{ - void *vbuf; - struct cx231xx_buffer *buf; - - if (list_empty(&dma_q->active)) - return; - - - buf = list_entry(dma_q->active.next, - struct cx231xx_buffer, vb.queue); - - - /* Fill buffer */ - vbuf = videobuf_to_vmalloc(&buf->vb); - memcpy(vbuf, data, len); - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - do_gettimeofday(&buf->vb.ts); - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); - - return; -} -static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) -{ - struct cx231xx_dmaqueue *dma_q = urb->context; - unsigned char *p_buffer; - u32 buffer_size = 0; - u32 i = 0; - - for (i = 0; i < urb->number_of_packets; i++) { - if (dma_q->left_data_count > 0) { - buffer_copy(dev, dma_q->p_left_data, - dma_q->left_data_count, urb, dma_q); - dma_q->mpeg_buffer_completed = dma_q->left_data_count; - dma_q->left_data_count = 0; - } - - p_buffer = urb->transfer_buffer + - urb->iso_frame_desc[i].offset; - buffer_size = urb->iso_frame_desc[i].actual_length; - - if (buffer_size > 0) - buffer_copy(dev, p_buffer, buffer_size, urb, dma_q); - } - - return 0; -} -static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb) -{ - - /*char *outp;*/ - /*struct cx231xx_buffer *buf;*/ - struct cx231xx_dmaqueue *dma_q = urb->context; - unsigned char *p_buffer, *buffer; - u32 buffer_size = 0; - - p_buffer = urb->transfer_buffer; - buffer_size = urb->actual_length; - - buffer = kmalloc(buffer_size, GFP_ATOMIC); - - memcpy(buffer, dma_q->ps_head, 3); - memcpy(buffer+3, p_buffer, buffer_size-3); - memcpy(dma_q->ps_head, p_buffer+buffer_size-3, 3); - - p_buffer = buffer; - buffer_filled(p_buffer, buffer_size, urb, dma_q); - - kfree(buffer); - return 0; -} - -static int bb_buf_prepare(struct videobuf_queue *q, - struct videobuf_buffer *vb, enum v4l2_field field) -{ - struct cx231xx_fh *fh = q->priv_data; - struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx *dev = fh->dev; - int rc = 0, urb_init = 0; - int size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count; - - dma_qq = &dev->video_mode.vidq; - - if (0 != buf->vb.baddr && buf->vb.bsize < size) - return -EINVAL; - buf->vb.width = fh->dev->ts1.ts_packet_size; - buf->vb.height = fh->dev->ts1.ts_packet_count; - buf->vb.size = size; - buf->vb.field = field; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(q, &buf->vb, NULL); - if (rc < 0) - goto fail; - } - - if (dev->USE_ISO) { - if (!dev->video_mode.isoc_ctl.num_bufs) - urb_init = 1; - } else { - if (!dev->video_mode.bulk_ctl.num_bufs) - urb_init = 1; - } - /*cx231xx_info("urb_init=%d dev->video_mode.max_pkt_size=%d\n", - urb_init, dev->video_mode.max_pkt_size);*/ - dev->mode_tv = 1; - - if (urb_init) { - rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); - rc = cx231xx_unmute_audio(dev); - if (dev->USE_ISO) { - cx231xx_set_alt_setting(dev, INDEX_TS1, 4); - rc = cx231xx_init_isoc(dev, mpeglines, - mpegbufs, - dev->ts1_mode.max_pkt_size, - cx231xx_isoc_copy); - } else { - cx231xx_set_alt_setting(dev, INDEX_TS1, 0); - rc = cx231xx_init_bulk(dev, mpeglines, - mpegbufs, - dev->ts1_mode.max_pkt_size, - cx231xx_bulk_copy); - } - if (rc < 0) - goto fail; - } - - buf->vb.state = VIDEOBUF_PREPARED; - return 0; - -fail: - free_buffer(q, buf); - return rc; -} - -static void bb_buf_queue(struct videobuf_queue *q, - struct videobuf_buffer *vb) -{ - struct cx231xx_fh *fh = q->priv_data; - - struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx *dev = fh->dev; - struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; - - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vidq->active); - -} - -static void bb_buf_release(struct videobuf_queue *q, - struct videobuf_buffer *vb) -{ - struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - /*struct cx231xx_fh *fh = q->priv_data;*/ - /*struct cx231xx *dev = (struct cx231xx *)fh->dev;*/ - - free_buffer(q, buf); -} - -static struct videobuf_queue_ops cx231xx_qops = { - .buf_setup = bb_buf_setup, - .buf_prepare = bb_buf_prepare, - .buf_queue = bb_buf_queue, - .buf_release = bb_buf_release, -}; - -/* ------------------------------------------------------------------ */ - -static const u32 *ctrl_classes[] = { - cx2341x_mpeg_ctrls, - NULL -}; - -static int cx231xx_queryctrl(struct cx231xx *dev, - struct v4l2_queryctrl *qctrl) -{ - qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); - if (qctrl->id == 0) - return -EINVAL; - - /* MPEG V4L2 controls */ - if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl)) - qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; - - return 0; -} - -static int cx231xx_querymenu(struct cx231xx *dev, - struct v4l2_querymenu *qmenu) -{ - struct v4l2_queryctrl qctrl; - - qctrl.id = qmenu->id; - cx231xx_queryctrl(dev, &qctrl); - return v4l2_ctrl_query_menu(qmenu, &qctrl, - cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id)); -} - -static int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm) -{ - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; - - *norm = dev->encodernorm.id; - return 0; -} -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) -{ - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(cx231xx_tvnorms); i++) - if (*id & cx231xx_tvnorms[i].id) - break; - if (i == ARRAY_SIZE(cx231xx_tvnorms)) - return -EINVAL; - dev->encodernorm = cx231xx_tvnorms[i]; - - if (dev->encodernorm.id & 0xb000) { - dprintk(3, "encodernorm set to NTSC\n"); - dev->norm = V4L2_STD_NTSC; - dev->ts1.height = 480; - dev->mpeg_params.is_50hz = 0; - } else { - dprintk(3, "encodernorm set to PAL\n"); - dev->norm = V4L2_STD_PAL_B; - dev->ts1.height = 576; - dev->mpeg_params.is_50hz = 1; - } - call_all(dev, core, s_std, dev->norm); - /* do mode control overrides */ - cx231xx_do_mode_ctrl_overrides(dev); - - dprintk(3, "exit vidioc_s_std() i=0x%x\n", i); - return 0; -} -static int vidioc_g_audio(struct file *file, void *fh, - struct v4l2_audio *a) -{ - struct v4l2_audio *vin = a; - - int ret = -EINVAL; - if (vin->index > 0) - return ret; - strncpy(vin->name, "VideoGrabber Audio", 14); - vin->capability = V4L2_AUDCAP_STEREO; -return 0; -} -static int vidioc_enumaudio(struct file *file, void *fh, - struct v4l2_audio *a) -{ - struct v4l2_audio *vin = a; - - int ret = -EINVAL; - - if (vin->index > 0) - return ret; - strncpy(vin->name, "VideoGrabber Audio", 14); - vin->capability = V4L2_AUDCAP_STEREO; - - -return 0; -} -static const char *iname[] = { - [CX231XX_VMUX_COMPOSITE1] = "Composite1", - [CX231XX_VMUX_SVIDEO] = "S-Video", - [CX231XX_VMUX_TELEVISION] = "Television", - [CX231XX_VMUX_CABLE] = "Cable TV", - [CX231XX_VMUX_DVB] = "DVB", - [CX231XX_VMUX_DEBUG] = "for debug only", -}; -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *i) -{ - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; - struct cx231xx_input *input; - int n; - dprintk(3, "enter vidioc_enum_input()i->index=%d\n", i->index); - - if (i->index >= 4) - return -EINVAL; - - - input = &cx231xx_boards[dev->model].input[i->index]; - - if (input->type == 0) - return -EINVAL; - - /* FIXME - * strcpy(i->name, input->name); */ - - n = i->index; - strcpy(i->name, iname[INPUT(n)->type]); - - if (input->type == CX231XX_VMUX_TELEVISION || - input->type == CX231XX_VMUX_CABLE) - i->type = V4L2_INPUT_TYPE_TUNER; - else - i->type = V4L2_INPUT_TYPE_CAMERA; - - - return 0; -} - -static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) -{ - *i = 0; - return 0; -} - -static int vidioc_s_input(struct file *file, void *priv, unsigned int i) -{ - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; - - dprintk(3, "enter vidioc_s_input() i=%d\n", i); - - mutex_lock(&dev->lock); - - video_mux(dev, i); - - mutex_unlock(&dev->lock); - - if (i >= 4) - return -EINVAL; - dev->input = i; - dprintk(3, "exit vidioc_s_input()\n"); - return 0; -} - -static int vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - return 0; -} - -static int vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - return 0; -} - -static int vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - return 0; -} - -static int vidioc_s_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - - - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; - dprintk(3, "enter vidioc_s_ctrl()\n"); - /* Update the A/V core */ - call_all(dev, core, s_ctrl, ctl); - dprintk(3, "exit vidioc_s_ctrl()\n"); - return 0; -} -static struct v4l2_capability pvr_capability = { - .driver = "cx231xx", - .card = "VideoGrabber", - .bus_info = "usb", - .version = 1, - .capabilities = (V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | - V4L2_CAP_STREAMING | V4L2_CAP_READWRITE), -}; -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - - - - memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability)); - return 0; -} - -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - - if (f->index != 0) - return -EINVAL; - - strlcpy(f->description, "MPEG", sizeof(f->description)); - f->pixelformat = V4L2_PIX_FMT_MPEG; - - return 0; -} - -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; - dprintk(3, "enter vidioc_g_fmt_vid_cap()\n"); - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = - dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; - f->fmt.pix.colorspace = 0; - f->fmt.pix.width = dev->ts1.width; - f->fmt.pix.height = dev->ts1.height; - f->fmt.pix.field = fh->vidq.field; - dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n", - dev->ts1.width, dev->ts1.height, fh->vidq.field); - dprintk(3, "exit vidioc_g_fmt_vid_cap()\n"); - return 0; -} - -static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; - dprintk(3, "enter vidioc_try_fmt_vid_cap()\n"); - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = - dev->ts1.ts_packet_size * dev->ts1.ts_packet_count; - f->fmt.pix.colorspace = 0; - dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", - dev->ts1.width, dev->ts1.height, fh->vidq.field); - dprintk(3, "exit vidioc_try_fmt_vid_cap()\n"); - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - - return 0; -} - -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *p) -{ - struct cx231xx_fh *fh = file->private_data; - - return videobuf_reqbufs(&fh->vidq, p); -} - -static int vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *p) -{ - struct cx231xx_fh *fh = file->private_data; - - return videobuf_querybuf(&fh->vidq, p); -} - -static int vidioc_qbuf(struct file *file, void *priv, - struct v4l2_buffer *p) -{ - struct cx231xx_fh *fh = file->private_data; - - return videobuf_qbuf(&fh->vidq, p); -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct cx231xx_fh *fh = priv; - - return videobuf_dqbuf(&fh->vidq, b, file->f_flags & O_NONBLOCK); -} - - -static int vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type i) -{ - struct cx231xx_fh *fh = file->private_data; - - struct cx231xx *dev = fh->dev; - dprintk(3, "enter vidioc_streamon()\n"); - cx231xx_set_alt_setting(dev, INDEX_TS1, 0); - cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); - if (dev->USE_ISO) - cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS, - CX231XX_NUM_BUFS, - dev->video_mode.max_pkt_size, - cx231xx_isoc_copy); - else { - cx231xx_init_bulk(dev, 320, - 5, - dev->ts1_mode.max_pkt_size, - cx231xx_bulk_copy); - } - dprintk(3, "exit vidioc_streamon()\n"); - return videobuf_streamon(&fh->vidq); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx231xx_fh *fh = file->private_data; - - return videobuf_streamoff(&fh->vidq); -} - -static int vidioc_g_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *f) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - dprintk(3, "enter vidioc_g_ext_ctrls()\n"); - if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) - return -EINVAL; - dprintk(3, "exit vidioc_g_ext_ctrls()\n"); - return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS); -} - -static int vidioc_s_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *f) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - struct cx2341x_mpeg_params p; - int err; - dprintk(3, "enter vidioc_s_ext_ctrls()\n"); - if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) - return -EINVAL; - - p = dev->mpeg_params; - err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS); - if (err == 0) { - err = cx2341x_update(dev, cx231xx_mbox_func, - &dev->mpeg_params, &p); - dev->mpeg_params = p; - } - - return err; - - -return 0; -} - -static int vidioc_try_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *f) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - struct cx2341x_mpeg_params p; - int err; - dprintk(3, "enter vidioc_try_ext_ctrls()\n"); - if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) - return -EINVAL; - - p = dev->mpeg_params; - err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS); - dprintk(3, "exit vidioc_try_ext_ctrls() err=%d\n", err); - return err; -} - -static int vidioc_log_status(struct file *file, void *priv) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - char name[32 + 2]; - - snprintf(name, sizeof(name), "%s/2", dev->name); - dprintk(3, - "%s/2: ============ START LOG STATUS ============\n", - dev->name); - call_all(dev, core, log_status); - cx2341x_log_status(&dev->mpeg_params, name); - dprintk(3, - "%s/2: ============= END LOG STATUS =============\n", - dev->name); - return 0; -} - -static int vidioc_querymenu(struct file *file, void *priv, - struct v4l2_querymenu *a) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - dprintk(3, "enter vidioc_querymenu()\n"); - dprintk(3, "exit vidioc_querymenu()\n"); - return cx231xx_querymenu(dev, a); -} - -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *c) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - dprintk(3, "enter vidioc_queryctrl()\n"); - dprintk(3, "exit vidioc_queryctrl()\n"); - return cx231xx_queryctrl(dev, c); -} - -static int mpeg_open(struct file *file) -{ - int minor = video_devdata(file)->minor; - struct cx231xx *h, *dev = NULL; - /*struct list_head *list;*/ - struct cx231xx_fh *fh; - /*u32 value = 0;*/ - - dprintk(2, "%s()\n", __func__); - - list_for_each_entry(h, &cx231xx_devlist, devlist) { - if (h->v4l_device->minor == minor) - dev = h; - } - - if (dev == NULL) - return -ENODEV; - - mutex_lock(&dev->lock); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - mutex_unlock(&dev->lock); - return -ENOMEM; - } - - file->private_data = fh; - fh->dev = dev; - - - videobuf_queue_vmalloc_init(&fh->vidq, &cx231xx_qops, - NULL, &dev->video_mode.slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, - sizeof(struct cx231xx_buffer), fh, NULL); -/* - videobuf_queue_sg_init(&fh->vidq, &cx231xx_qops, - &dev->udev->dev, &dev->ts1.slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx231xx_buffer), - fh, NULL); -*/ - - - cx231xx_set_alt_setting(dev, INDEX_VANC, 1); - cx231xx_set_gpio_value(dev, 2, 0); - - cx231xx_initialize_codec(dev); - - mutex_unlock(&dev->lock); - cx231xx_start_TS1(dev); - - return 0; -} - -static int mpeg_release(struct file *file) -{ - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; - - dprintk(3, "mpeg_release()! dev=0x%p\n", dev); - - if (!dev) { - dprintk(3, "abort!!!\n"); - return 0; - } - - mutex_lock(&dev->lock); - - cx231xx_stop_TS1(dev); - - /* do this before setting alternate! */ - if (dev->USE_ISO) - cx231xx_uninit_isoc(dev); - else - cx231xx_uninit_bulk(dev); - cx231xx_set_mode(dev, CX231XX_SUSPEND); - - cx231xx_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, - CX231xx_END_NOW, CX231xx_MPEG_CAPTURE, - CX231xx_RAW_BITS_NONE); - - /* FIXME: Review this crap */ - /* Shut device down on last close */ - if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) { - if (atomic_dec_return(&dev->v4l_reader_count) == 0) { - /* stop mpeg capture */ - - msleep(500); - cx231xx_417_check_encoder(dev); - - } - } - - if (fh->vidq.streaming) - videobuf_streamoff(&fh->vidq); - if (fh->vidq.reading) - videobuf_read_stop(&fh->vidq); - - videobuf_mmap_free(&fh->vidq); - file->private_data = NULL; - kfree(fh); - mutex_unlock(&dev->lock); - return 0; -} - -static ssize_t mpeg_read(struct file *file, char __user *data, - size_t count, loff_t *ppos) -{ - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; - - - /* Deal w/ A/V decoder * and mpeg encoder sync issues. */ - /* Start mpeg encoder on first read. */ - if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { - if (atomic_inc_return(&dev->v4l_reader_count) == 1) { - if (cx231xx_initialize_codec(dev) < 0) - return -EINVAL; - } - } - - return videobuf_read_stream(&fh->vidq, data, count, ppos, 0, - file->f_flags & O_NONBLOCK); -} - -static unsigned int mpeg_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct cx231xx_fh *fh = file->private_data; - /*struct cx231xx *dev = fh->dev;*/ - - /*dprintk(2, "%s\n", __func__);*/ - - return videobuf_poll_stream(file, &fh->vidq, wait); -} - -static int mpeg_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct cx231xx_fh *fh = file->private_data; - struct cx231xx *dev = fh->dev; - - dprintk(2, "%s()\n", __func__); - - return videobuf_mmap_mapper(&fh->vidq, vma); -} - -static struct v4l2_file_operations mpeg_fops = { - .owner = THIS_MODULE, - .open = mpeg_open, - .release = mpeg_release, - .read = mpeg_read, - .poll = mpeg_poll, - .mmap = mpeg_mmap, - .ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { - .vidioc_s_std = vidioc_s_std, - .vidioc_g_std = vidioc_g_std, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_enumaudio = vidioc_enumaudio, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, - .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, - .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, - .vidioc_log_status = vidioc_log_status, - .vidioc_querymenu = vidioc_querymenu, - .vidioc_queryctrl = vidioc_queryctrl, -/* .vidioc_g_chip_ident = cx231xx_g_chip_ident,*/ -#ifdef CONFIG_VIDEO_ADV_DEBUG -/* .vidioc_g_register = cx231xx_g_register,*/ -/* .vidioc_s_register = cx231xx_s_register,*/ -#endif -}; - -static struct video_device cx231xx_mpeg_template = { - .name = "cx231xx", - .fops = &mpeg_fops, - .ioctl_ops = &mpeg_ioctl_ops, - .minor = -1, - .tvnorms = CX231xx_NORMS, - .current_norm = V4L2_STD_NTSC_M, -}; - -void cx231xx_417_unregister(struct cx231xx *dev) -{ - dprintk(1, "%s()\n", __func__); - dprintk(3, "%s()\n", __func__); - - if (dev->v4l_device) { - if (-1 != dev->v4l_device->minor) - video_unregister_device(dev->v4l_device); - else - video_device_release(dev->v4l_device); - dev->v4l_device = NULL; - } -} - -static struct video_device *cx231xx_video_dev_alloc( - struct cx231xx *dev, - struct usb_device *usbdev, - struct video_device *template, - char *type) -{ - struct video_device *vfd; - - dprintk(1, "%s()\n", __func__); - vfd = video_device_alloc(); - if (NULL == vfd) - return NULL; - *vfd = *template; - vfd->minor = -1; - snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, - type, cx231xx_boards[dev->model].name); - - vfd->v4l2_dev = &dev->v4l2_dev; - vfd->release = video_device_release; - - return vfd; - -} - -int cx231xx_417_register(struct cx231xx *dev) -{ - /* FIXME: Port1 hardcoded here */ - int err = -ENODEV; - struct cx231xx_tsport *tsport = &dev->ts1; - - dprintk(1, "%s()\n", __func__); - - /* Set default TV standard */ - dev->encodernorm = cx231xx_tvnorms[0]; - - if (dev->encodernorm.id & V4L2_STD_525_60) - tsport->height = 480; - else - tsport->height = 576; - - tsport->width = 720; - cx2341x_fill_defaults(&dev->mpeg_params); - dev->norm = V4L2_STD_NTSC; - - dev->mpeg_params.port = CX2341X_PORT_SERIAL; - - /* Allocate and initialize V4L video device */ - dev->v4l_device = cx231xx_video_dev_alloc(dev, - dev->udev, &cx231xx_mpeg_template, "mpeg"); - err = video_register_device(dev->v4l_device, - VFL_TYPE_GRABBER, -1); - if (err < 0) { - dprintk(3, "%s: can't register mpeg device\n", dev->name); - return err; - } - - dprintk(3, "%s: registered device video%d [mpeg]\n", - dev->name, dev->v4l_device->num); - - return 0; -} - -MODULE_FIRMWARE(CX231xx_FIRM_IMAGE_NAME); diff --git a/drivers/media/video/cx231xx/cx231xx-audio.c b/drivers/media/video/cx231xx/cx231xx-audio.c deleted file mode 100644 index b4c99c7270cf..000000000000 --- a/drivers/media/video/cx231xx/cx231xx-audio.c +++ /dev/null @@ -1,780 +0,0 @@ -/* - * Conexant Cx231xx audio extension - * - * Copyright (C) 2008 <srinivasa.deevi at conexant dot com> - * Based on em28xx driver - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/kernel.h> -#include <linux/usb.h> -#include <linux/init.h> -#include <linux/sound.h> -#include <linux/spinlock.h> -#include <linux/soundcard.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/proc_fs.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/info.h> -#include <sound/initval.h> -#include <sound/control.h> -#include <media/v4l2-common.h> -#include "cx231xx.h" - -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "activates debug info"); - -#define dprintk(fmt, arg...) do { \ - if (debug) \ - printk(KERN_INFO "cx231xx-audio %s: " fmt, \ - __func__, ##arg); \ - } while (0) - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; - -static int cx231xx_isoc_audio_deinit(struct cx231xx *dev) -{ - int i; - - dprintk("Stopping isoc\n"); - - for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { - if (dev->adev.urb[i]) { - if (!irqs_disabled()) - usb_kill_urb(dev->adev.urb[i]); - else - usb_unlink_urb(dev->adev.urb[i]); - - usb_free_urb(dev->adev.urb[i]); - dev->adev.urb[i] = NULL; - - kfree(dev->adev.transfer_buffer[i]); - dev->adev.transfer_buffer[i] = NULL; - } - } - - return 0; -} - -static int cx231xx_bulk_audio_deinit(struct cx231xx *dev) -{ - int i; - - dprintk("Stopping bulk\n"); - - for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { - if (dev->adev.urb[i]) { - if (!irqs_disabled()) - usb_kill_urb(dev->adev.urb[i]); - else - usb_unlink_urb(dev->adev.urb[i]); - - usb_free_urb(dev->adev.urb[i]); - dev->adev.urb[i] = NULL; - - kfree(dev->adev.transfer_buffer[i]); - dev->adev.transfer_buffer[i] = NULL; - } - } - - return 0; -} - -static void cx231xx_audio_isocirq(struct urb *urb) -{ - struct cx231xx *dev = urb->context; - int i; - unsigned int oldptr; - int period_elapsed = 0; - int status; - unsigned char *cp; - unsigned int stride; - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - - if (dev->state & DEV_DISCONNECTED) - return; - - switch (urb->status) { - case 0: /* success */ - case -ETIMEDOUT: /* NAK */ - break; - case -ECONNRESET: /* kill */ - case -ENOENT: - case -ESHUTDOWN: - return; - default: /* error */ - dprintk("urb completition error %d.\n", urb->status); - break; - } - - if (atomic_read(&dev->stream_started) == 0) - return; - - if (dev->adev.capture_pcm_substream) { - substream = dev->adev.capture_pcm_substream; - runtime = substream->runtime; - stride = runtime->frame_bits >> 3; - - for (i = 0; i < urb->number_of_packets; i++) { - int length = urb->iso_frame_desc[i].actual_length / - stride; - cp = (unsigned char *)urb->transfer_buffer + - urb->iso_frame_desc[i].offset; - - if (!length) - continue; - - oldptr = dev->adev.hwptr_done_capture; - if (oldptr + length >= runtime->buffer_size) { - unsigned int cnt; - - cnt = runtime->buffer_size - oldptr; - memcpy(runtime->dma_area + oldptr * stride, cp, - cnt * stride); - memcpy(runtime->dma_area, cp + cnt * stride, - length * stride - cnt * stride); - } else { - memcpy(runtime->dma_area + oldptr * stride, cp, - length * stride); - } - - snd_pcm_stream_lock(substream); - - dev->adev.hwptr_done_capture += length; - if (dev->adev.hwptr_done_capture >= - runtime->buffer_size) - dev->adev.hwptr_done_capture -= - runtime->buffer_size; - - dev->adev.capture_transfer_done += length; - if (dev->adev.capture_transfer_done >= - runtime->period_size) { - dev->adev.capture_transfer_done -= - runtime->period_size; - period_elapsed = 1; - } - snd_pcm_stream_unlock(substream); - } - if (period_elapsed) - snd_pcm_period_elapsed(substream); - } - urb->status = 0; - - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status < 0) { - cx231xx_errdev("resubmit of audio urb failed (error=%i)\n", - status); - } - return; -} - -static void cx231xx_audio_bulkirq(struct urb *urb) -{ - struct cx231xx *dev = urb->context; - unsigned int oldptr; - int period_elapsed = 0; - int status; - unsigned char *cp; - unsigned int stride; - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - - if (dev->state & DEV_DISCONNECTED) - return; - - switch (urb->status) { - case 0: /* success */ - case -ETIMEDOUT: /* NAK */ - break; - case -ECONNRESET: /* kill */ - case -ENOENT: - case -ESHUTDOWN: - return; - default: /* error */ - dprintk("urb completition error %d.\n", urb->status); - break; - } - - if (atomic_read(&dev->stream_started) == 0) - return; - - if (dev->adev.capture_pcm_substream) { - substream = dev->adev.capture_pcm_substream; - runtime = substream->runtime; - stride = runtime->frame_bits >> 3; - - if (1) { - int length = urb->actual_length / - stride; - cp = (unsigned char *)urb->transfer_buffer; - - oldptr = dev->adev.hwptr_done_capture; - if (oldptr + length >= runtime->buffer_size) { - unsigned int cnt; - - cnt = runtime->buffer_size - oldptr; - memcpy(runtime->dma_area + oldptr * stride, cp, - cnt * stride); - memcpy(runtime->dma_area, cp + cnt * stride, - length * stride - cnt * stride); - } else { - memcpy(runtime->dma_area + oldptr * stride, cp, - length * stride); - } - - snd_pcm_stream_lock(substream); - - dev->adev.hwptr_done_capture += length; - if (dev->adev.hwptr_done_capture >= - runtime->buffer_size) - dev->adev.hwptr_done_capture -= - runtime->buffer_size; - - dev->adev.capture_transfer_done += length; - if (dev->adev.capture_transfer_done >= - runtime->period_size) { - dev->adev.capture_transfer_done -= - runtime->period_size; - period_elapsed = 1; - } - snd_pcm_stream_unlock(substream); - } - if (period_elapsed) - snd_pcm_period_elapsed(substream); - } - urb->status = 0; - - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status < 0) { - cx231xx_errdev("resubmit of audio urb failed (error=%i)\n", - status); - } - return; -} - -static int cx231xx_init_audio_isoc(struct cx231xx *dev) -{ - int i, errCode; - int sb_size; - - cx231xx_info("%s: Starting ISO AUDIO transfers\n", __func__); - - if (dev->state & DEV_DISCONNECTED) - return -ENODEV; - - sb_size = CX231XX_ISO_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; - - for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { - struct urb *urb; - int j, k; - - dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC); - if (!dev->adev.transfer_buffer[i]) - return -ENOMEM; - - memset(dev->adev.transfer_buffer[i], 0x80, sb_size); - urb = usb_alloc_urb(CX231XX_ISO_NUM_AUDIO_PACKETS, GFP_ATOMIC); - if (!urb) { - cx231xx_errdev("usb_alloc_urb failed!\n"); - for (j = 0; j < i; j++) { - usb_free_urb(dev->adev.urb[j]); - kfree(dev->adev.transfer_buffer[j]); - } - return -ENOMEM; - } - - urb->dev = dev->udev; - urb->context = dev; - urb->pipe = usb_rcvisocpipe(dev->udev, - dev->adev.end_point_addr); - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = dev->adev.transfer_buffer[i]; - urb->interval = 1; - urb->complete = cx231xx_audio_isocirq; - urb->number_of_packets = CX231XX_ISO_NUM_AUDIO_PACKETS; - urb->transfer_buffer_length = sb_size; - - for (j = k = 0; j < CX231XX_ISO_NUM_AUDIO_PACKETS; - j++, k += dev->adev.max_pkt_size) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = dev->adev.max_pkt_size; - } - dev->adev.urb[i] = urb; - } - - for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { - errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); - if (errCode < 0) { - cx231xx_isoc_audio_deinit(dev); - return errCode; - } - } - - return errCode; -} - -static int cx231xx_init_audio_bulk(struct cx231xx *dev) -{ - int i, errCode; - int sb_size; - - cx231xx_info("%s: Starting BULK AUDIO transfers\n", __func__); - - if (dev->state & DEV_DISCONNECTED) - return -ENODEV; - - sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; - - for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { - struct urb *urb; - int j; - - dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC); - if (!dev->adev.transfer_buffer[i]) - return -ENOMEM; - - memset(dev->adev.transfer_buffer[i], 0x80, sb_size); - urb = usb_alloc_urb(CX231XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); - if (!urb) { - cx231xx_errdev("usb_alloc_urb failed!\n"); - for (j = 0; j < i; j++) { - usb_free_urb(dev->adev.urb[j]); - kfree(dev->adev.transfer_buffer[j]); - } - return -ENOMEM; - } - - urb->dev = dev->udev; - urb->context = dev; - urb->pipe = usb_rcvbulkpipe(dev->udev, - dev->adev.end_point_addr); - urb->transfer_flags = 0; - urb->transfer_buffer = dev->adev.transfer_buffer[i]; - urb->complete = cx231xx_audio_bulkirq; - urb->transfer_buffer_length = sb_size; - - dev->adev.urb[i] = urb; - - } - - for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { - errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); - if (errCode < 0) { - cx231xx_bulk_audio_deinit(dev); - return errCode; - } - } - - return errCode; -} - -static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, - size_t size) -{ - struct snd_pcm_runtime *runtime = subs->runtime; - - dprintk("Allocating vbuffer\n"); - if (runtime->dma_area) { - if (runtime->dma_bytes > size) - return 0; - - vfree(runtime->dma_area); - } - runtime->dma_area = vmalloc(size); - if (!runtime->dma_area) - return -ENOMEM; - - runtime->dma_bytes = size; - - return 0; -} - -static struct snd_pcm_hardware snd_cx231xx_hw_capture = { - .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID, - - .formats = SNDRV_PCM_FMTBIT_S16_LE, - - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT, - - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */ - .period_bytes_min = 64, /* 12544/2, */ - .period_bytes_max = 12544, - .periods_min = 2, - .periods_max = 98, /* 12544, */ -}; - -static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream) -{ - struct cx231xx *dev = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int ret = 0; - - dprintk("opening device and trying to acquire exclusive lock\n"); - - if (!dev) { - cx231xx_errdev("BUG: cx231xx can't find device struct." - " Can't proceed with open\n"); - return -ENODEV; - } - - if (dev->state & DEV_DISCONNECTED) { - cx231xx_errdev("Can't open. the device was removed.\n"); - return -ENODEV; - } - - /* Sets volume, mute, etc */ - dev->mute = 0; - - /* set alternate setting for audio interface */ - /* 1 - 48000 samples per sec */ - mutex_lock(&dev->lock); - if (dev->USE_ISO) - ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1); - else - ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0); - mutex_unlock(&dev->lock); - if (ret < 0) { - cx231xx_errdev("failed to set alternate setting !\n"); - - return ret; - } - - runtime->hw = snd_cx231xx_hw_capture; - - mutex_lock(&dev->lock); - /* inform hardware to start streaming */ - ret = cx231xx_capture_start(dev, 1, Audio); - - dev->adev.users++; - mutex_unlock(&dev->lock); - - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - dev->adev.capture_pcm_substream = substream; - runtime->private_data = dev; - - return 0; -} - -static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream) -{ - int ret; - struct cx231xx *dev = snd_pcm_substream_chip(substream); - - dprintk("closing device\n"); - - /* inform hardware to stop streaming */ - mutex_lock(&dev->lock); - ret = cx231xx_capture_start(dev, 0, Audio); - - /* set alternate setting for audio interface */ - /* 1 - 48000 samples per sec */ - ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0); - if (ret < 0) { - cx231xx_errdev("failed to set alternate setting !\n"); - - mutex_unlock(&dev->lock); - return ret; - } - - dev->mute = 1; - dev->adev.users--; - mutex_unlock(&dev->lock); - - if (dev->adev.users == 0 && dev->adev.shutdown == 1) { - dprintk("audio users: %d\n", dev->adev.users); - dprintk("disabling audio stream!\n"); - dev->adev.shutdown = 0; - dprintk("released lock\n"); - if (atomic_read(&dev->stream_started) > 0) { - atomic_set(&dev->stream_started, 0); - schedule_work(&dev->wq_trigger); - } - } - return 0; -} - -static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - int ret; - - dprintk("Setting capture parameters\n"); - - ret = snd_pcm_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); -#if 0 - /* TODO: set up cx231xx audio chip to deliver the correct audio format, - current default is 48000hz multiplexed => 96000hz mono - which shouldn't matter since analogue TV only supports mono */ - unsigned int channels, rate, format; - - format = params_format(hw_params); - rate = params_rate(hw_params); - channels = params_channels(hw_params); -#endif - - return ret; -} - -static int snd_cx231xx_hw_capture_free(struct snd_pcm_substream *substream) -{ - struct cx231xx *dev = snd_pcm_substream_chip(substream); - - dprintk("Stop capture, if needed\n"); - - if (atomic_read(&dev->stream_started) > 0) { - atomic_set(&dev->stream_started, 0); - schedule_work(&dev->wq_trigger); - } - - return 0; -} - -static int snd_cx231xx_prepare(struct snd_pcm_substream *substream) -{ - struct cx231xx *dev = snd_pcm_substream_chip(substream); - - dev->adev.hwptr_done_capture = 0; - dev->adev.capture_transfer_done = 0; - - return 0; -} - -static void audio_trigger(struct work_struct *work) -{ - struct cx231xx *dev = container_of(work, struct cx231xx, wq_trigger); - - if (atomic_read(&dev->stream_started)) { - dprintk("starting capture"); - if (is_fw_load(dev) == 0) - cx25840_call(dev, core, load_fw); - if (dev->USE_ISO) - cx231xx_init_audio_isoc(dev); - else - cx231xx_init_audio_bulk(dev); - } else { - dprintk("stopping capture"); - cx231xx_isoc_audio_deinit(dev); - } -} - -static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct cx231xx *dev = snd_pcm_substream_chip(substream); - int retval = 0; - - if (dev->state & DEV_DISCONNECTED) - return -ENODEV; - - spin_lock(&dev->adev.slock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - atomic_set(&dev->stream_started, 1); - break; - case SNDRV_PCM_TRIGGER_STOP: - atomic_set(&dev->stream_started, 0); - break; - default: - retval = -EINVAL; - break; - } - spin_unlock(&dev->adev.slock); - - schedule_work(&dev->wq_trigger); - - return retval; -} - -static snd_pcm_uframes_t snd_cx231xx_capture_pointer(struct snd_pcm_substream - *substream) -{ - struct cx231xx *dev; - unsigned long flags; - snd_pcm_uframes_t hwptr_done; - - dev = snd_pcm_substream_chip(substream); - - spin_lock_irqsave(&dev->adev.slock, flags); - hwptr_done = dev->adev.hwptr_done_capture; - spin_unlock_irqrestore(&dev->adev.slock, flags); - - return hwptr_done; -} - -static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, - unsigned long offset) -{ - void *pageptr = subs->runtime->dma_area + offset; - - return vmalloc_to_page(pageptr); -} - -static struct snd_pcm_ops snd_cx231xx_pcm_capture = { - .open = snd_cx231xx_capture_open, - .close = snd_cx231xx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cx231xx_hw_capture_params, - .hw_free = snd_cx231xx_hw_capture_free, - .prepare = snd_cx231xx_prepare, - .trigger = snd_cx231xx_capture_trigger, - .pointer = snd_cx231xx_capture_pointer, - .page = snd_pcm_get_vmalloc_page, -}; - -static int cx231xx_audio_init(struct cx231xx *dev) -{ - struct cx231xx_audio *adev = &dev->adev; - struct snd_pcm *pcm; - struct snd_card *card; - static int devnr; - int err; - struct usb_interface *uif; - int i, isoc_pipe = 0; - - if (dev->has_alsa_audio != 1) { - /* This device does not support the extension (in this case - the device is expecting the snd-usb-audio module or - doesn't have analog audio support at all) */ - return 0; - } - - cx231xx_info("cx231xx-audio.c: probing for cx231xx " - "non standard usbaudio\n"); - - err = snd_card_create(index[devnr], "Cx231xx Audio", THIS_MODULE, - 0, &card); - if (err < 0) - return err; - - spin_lock_init(&adev->slock); - err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm); - if (err < 0) { - snd_card_free(card); - return err; - } - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_cx231xx_pcm_capture); - pcm->info_flags = 0; - pcm->private_data = dev; - strcpy(pcm->name, "Conexant cx231xx Capture"); - snd_card_set_dev(card, &dev->udev->dev); - strcpy(card->driver, "Cx231xx-Audio"); - strcpy(card->shortname, "Cx231xx Audio"); - strcpy(card->longname, "Conexant cx231xx Audio"); - - INIT_WORK(&dev->wq_trigger, audio_trigger); - - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - adev->sndcard = card; - adev->udev = dev->udev; - - /* compute alternate max packet sizes for Audio */ - uif = - dev->udev->actconfig->interface[dev->current_pcb_config. - hs_config_info[0].interface_info. - audio_index + 1]; - - adev->end_point_addr = - le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc. - bEndpointAddress); - - adev->num_alt = uif->num_altsetting; - cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", - adev->end_point_addr, adev->num_alt); - adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL); - - if (adev->alt_max_pkt_size == NULL) { - cx231xx_errdev("out of memory!\n"); - return -ENOMEM; - } - - for (i = 0; i < adev->num_alt; i++) { - u16 tmp = - le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. - wMaxPacketSize); - adev->alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - cx231xx_info("Alternate setting %i, max size= %i\n", i, - adev->alt_max_pkt_size[i]); - } - - return 0; -} - -static int cx231xx_audio_fini(struct cx231xx *dev) -{ - if (dev == NULL) - return 0; - - if (dev->has_alsa_audio != 1) { - /* This device does not support the extension (in this case - the device is expecting the snd-usb-audio module or - doesn't have analog audio support at all) */ - return 0; - } - - if (dev->adev.sndcard) { - snd_card_free(dev->adev.sndcard); - kfree(dev->adev.alt_max_pkt_size); - dev->adev.sndcard = NULL; - } - - return 0; -} - -static struct cx231xx_ops audio_ops = { - .id = CX231XX_AUDIO, - .name = "Cx231xx Audio Extension", - .init = cx231xx_audio_init, - .fini = cx231xx_audio_fini, -}; - -static int __init cx231xx_alsa_register(void) -{ - return cx231xx_register_extension(&audio_ops); -} - -static void __exit cx231xx_alsa_unregister(void) -{ - cx231xx_unregister_extension(&audio_ops); -} - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>"); -MODULE_DESCRIPTION("Cx231xx Audio driver"); - -module_init(cx231xx_alsa_register); -module_exit(cx231xx_alsa_unregister); diff --git a/drivers/media/video/cx231xx/cx231xx-avcore.c b/drivers/media/video/cx231xx/cx231xx-avcore.c deleted file mode 100644 index 447148eff958..000000000000 --- a/drivers/media/video/cx231xx/cx231xx-avcore.c +++ /dev/null @@ -1,3087 +0,0 @@ -/* - cx231xx_avcore.c - driver for Conexant Cx23100/101/102 - USB video capture devices - - Copyright (C) 2008 <srinivasa.deevi at conexant dot com> - - This program contains the specific code to control the avdecoder chip and - other related usb control functions for cx231xx based chipset. - - 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 <linux/init.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/bitmap.h> -#include <linux/usb.h> -#include <linux/i2c.h> -#include <linux/mm.h> -#include <linux/mutex.h> -#include <media/tuner.h> - -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-chip-ident.h> - -#include "cx231xx.h" -#include "cx231xx-dif.h" - -#define TUNER_MODE_FM_RADIO 0 -/****************************************************************************** - -: BLOCK ARRANGEMENT :- - I2S block ----------------------| - [I2S audio] | - | - Analog Front End --> Direct IF -|-> Cx25840 --> Audio - [video & audio] | [Audio] - | - |-> Cx25840 --> Video - [Video] - -*******************************************************************************/ -/****************************************************************************** - * VERVE REGISTER * - * * - ******************************************************************************/ -static int verve_write_byte(struct cx231xx *dev, u8 saddr, u8 data) -{ - return cx231xx_write_i2c_data(dev, VERVE_I2C_ADDRESS, - saddr, 1, data, 1); -} - -static int verve_read_byte(struct cx231xx *dev, u8 saddr, u8 *data) -{ - int status; - u32 temp = 0; - - status = cx231xx_read_i2c_data(dev, VERVE_I2C_ADDRESS, - saddr, 1, &temp, 1); - *data = (u8) temp; - return status; -} -void initGPIO(struct cx231xx *dev) -{ - u32 _gpio_direction = 0; - u32 value = 0; - u8 val = 0; - - _gpio_direction = _gpio_direction & 0xFC0003FF; - _gpio_direction = _gpio_direction | 0x03FDFC00; - cx231xx_send_gpio_cmd(dev, _gpio_direction, (u8 *)&value, 4, 0, 0); - - verve_read_byte(dev, 0x07, &val); - cx231xx_info(" verve_read_byte address0x07=0x%x\n", val); - verve_write_byte(dev, 0x07, 0xF4); - verve_read_byte(dev, 0x07, &val); - cx231xx_info(" verve_read_byte address0x07=0x%x\n", val); - - cx231xx_capture_start(dev, 1, Vbi); - - cx231xx_mode_register(dev, EP_MODE_SET, 0x0500FE00); - cx231xx_mode_register(dev, GBULK_BIT_EN, 0xFFFDFFFF); - -} -void uninitGPIO(struct cx231xx *dev) -{ - u8 value[4] = { 0, 0, 0, 0 }; - - cx231xx_capture_start(dev, 0, Vbi); - verve_write_byte(dev, 0x07, 0x14); - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - 0x68, value, 4); -} - -/****************************************************************************** - * A F E - B L O C K C O N T R O L functions * - * [ANALOG FRONT END] * - ******************************************************************************/ -static int afe_write_byte(struct cx231xx *dev, u16 saddr, u8 data) -{ - return cx231xx_write_i2c_data(dev, AFE_DEVICE_ADDRESS, - saddr, 2, data, 1); -} - -static int afe_read_byte(struct cx231xx *dev, u16 saddr, u8 *data) -{ - int status; - u32 temp = 0; - - status = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS, - saddr, 2, &temp, 1); - *data = (u8) temp; - return status; -} - -int cx231xx_afe_init_super_block(struct cx231xx *dev, u32 ref_count) -{ - int status = 0; - u8 temp = 0; - u8 afe_power_status = 0; - int i = 0; - - /* super block initialize */ - temp = (u8) (ref_count & 0xff); - status = afe_write_byte(dev, SUP_BLK_TUNE2, temp); - if (status < 0) - return status; - - status = afe_read_byte(dev, SUP_BLK_TUNE2, &afe_power_status); - if (status < 0) - return status; - - temp = (u8) ((ref_count & 0x300) >> 8); - temp |= 0x40; - status = afe_write_byte(dev, SUP_BLK_TUNE1, temp); - if (status < 0) - return status; - - status = afe_write_byte(dev, SUP_BLK_PLL2, 0x0f); - if (status < 0) - return status; - - /* enable pll */ - while (afe_power_status != 0x18) { - status = afe_write_byte(dev, SUP_BLK_PWRDN, 0x18); - if (status < 0) { - cx231xx_info( - ": Init Super Block failed in send cmd\n"); - break; - } - - status = afe_read_byte(dev, SUP_BLK_PWRDN, &afe_power_status); - afe_power_status &= 0xff; - if (status < 0) { - cx231xx_info( - ": Init Super Block failed in receive cmd\n"); - break; - } - i++; - if (i == 10) { - cx231xx_info( - ": Init Super Block force break in loop !!!!\n"); - status = -1; - break; - } - } - - if (status < 0) - return status; - - /* start tuning filter */ - status = afe_write_byte(dev, SUP_BLK_TUNE3, 0x40); - if (status < 0) - return status; - - msleep(5); - - /* exit tuning */ - status = afe_write_byte(dev, SUP_BLK_TUNE3, 0x00); - - return status; -} - -int cx231xx_afe_init_channels(struct cx231xx *dev) -{ - int status = 0; - - /* power up all 3 channels, clear pd_buffer */ - status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, 0x00); - status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, 0x00); - status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, 0x00); - - /* Enable quantizer calibration */ - status = afe_write_byte(dev, ADC_COM_QUANT, 0x02); - - /* channel initialize, force modulator (fb) reset */ - status = afe_write_byte(dev, ADC_FB_FRCRST_CH1, 0x17); - status = afe_write_byte(dev, ADC_FB_FRCRST_CH2, 0x17); - status = afe_write_byte(dev, ADC_FB_FRCRST_CH3, 0x17); - - /* start quantilizer calibration */ - status = afe_write_byte(dev, ADC_CAL_ATEST_CH1, 0x10); - status = afe_write_byte(dev, ADC_CAL_ATEST_CH2, 0x10); - status = afe_write_byte(dev, ADC_CAL_ATEST_CH3, 0x10); - msleep(5); - - /* exit modulator (fb) reset */ - status = afe_write_byte(dev, ADC_FB_FRCRST_CH1, 0x07); - status = afe_write_byte(dev, ADC_FB_FRCRST_CH2, 0x07); - status = afe_write_byte(dev, ADC_FB_FRCRST_CH3, 0x07); - - /* enable the pre_clamp in each channel for single-ended input */ - status = afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH1, 0xf0); - status = afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH2, 0xf0); - status = afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH3, 0xf0); - - /* use diode instead of resistor, so set term_en to 0, res_en to 0 */ - status = cx231xx_reg_mask_write(dev, AFE_DEVICE_ADDRESS, 8, - ADC_QGAIN_RES_TRM_CH1, 3, 7, 0x00); - status = cx231xx_reg_mask_write(dev, AFE_DEVICE_ADDRESS, 8, - ADC_QGAIN_RES_TRM_CH2, 3, 7, 0x00); - status = cx231xx_reg_mask_write(dev, AFE_DEVICE_ADDRESS, 8, - ADC_QGAIN_RES_TRM_CH3, 3, 7, 0x00); - - /* dynamic element matching off */ - status = afe_write_byte(dev, ADC_DCSERVO_DEM_CH1, 0x03); - status = afe_write_byte(dev, ADC_DCSERVO_DEM_CH2, 0x03); - status = afe_write_byte(dev, ADC_DCSERVO_DEM_CH3, 0x03); - - return status; -} - -int cx231xx_afe_setup_AFE_for_baseband(struct cx231xx *dev) -{ - u8 c_value = 0; - int status = 0; - - status = afe_read_byte(dev, ADC_PWRDN_CLAMP_CH2, &c_value); - c_value &= (~(0x50)); - status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, c_value); - - return status; -} - -/* - The Analog Front End in Cx231xx has 3 channels. These - channels are used to share between different inputs - like tuner, s-video and composite inputs. - - channel 1 ----- pin 1 to pin4(in reg is 1-4) - channel 2 ----- pin 5 to pin8(in reg is 5-8) - channel 3 ----- pin 9 to pin 12(in reg is 9-11) -*/ -int cx231xx_afe_set_input_mux(struct cx231xx *dev, u32 input_mux) -{ - u8 ch1_setting = (u8) input_mux; - u8 ch2_setting = (u8) (input_mux >> 8); - u8 ch3_setting = (u8) (input_mux >> 16); - int status = 0; - u8 value = 0; - - if (ch1_setting != 0) { - status = afe_read_byte(dev, ADC_INPUT_CH1, &value); - value &= ~INPUT_SEL_MASK; - value |= (ch1_setting - 1) << 4; - value &= 0xff; - status = afe_write_byte(dev, ADC_INPUT_CH1, value); - } - - if (ch2_setting != 0) { - status = afe_read_byte(dev, ADC_INPUT_CH2, &value); - value &= ~INPUT_SEL_MASK; - value |= (ch2_setting - 1) << 4; - value &= 0xff; - status = afe_write_byte(dev, ADC_INPUT_CH2, value); - } - - /* For ch3_setting, the value to put in the register is - 7 less than the input number */ - if (ch3_setting != 0) { - status = afe_read_byte(dev, ADC_INPUT_CH3, &value); - value &= ~INPUT_SEL_MASK; - value |= (ch3_setting - 1) << 4; - value &= 0xff; - status = afe_write_byte(dev, ADC_INPUT_CH3, value); - } - - return status; -} - -int cx231xx_afe_set_mode(struct cx231xx *dev, enum AFE_MODE mode) -{ - int status = 0; - - /* - * FIXME: We need to implement the AFE code for LOW IF and for HI IF. - * Currently, only baseband works. - */ - - switch (mode) { - case AFE_MODE_LOW_IF: - cx231xx_Setup_AFE_for_LowIF(dev); - break; - case AFE_MODE_BASEBAND: - status = cx231xx_afe_setup_AFE_for_baseband(dev); - break; - case AFE_MODE_EU_HI_IF: - /* SetupAFEforEuHiIF(); */ - break; - case AFE_MODE_US_HI_IF: - /* SetupAFEforUsHiIF(); */ - break; - case AFE_MODE_JAPAN_HI_IF: - /* SetupAFEforJapanHiIF(); */ - break; - } - - if ((mode != dev->afe_mode) && - (dev->video_input == CX231XX_VMUX_TELEVISION)) - status = cx231xx_afe_adjust_ref_count(dev, - CX231XX_VMUX_TELEVISION); - - dev->afe_mode = mode; - - return status; -} - -int cx231xx_afe_update_power_control(struct cx231xx *dev, - enum AV_MODE avmode) -{ - u8 afe_power_status = 0; - int status = 0; - - switch (dev->model) { - case CX231XX_BOARD_CNXT_CARRAERA: - case CX231XX_BOARD_CNXT_RDE_250: - case CX231XX_BOARD_CNXT_SHELBY: - case CX231XX_BOARD_CNXT_RDU_250: - case CX231XX_BOARD_CNXT_RDE_253S: - case CX231XX_BOARD_CNXT_RDU_253S: - case CX231XX_BOARD_CNXT_VIDEO_GRABBER: - case CX231XX_BOARD_HAUPPAUGE_EXETER: - case CX231XX_BOARD_HAUPPAUGE_USBLIVE2: - case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: - case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL: - case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC: - if (avmode == POLARIS_AVMODE_ANALOGT_TV) { - while (afe_power_status != (FLD_PWRDN_TUNING_BIAS | - FLD_PWRDN_ENABLE_PLL)) { - status = afe_write_byte(dev, SUP_BLK_PWRDN, - FLD_PWRDN_TUNING_BIAS | - FLD_PWRDN_ENABLE_PLL); - status |= afe_read_byte(dev, SUP_BLK_PWRDN, - &afe_power_status); - if (status < 0) - break; - } - - status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, - 0x00); - status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, - 0x00); - status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, - 0x00); - } else if (avmode == POLARIS_AVMODE_DIGITAL) { - status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, - 0x70); - status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, - 0x70); - status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, - 0x70); - - status |= afe_read_byte(dev, SUP_BLK_PWRDN, - &afe_power_status); - afe_power_status |= FLD_PWRDN_PD_BANDGAP | - FLD_PWRDN_PD_BIAS | - FLD_PWRDN_PD_TUNECK; - status |= afe_write_byte(dev, SUP_BLK_PWRDN, - afe_power_status); - } else if (avmode == POLARIS_AVMODE_ENXTERNAL_AV) { - while (afe_power_status != (FLD_PWRDN_TUNING_BIAS | - FLD_PWRDN_ENABLE_PLL)) { - status = afe_write_byte(dev, SUP_BLK_PWRDN, - FLD_PWRDN_TUNING_BIAS | - FLD_PWRDN_ENABLE_PLL); - status |= afe_read_byte(dev, SUP_BLK_PWRDN, - &afe_power_status); - if (status < 0) - break; - } - - status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, - 0x00); - status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, - 0x00); - status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, - 0x00); - } else { - cx231xx_info("Invalid AV mode input\n"); - status = -1; - } - break; - default: - if (avmode == POLARIS_AVMODE_ANALOGT_TV) { - while (afe_power_status != (FLD_PWRDN_TUNING_BIAS | - FLD_PWRDN_ENABLE_PLL)) { - status = afe_write_byte(dev, SUP_BLK_PWRDN, - FLD_PWRDN_TUNING_BIAS | - FLD_PWRDN_ENABLE_PLL); - status |= afe_read_byte(dev, SUP_BLK_PWRDN, - &afe_power_status); - if (status < 0) - break; - } - - status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, - 0x40); - status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, - 0x40); - status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, - 0x00); - } else if (avmode == POLARIS_AVMODE_DIGITAL) { - status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, - 0x70); - status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, - 0x70); - status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, - 0x70); - - status |= afe_read_byte(dev, SUP_BLK_PWRDN, - &afe_power_status); - afe_power_status |= FLD_PWRDN_PD_BANDGAP | - FLD_PWRDN_PD_BIAS | - FLD_PWRDN_PD_TUNECK; - status |= afe_write_byte(dev, SUP_BLK_PWRDN, - afe_power_status); - } else if (avmode == POLARIS_AVMODE_ENXTERNAL_AV) { - while (afe_power_status != (FLD_PWRDN_TUNING_BIAS | - FLD_PWRDN_ENABLE_PLL)) { - status = afe_write_byte(dev, SUP_BLK_PWRDN, - FLD_PWRDN_TUNING_BIAS | - FLD_PWRDN_ENABLE_PLL); - status |= afe_read_byte(dev, SUP_BLK_PWRDN, - &afe_power_status); - if (status < 0) - break; - } - - status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, - 0x00); - status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, - 0x00); - status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, - 0x40); - } else { - cx231xx_info("Invalid AV mode input\n"); - status = -1; - } - } /* switch */ - - return status; -} - -int cx231xx_afe_adjust_ref_count(struct cx231xx *dev, u32 video_input) -{ - u8 input_mode = 0; - u8 ntf_mode = 0; - int status = 0; - - dev->video_input = video_input; - - if (video_input == CX231XX_VMUX_TELEVISION) { - status = afe_read_byte(dev, ADC_INPUT_CH3, &input_mode); - status = afe_read_byte(dev, ADC_NTF_PRECLMP_EN_CH3, - &ntf_mode); - } else { - status = afe_read_byte(dev, ADC_INPUT_CH1, &input_mode); - status = afe_read_byte(dev, ADC_NTF_PRECLMP_EN_CH1, - &ntf_mode); - } - - input_mode = (ntf_mode & 0x3) | ((input_mode & 0x6) << 1); - - switch (input_mode) { - case SINGLE_ENDED: - dev->afe_ref_count = 0x23C; - break; - case LOW_IF: - dev->afe_ref_count = 0x24C; - break; - case EU_IF: - dev->afe_ref_count = 0x258; - break; - case US_IF: - dev->afe_ref_count = 0x260; - break; - default: - break; - } - - status = cx231xx_afe_init_super_block(dev, dev->afe_ref_count); - - return status; -} - -/****************************************************************************** - * V I D E O / A U D I O D E C O D E R C O N T R O L functions * - ******************************************************************************/ -static int vid_blk_write_byte(struct cx231xx *dev, u16 saddr, u8 data) -{ - return cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS, - saddr, 2, data, 1); -} - -static int vid_blk_read_byte(struct cx231xx *dev, u16 saddr, u8 *data) -{ - int status; - u32 temp = 0; - - status = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, - saddr, 2, &temp, 1); - *data = (u8) temp; - return status; -} - -static int vid_blk_write_word(struct cx231xx *dev, u16 saddr, u32 data) -{ - return cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS, - saddr, 2, data, 4); -} - -static int vid_blk_read_word(struct cx231xx *dev, u16 saddr, u32 *data) -{ - return cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, - saddr, 2, data, 4); -} -int cx231xx_check_fw(struct cx231xx *dev) -{ - u8 temp = 0; - int status = 0; - status = vid_blk_read_byte(dev, DL_CTL_ADDRESS_LOW, &temp); - if (status < 0) - return status; - else - return temp; - -} - -int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input) -{ - int status = 0; - - switch (INPUT(input)->type) { - case CX231XX_VMUX_COMPOSITE1: - case CX231XX_VMUX_SVIDEO: - if ((dev->current_pcb_config.type == USB_BUS_POWER) && - (dev->power_mode != POLARIS_AVMODE_ENXTERNAL_AV)) { - /* External AV */ - status = cx231xx_set_power_mode(dev, - POLARIS_AVMODE_ENXTERNAL_AV); - if (status < 0) { - cx231xx_errdev("%s: set_power_mode : Failed to" - " set Power - errCode [%d]!\n", - __func__, status); - return status; - } - } - status = cx231xx_set_decoder_video_input(dev, - INPUT(input)->type, - INPUT(input)->vmux); - break; - case CX231XX_VMUX_TELEVISION: - case CX231XX_VMUX_CABLE: - if ((dev->current_pcb_config.type == USB_BUS_POWER) && - (dev->power_mode != POLARIS_AVMODE_ANALOGT_TV)) { - /* Tuner */ - status = cx231xx_set_power_mode(dev, - POLARIS_AVMODE_ANALOGT_TV); - if (status < 0) { - cx231xx_errdev("%s: set_power_mode:Failed" - " to set Power - errCode [%d]!\n", - __func__, status); - return status; - } - } - if (dev->tuner_type == TUNER_NXP_TDA18271) - status = cx231xx_set_decoder_video_input(dev, - CX231XX_VMUX_TELEVISION, - INPUT(input)->vmux); - else - status = cx231xx_set_decoder_video_input(dev, - CX231XX_VMUX_COMPOSITE1, - INPUT(input)->vmux); - - break; - default: - cx231xx_errdev("%s: set_power_mode : Unknown Input %d !\n", - __func__, INPUT(input)->type); - break; - } - - /* save the selection */ - dev->video_input = input; - - return status; -} - -int cx231xx_set_decoder_video_input(struct cx231xx *dev, - u8 pin_type, u8 input) -{ - int status = 0; - u32 value = 0; - - if (pin_type != dev->video_input) { - status = cx231xx_afe_adjust_ref_count(dev, pin_type); - if (status < 0) { - cx231xx_errdev("%s: adjust_ref_count :Failed to set" - "AFE input mux - errCode [%d]!\n", - __func__, status); - return status; - } - } - - /* call afe block to set video inputs */ - status = cx231xx_afe_set_input_mux(dev, input); - if (status < 0) { - cx231xx_errdev("%s: set_input_mux :Failed to set" - " AFE input mux - errCode [%d]!\n", - __func__, status); - return status; - } - - switch (pin_type) { - case CX231XX_VMUX_COMPOSITE1: - status = vid_blk_read_word(dev, AFE_CTRL, &value); - value |= (0 << 13) | (1 << 4); - value &= ~(1 << 5); - - /* set [24:23] [22:15] to 0 */ - value &= (~(0x1ff8000)); - /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ - value |= 0x1000000; - status = vid_blk_write_word(dev, AFE_CTRL, value); - - status = vid_blk_read_word(dev, OUT_CTRL1, &value); - value |= (1 << 7); - status = vid_blk_write_word(dev, OUT_CTRL1, value); - - /* Set output mode */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - OUT_CTRL1, - FLD_OUT_MODE, - dev->board.output_mode); - - /* Tell DIF object to go to baseband mode */ - status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); - if (status < 0) { - cx231xx_errdev("%s: cx231xx_dif set to By pass" - " mode- errCode [%d]!\n", - __func__, status); - return status; - } - - /* Read the DFE_CTRL1 register */ - status = vid_blk_read_word(dev, DFE_CTRL1, &value); - - /* enable the VBI_GATE_EN */ - value |= FLD_VBI_GATE_EN; - - /* Enable the auto-VGA enable */ - value |= FLD_VGA_AUTO_EN; - - /* Write it back */ - status = vid_blk_write_word(dev, DFE_CTRL1, value); - - /* Disable auto config of registers */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - MODE_CTRL, FLD_ACFG_DIS, - cx231xx_set_field(FLD_ACFG_DIS, 1)); - - /* Set CVBS input mode */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - MODE_CTRL, FLD_INPUT_MODE, - cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0)); - break; - case CX231XX_VMUX_SVIDEO: - /* Disable the use of DIF */ - - status = vid_blk_read_word(dev, AFE_CTRL, &value); - - /* set [24:23] [22:15] to 0 */ - value &= (~(0x1ff8000)); - /* set FUNC_MODE[24:23] = 2 - IF_MOD[22:15] = 0 DCR_BYP_CH2[4:4] = 1; */ - value |= 0x1000010; - status = vid_blk_write_word(dev, AFE_CTRL, value); - - /* Tell DIF object to go to baseband mode */ - status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); - if (status < 0) { - cx231xx_errdev("%s: cx231xx_dif set to By pass" - " mode- errCode [%d]!\n", - __func__, status); - return status; - } - - /* Read the DFE_CTRL1 register */ - status = vid_blk_read_word(dev, DFE_CTRL1, &value); - - /* enable the VBI_GATE_EN */ - value |= FLD_VBI_GATE_EN; - - /* Enable the auto-VGA enable */ - value |= FLD_VGA_AUTO_EN; - - /* Write it back */ - status = vid_blk_write_word(dev, DFE_CTRL1, value); - - /* Disable auto config of registers */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - MODE_CTRL, FLD_ACFG_DIS, - cx231xx_set_field(FLD_ACFG_DIS, 1)); - - /* Set YC input mode */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - MODE_CTRL, - FLD_INPUT_MODE, - cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_YC_1)); - - /* Chroma to ADC2 */ - status = vid_blk_read_word(dev, AFE_CTRL, &value); - value |= FLD_CHROMA_IN_SEL; /* set the chroma in select */ - - /* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8) - This sets them to use video - rather than audio. Only one of the two will be in use. */ - value &= ~(FLD_VGA_SEL_CH2 | FLD_VGA_SEL_CH3); - - status = vid_blk_write_word(dev, AFE_CTRL, value); - - status = cx231xx_afe_set_mode(dev, AFE_MODE_BASEBAND); - break; - case CX231XX_VMUX_TELEVISION: - case CX231XX_VMUX_CABLE: - default: - /* TODO: Test if this is also needed for xc2028/xc3028 */ - if (dev->board.tuner_type == TUNER_XC5000) { - /* Disable the use of DIF */ - - status = vid_blk_read_word(dev, AFE_CTRL, &value); - value |= (0 << 13) | (1 << 4); - value &= ~(1 << 5); - - /* set [24:23] [22:15] to 0 */ - value &= (~(0x1FF8000)); - /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */ - value |= 0x1000000; - status = vid_blk_write_word(dev, AFE_CTRL, value); - - status = vid_blk_read_word(dev, OUT_CTRL1, &value); - value |= (1 << 7); - status = vid_blk_write_word(dev, OUT_CTRL1, value); - - /* Set output mode */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - OUT_CTRL1, FLD_OUT_MODE, - dev->board.output_mode); - - /* Tell DIF object to go to baseband mode */ - status = cx231xx_dif_set_standard(dev, - DIF_USE_BASEBAND); - if (status < 0) { - cx231xx_errdev("%s: cx231xx_dif set to By pass" - " mode- errCode [%d]!\n", - __func__, status); - return status; - } - - /* Read the DFE_CTRL1 register */ - status = vid_blk_read_word(dev, DFE_CTRL1, &value); - - /* enable the VBI_GATE_EN */ - value |= FLD_VBI_GATE_EN; - - /* Enable the auto-VGA enable */ - value |= FLD_VGA_AUTO_EN; - - /* Write it back */ - status = vid_blk_write_word(dev, DFE_CTRL1, value); - - /* Disable auto config of registers */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - MODE_CTRL, FLD_ACFG_DIS, - cx231xx_set_field(FLD_ACFG_DIS, 1)); - - /* Set CVBS input mode */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - MODE_CTRL, FLD_INPUT_MODE, - cx231xx_set_field(FLD_INPUT_MODE, - INPUT_MODE_CVBS_0)); - } else { - /* Enable the DIF for the tuner */ - - /* Reinitialize the DIF */ - status = cx231xx_dif_set_standard(dev, dev->norm); - if (status < 0) { - cx231xx_errdev("%s: cx231xx_dif set to By pass" - " mode- errCode [%d]!\n", - __func__, status); - return status; - } - - /* Make sure bypass is cleared */ - status = vid_blk_read_word(dev, DIF_MISC_CTRL, &value); - - /* Clear the bypass bit */ - value &= ~FLD_DIF_DIF_BYPASS; - - /* Enable the use of the DIF block */ - status = vid_blk_write_word(dev, DIF_MISC_CTRL, value); - - /* Read the DFE_CTRL1 register */ - status = vid_blk_read_word(dev, DFE_CTRL1, &value); - - /* Disable the VBI_GATE_EN */ - value &= ~FLD_VBI_GATE_EN; - - /* Enable the auto-VGA enable, AGC, and - set the skip count to 2 */ - value |= FLD_VGA_AUTO_EN | FLD_AGC_AUTO_EN | 0x00200000; - - /* Write it back */ - status = vid_blk_write_word(dev, DFE_CTRL1, value); - - /* Wait until AGC locks up */ - msleep(1); - - /* Disable the auto-VGA enable AGC */ - value &= ~(FLD_VGA_AUTO_EN); - - /* Write it back */ - status = vid_blk_write_word(dev, DFE_CTRL1, value); - - /* Enable Polaris B0 AGC output */ - status = vid_blk_read_word(dev, PIN_CTRL, &value); - value |= (FLD_OEF_AGC_RF) | - (FLD_OEF_AGC_IFVGA) | - (FLD_OEF_AGC_IF); - status = vid_blk_write_word(dev, PIN_CTRL, value); - - /* Set output mode */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - OUT_CTRL1, FLD_OUT_MODE, - dev->board.output_mode); - - /* Disable auto config of registers */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - MODE_CTRL, FLD_ACFG_DIS, - cx231xx_set_field(FLD_ACFG_DIS, 1)); - - /* Set CVBS input mode */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - MODE_CTRL, FLD_INPUT_MODE, - cx231xx_set_field(FLD_INPUT_MODE, - INPUT_MODE_CVBS_0)); - - /* Set some bits in AFE_CTRL so that channel 2 or 3 - * is ready to receive audio */ - /* Clear clamp for channels 2 and 3 (bit 16-17) */ - /* Clear droop comp (bit 19-20) */ - /* Set VGA_SEL (for audio control) (bit 7-8) */ - status = vid_blk_read_word(dev, AFE_CTRL, &value); - - /*Set Func mode:01-DIF 10-baseband 11-YUV*/ - value &= (~(FLD_FUNC_MODE)); - value |= 0x800000; - - value |= FLD_VGA_SEL_CH3 | FLD_VGA_SEL_CH2; - - status = vid_blk_write_word(dev, AFE_CTRL, value); - - if (dev->tuner_type == TUNER_NXP_TDA18271) { - status = vid_blk_read_word(dev, PIN_CTRL, - &value); - status = vid_blk_write_word(dev, PIN_CTRL, - (value & 0xFFFFFFEF)); - } - - break; - - } - break; - } - - /* Set raw VBI mode */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - OUT_CTRL1, FLD_VBIHACTRAW_EN, - cx231xx_set_field(FLD_VBIHACTRAW_EN, 1)); - - status = vid_blk_read_word(dev, OUT_CTRL1, &value); - if (value & 0x02) { - value |= (1 << 19); - status = vid_blk_write_word(dev, OUT_CTRL1, value); - } - - return status; -} - -void cx231xx_enable656(struct cx231xx *dev) -{ - u8 temp = 0; - /*enable TS1 data[0:7] as output to export 656*/ - - vid_blk_write_byte(dev, TS1_PIN_CTL0, 0xFF); - - /*enable TS1 clock as output to export 656*/ - - vid_blk_read_byte(dev, TS1_PIN_CTL1, &temp); - temp = temp|0x04; - - vid_blk_write_byte(dev, TS1_PIN_CTL1, temp); -} -EXPORT_SYMBOL_GPL(cx231xx_enable656); - -void cx231xx_disable656(struct cx231xx *dev) -{ - u8 temp = 0; - - vid_blk_write_byte(dev, TS1_PIN_CTL0, 0x00); - - vid_blk_read_byte(dev, TS1_PIN_CTL1, &temp); - temp = temp&0xFB; - - vid_blk_write_byte(dev, TS1_PIN_CTL1, temp); -} -EXPORT_SYMBOL_GPL(cx231xx_disable656); - -/* - * Handle any video-mode specific overrides that are different - * on a per video standards basis after touching the MODE_CTRL - * register which resets many values for autodetect - */ -int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) -{ - int status = 0; - - cx231xx_info("do_mode_ctrl_overrides : 0x%x\n", - (unsigned int)dev->norm); - - /* Change the DFE_CTRL3 bp_percent to fix flagging */ - status = vid_blk_write_word(dev, DFE_CTRL3, 0xCD3F0280); - - if (dev->norm & (V4L2_STD_NTSC | V4L2_STD_PAL_M)) { - cx231xx_info("do_mode_ctrl_overrides NTSC\n"); - - /* Move the close caption lines out of active video, - adjust the active video start point */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - VERT_TIM_CTRL, - FLD_VBLANK_CNT, 0x18); - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - VERT_TIM_CTRL, - FLD_VACTIVE_CNT, - 0x1E7000); - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - VERT_TIM_CTRL, - FLD_V656BLANK_CNT, - 0x1C000000); - - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - HORIZ_TIM_CTRL, - FLD_HBLANK_CNT, - cx231xx_set_field - (FLD_HBLANK_CNT, 0x79)); - - } else if (dev->norm & V4L2_STD_SECAM) { - cx231xx_info("do_mode_ctrl_overrides SECAM\n"); - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - VERT_TIM_CTRL, - FLD_VBLANK_CNT, 0x20); - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - VERT_TIM_CTRL, - FLD_VACTIVE_CNT, - cx231xx_set_field - (FLD_VACTIVE_CNT, - 0x244)); - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - VERT_TIM_CTRL, - FLD_V656BLANK_CNT, - cx231xx_set_field - (FLD_V656BLANK_CNT, - 0x24)); - /* Adjust the active video horizontal start point */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - HORIZ_TIM_CTRL, - FLD_HBLANK_CNT, - cx231xx_set_field - (FLD_HBLANK_CNT, 0x85)); - } else { - cx231xx_info("do_mode_ctrl_overrides PAL\n"); - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - VERT_TIM_CTRL, - FLD_VBLANK_CNT, 0x20); - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - VERT_TIM_CTRL, - FLD_VACTIVE_CNT, - cx231xx_set_field - (FLD_VACTIVE_CNT, - 0x244)); - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - VERT_TIM_CTRL, - FLD_V656BLANK_CNT, - cx231xx_set_field - (FLD_V656BLANK_CNT, - 0x24)); - /* Adjust the active video horizontal start point */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - HORIZ_TIM_CTRL, - FLD_HBLANK_CNT, - cx231xx_set_field - (FLD_HBLANK_CNT, 0x85)); - - } - - return status; -} - -int cx231xx_unmute_audio(struct cx231xx *dev) -{ - return vid_blk_write_byte(dev, PATH1_VOL_CTL, 0x24); -} -EXPORT_SYMBOL_GPL(cx231xx_unmute_audio); - -int stopAudioFirmware(struct cx231xx *dev) -{ - return vid_blk_write_byte(dev, DL_CTL_CONTROL, 0x03); -} - -int restartAudioFirmware(struct cx231xx *dev) -{ - return vid_blk_write_byte(dev, DL_CTL_CONTROL, 0x13); -} - -int cx231xx_set_audio_input(struct cx231xx *dev, u8 input) -{ - int status = 0; - enum AUDIO_INPUT ainput = AUDIO_INPUT_LINE; - - switch (INPUT(input)->amux) { - case CX231XX_AMUX_VIDEO: - ainput = AUDIO_INPUT_TUNER_TV; - break; - case CX231XX_AMUX_LINE_IN: - status = cx231xx_i2s_blk_set_audio_input(dev, input); - ainput = AUDIO_INPUT_LINE; - break; - default: - break; - } - - status = cx231xx_set_audio_decoder_input(dev, ainput); - - return status; -} - -int cx231xx_set_audio_decoder_input(struct cx231xx *dev, - enum AUDIO_INPUT audio_input) -{ - u32 dwval; - int status; - u8 gen_ctrl; - u32 value = 0; - - /* Put it in soft reset */ - status = vid_blk_read_byte(dev, GENERAL_CTL, &gen_ctrl); - gen_ctrl |= 1; - status = vid_blk_write_byte(dev, GENERAL_CTL, gen_ctrl); - - switch (audio_input) { - case AUDIO_INPUT_LINE: - /* setup AUD_IO control from Merlin paralle output */ - value = cx231xx_set_field(FLD_AUD_CHAN1_SRC, - AUD_CHAN_SRC_PARALLEL); - status = vid_blk_write_word(dev, AUD_IO_CTRL, value); - - /* setup input to Merlin, SRC2 connect to AC97 - bypass upsample-by-2, slave mode, sony mode, left justify - adr 091c, dat 01000000 */ - status = vid_blk_read_word(dev, AC97_CTL, &dwval); - - status = vid_blk_write_word(dev, AC97_CTL, - (dwval | FLD_AC97_UP2X_BYPASS)); - - /* select the parallel1 and SRC3 */ - status = vid_blk_write_word(dev, BAND_OUT_SEL, - cx231xx_set_field(FLD_SRC3_IN_SEL, 0x0) | - cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x0) | - cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x0)); - - /* unmute all, AC97 in, independence mode - adr 08d0, data 0x00063073 */ - status = vid_blk_write_word(dev, DL_CTL, 0x3000001); - status = vid_blk_write_word(dev, PATH1_CTL1, 0x00063073); - - /* set AVC maximum threshold, adr 08d4, dat ffff0024 */ - status = vid_blk_read_word(dev, PATH1_VOL_CTL, &dwval); - status = vid_blk_write_word(dev, PATH1_VOL_CTL, - (dwval | FLD_PATH1_AVC_THRESHOLD)); - - /* set SC maximum threshold, adr 08ec, dat ffffb3a3 */ - status = vid_blk_read_word(dev, PATH1_SC_CTL, &dwval); - status = vid_blk_write_word(dev, PATH1_SC_CTL, - (dwval | FLD_PATH1_SC_THRESHOLD)); - break; - - case AUDIO_INPUT_TUNER_TV: - default: - status = stopAudioFirmware(dev); - /* Setup SRC sources and clocks */ - status = vid_blk_write_word(dev, BAND_OUT_SEL, - cx231xx_set_field(FLD_SRC6_IN_SEL, 0x00) | - cx231xx_set_field(FLD_SRC6_CLK_SEL, 0x01) | - cx231xx_set_field(FLD_SRC5_IN_SEL, 0x00) | - cx231xx_set_field(FLD_SRC5_CLK_SEL, 0x02) | - cx231xx_set_field(FLD_SRC4_IN_SEL, 0x02) | - cx231xx_set_field(FLD_SRC4_CLK_SEL, 0x03) | - cx231xx_set_field(FLD_SRC3_IN_SEL, 0x00) | - cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x00) | - cx231xx_set_field(FLD_BASEBAND_BYPASS_CTL, 0x00) | - cx231xx_set_field(FLD_AC97_SRC_SEL, 0x03) | - cx231xx_set_field(FLD_I2S_SRC_SEL, 0x00) | - cx231xx_set_field(FLD_PARALLEL2_SRC_SEL, 0x02) | - cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x01)); - - /* Setup the AUD_IO control */ - status = vid_blk_write_word(dev, AUD_IO_CTRL, - cx231xx_set_field(FLD_I2S_PORT_DIR, 0x00) | - cx231xx_set_field(FLD_I2S_OUT_SRC, 0x00) | - cx231xx_set_field(FLD_AUD_CHAN3_SRC, 0x00) | - cx231xx_set_field(FLD_AUD_CHAN2_SRC, 0x00) | - cx231xx_set_field(FLD_AUD_CHAN1_SRC, 0x03)); - - status = vid_blk_write_word(dev, PATH1_CTL1, 0x1F063870); - - /* setAudioStandard(_audio_standard); */ - status = vid_blk_write_word(dev, PATH1_CTL1, 0x00063870); - - status = restartAudioFirmware(dev); - - switch (dev->board.tuner_type) { - case TUNER_XC5000: - /* SIF passthrough at 28.6363 MHz sample rate */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - CHIP_CTRL, - FLD_SIF_EN, - cx231xx_set_field(FLD_SIF_EN, 1)); - break; - case TUNER_NXP_TDA18271: - /* Normal mode: SIF passthrough at 14.32 MHz */ - status = cx231xx_read_modify_write_i2c_dword(dev, - VID_BLK_I2C_ADDRESS, - CHIP_CTRL, - FLD_SIF_EN, - cx231xx_set_field(FLD_SIF_EN, 0)); - break; - default: - /* This is just a casual suggestion to people adding - new boards in case they use a tuner type we don't - currently know about */ - printk(KERN_INFO "Unknown tuner type configuring SIF"); - break; - } - break; - - case AUDIO_INPUT_TUNER_FM: - /* use SIF for FM radio - setupFM(); - setAudioStandard(_audio_standard); - */ - break; - - case AUDIO_INPUT_MUTE: - status = vid_blk_write_word(dev, PATH1_CTL1, 0x1F011012); - break; - } - - /* Take it out of soft reset */ - status = vid_blk_read_byte(dev, GENERAL_CTL, &gen_ctrl); - gen_ctrl &= ~1; - status = vid_blk_write_byte(dev, GENERAL_CTL, gen_ctrl); - - return status; -} - -/****************************************************************************** - * C H I P Specific C O N T R O L functions * - ******************************************************************************/ -int cx231xx_init_ctrl_pin_status(struct cx231xx *dev) -{ - u32 value; - int status = 0; - - status = vid_blk_read_word(dev, PIN_CTRL, &value); - value |= (~dev->board.ctl_pin_status_mask); - status = vid_blk_write_word(dev, PIN_CTRL, value); - - return status; -} - -int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev, - u8 analog_or_digital) -{ - int status = 0; - - /* first set the direction to output */ - status = cx231xx_set_gpio_direction(dev, - dev->board. - agc_analog_digital_select_gpio, 1); - - /* 0 - demod ; 1 - Analog mode */ - status = cx231xx_set_gpio_value(dev, - dev->board.agc_analog_digital_select_gpio, - analog_or_digital); - - return status; -} - -int cx231xx_enable_i2c_port_3(struct cx231xx *dev, bool is_port_3) -{ - u8 value[4] = { 0, 0, 0, 0 }; - int status = 0; - bool current_is_port_3; - - if (dev->board.dont_use_port_3) - is_port_3 = false; - status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, - PWR_CTL_EN, value, 4); - if (status < 0) - return status; - - current_is_port_3 = value[0] & I2C_DEMOD_EN ? true : false; - - /* Just return, if already using the right port */ - if (current_is_port_3 == is_port_3) - return 0; - - if (is_port_3) - value[0] |= I2C_DEMOD_EN; - else - value[0] &= ~I2C_DEMOD_EN; - - cx231xx_info("Changing the i2c master port to %d\n", - is_port_3 ? 3 : 1); - - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - - return status; - -} -EXPORT_SYMBOL_GPL(cx231xx_enable_i2c_port_3); - -void update_HH_register_after_set_DIF(struct cx231xx *dev) -{ -/* - u8 status = 0; - u32 value = 0; - - vid_blk_write_word(dev, PIN_CTRL, 0xA0FFF82F); - vid_blk_write_word(dev, DIF_MISC_CTRL, 0x0A203F11); - vid_blk_write_word(dev, DIF_SRC_PHASE_INC, 0x1BEFBF06); - - status = vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value); - vid_blk_write_word(dev, AFE_CTRL_C2HH_SRC_CTRL, 0x4485D390); - status = vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value); -*/ -} - -void cx231xx_dump_HH_reg(struct cx231xx *dev) -{ - u32 value = 0; - u16 i = 0; - - value = 0x45005390; - vid_blk_write_word(dev, 0x104, value); - - for (i = 0x100; i < 0x140; i++) { - vid_blk_read_word(dev, i, &value); - cx231xx_info("reg0x%x=0x%x\n", i, value); - i = i+3; - } - - for (i = 0x300; i < 0x400; i++) { - vid_blk_read_word(dev, i, &value); - cx231xx_info("reg0x%x=0x%x\n", i, value); - i = i+3; - } - - for (i = 0x400; i < 0x440; i++) { - vid_blk_read_word(dev, i, &value); - cx231xx_info("reg0x%x=0x%x\n", i, value); - i = i+3; - } - - vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value); - cx231xx_info("AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value); - vid_blk_write_word(dev, AFE_CTRL_C2HH_SRC_CTRL, 0x4485D390); - vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value); - cx231xx_info("AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value); -} - -void cx231xx_dump_SC_reg(struct cx231xx *dev) -{ - u8 value[4] = { 0, 0, 0, 0 }; - cx231xx_info("cx231xx_dump_SC_reg!\n"); - - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", BOARD_CFG_STAT, value[0], - value[1], value[2], value[3]); - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS_MODE_REG, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS_MODE_REG, value[0], - value[1], value[2], value[3]); - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS1_CFG_REG, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS1_CFG_REG, value[0], - value[1], value[2], value[3]); - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS1_LENGTH_REG, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS1_LENGTH_REG, value[0], - value[1], value[2], value[3]); - - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS2_CFG_REG, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS2_CFG_REG, value[0], - value[1], value[2], value[3]); - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS2_LENGTH_REG, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS2_LENGTH_REG, value[0], - value[1], value[2], value[3]); - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", EP_MODE_SET, value[0], - value[1], value[2], value[3]); - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN1, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN1, value[0], - value[1], value[2], value[3]); - - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN2, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN2, value[0], - value[1], value[2], value[3]); - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN3, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN3, value[0], - value[1], value[2], value[3]); - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK0, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK0, value[0], - value[1], value[2], value[3]); - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK1, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK1, value[0], - value[1], value[2], value[3]); - - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK2, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK2, value[0], - value[1], value[2], value[3]); - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_GAIN, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_GAIN, value[0], - value[1], value[2], value[3]); - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_CAR_REG, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_CAR_REG, value[0], - value[1], value[2], value[3]); - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_OT_CFG1, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_OT_CFG1, value[0], - value[1], value[2], value[3]); - - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_OT_CFG2, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_OT_CFG2, value[0], - value[1], value[2], value[3]); - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, - value, 4); - cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN, value[0], - value[1], value[2], value[3]); - - -} - -void cx231xx_Setup_AFE_for_LowIF(struct cx231xx *dev) - -{ - u8 value = 0; - - afe_read_byte(dev, ADC_STATUS2_CH3, &value); - value = (value & 0xFE)|0x01; - afe_write_byte(dev, ADC_STATUS2_CH3, value); - - afe_read_byte(dev, ADC_STATUS2_CH3, &value); - value = (value & 0xFE)|0x00; - afe_write_byte(dev, ADC_STATUS2_CH3, value); - - -/* - config colibri to lo-if mode - - FIXME: ntf_mode = 2'b00 by default. But set 0x1 would reduce - the diff IF input by half, - - for low-if agc defect -*/ - - afe_read_byte(dev, ADC_NTF_PRECLMP_EN_CH3, &value); - value = (value & 0xFC)|0x00; - afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH3, value); - - afe_read_byte(dev, ADC_INPUT_CH3, &value); - value = (value & 0xF9)|0x02; - afe_write_byte(dev, ADC_INPUT_CH3, value); - - afe_read_byte(dev, ADC_FB_FRCRST_CH3, &value); - value = (value & 0xFB)|0x04; - afe_write_byte(dev, ADC_FB_FRCRST_CH3, value); - - afe_read_byte(dev, ADC_DCSERVO_DEM_CH3, &value); - value = (value & 0xFC)|0x03; - afe_write_byte(dev, ADC_DCSERVO_DEM_CH3, value); - - afe_read_byte(dev, ADC_CTRL_DAC1_CH3, &value); - value = (value & 0xFB)|0x04; - afe_write_byte(dev, ADC_CTRL_DAC1_CH3, value); - - afe_read_byte(dev, ADC_CTRL_DAC23_CH3, &value); - value = (value & 0xF8)|0x06; - afe_write_byte(dev, ADC_CTRL_DAC23_CH3, value); - - afe_read_byte(dev, ADC_CTRL_DAC23_CH3, &value); - value = (value & 0x8F)|0x40; - afe_write_byte(dev, ADC_CTRL_DAC23_CH3, value); - - afe_read_byte(dev, ADC_PWRDN_CLAMP_CH3, &value); - value = (value & 0xDF)|0x20; - afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, value); -} - -void cx231xx_set_Colibri_For_LowIF(struct cx231xx *dev, u32 if_freq, - u8 spectral_invert, u32 mode) -{ - u32 colibri_carrier_offset = 0; - u32 func_mode = 0x01; /* Device has a DIF if this function is called */ - u32 standard = 0; - u8 value[4] = { 0, 0, 0, 0 }; - - cx231xx_info("Enter cx231xx_set_Colibri_For_LowIF()\n"); - value[0] = (u8) 0x6F; - value[1] = (u8) 0x6F; - value[2] = (u8) 0x6F; - value[3] = (u8) 0x6F; - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - - /*Set colibri for low IF*/ - cx231xx_afe_set_mode(dev, AFE_MODE_LOW_IF); - - /* Set C2HH for low IF operation.*/ - standard = dev->norm; - cx231xx_dif_configure_C2HH_for_low_IF(dev, dev->active_mode, - func_mode, standard); - - /* Get colibri offsets.*/ - colibri_carrier_offset = cx231xx_Get_Colibri_CarrierOffset(mode, - standard); - - cx231xx_info("colibri_carrier_offset=%d, standard=0x%x\n", - colibri_carrier_offset, standard); - - /* Set the band Pass filter for DIF*/ - cx231xx_set_DIF_bandpass(dev, (if_freq+colibri_carrier_offset), - spectral_invert, mode); -} - -u32 cx231xx_Get_Colibri_CarrierOffset(u32 mode, u32 standerd) -{ - u32 colibri_carrier_offset = 0; - - if (mode == TUNER_MODE_FM_RADIO) { - colibri_carrier_offset = 1100000; - } else if (standerd & (V4L2_STD_MN | V4L2_STD_NTSC_M_JP)) { - colibri_carrier_offset = 4832000; /*4.83MHz */ - } else if (standerd & (V4L2_STD_PAL_B | V4L2_STD_PAL_G)) { - colibri_carrier_offset = 2700000; /*2.70MHz */ - } else if (standerd & (V4L2_STD_PAL_D | V4L2_STD_PAL_I - | V4L2_STD_SECAM)) { - colibri_carrier_offset = 2100000; /*2.10MHz */ - } - - return colibri_carrier_offset; -} - -void cx231xx_set_DIF_bandpass(struct cx231xx *dev, u32 if_freq, - u8 spectral_invert, u32 mode) -{ - unsigned long pll_freq_word; - u32 dif_misc_ctrl_value = 0; - u64 pll_freq_u64 = 0; - u32 i = 0; - - cx231xx_info("if_freq=%d;spectral_invert=0x%x;mode=0x%x\n", - if_freq, spectral_invert, mode); - - - if (mode == TUNER_MODE_FM_RADIO) { - pll_freq_word = 0x905A1CAC; - vid_blk_write_word(dev, DIF_PLL_FREQ_WORD, pll_freq_word); - - } else /*KSPROPERTY_TUNER_MODE_TV*/{ - /* Calculate the PLL frequency word based on the adjusted if_freq*/ - pll_freq_word = if_freq; - pll_freq_u64 = (u64)pll_freq_word << 28L; - do_div(pll_freq_u64, 50000000); - pll_freq_word = (u32)pll_freq_u64; - /*pll_freq_word = 0x3463497;*/ - vid_blk_write_word(dev, DIF_PLL_FREQ_WORD, pll_freq_word); - - if (spectral_invert) { - if_freq -= 400000; - /* Enable Spectral Invert*/ - vid_blk_read_word(dev, DIF_MISC_CTRL, - &dif_misc_ctrl_value); - dif_misc_ctrl_value = dif_misc_ctrl_value | 0x00200000; - vid_blk_write_word(dev, DIF_MISC_CTRL, - dif_misc_ctrl_value); - } else { - if_freq += 400000; - /* Disable Spectral Invert*/ - vid_blk_read_word(dev, DIF_MISC_CTRL, - &dif_misc_ctrl_value); - dif_misc_ctrl_value = dif_misc_ctrl_value & 0xFFDFFFFF; - vid_blk_write_word(dev, DIF_MISC_CTRL, - dif_misc_ctrl_value); - } - - if_freq = (if_freq/100000)*100000; - - if (if_freq < 3000000) - if_freq = 3000000; - - if (if_freq > 16000000) - if_freq = 16000000; - } - - cx231xx_info("Enter IF=%zd\n", - ARRAY_SIZE(Dif_set_array)); - for (i = 0; i < ARRAY_SIZE(Dif_set_array); i++) { - if (Dif_set_array[i].if_freq == if_freq) { - vid_blk_write_word(dev, - Dif_set_array[i].register_address, Dif_set_array[i].value); - } - } -} - -/****************************************************************************** - * D I F - B L O C K C O N T R O L functions * - ******************************************************************************/ -int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, - u32 function_mode, u32 standard) -{ - int status = 0; - - - if (mode == V4L2_TUNER_RADIO) { - /* C2HH */ - /* lo if big signal */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); - /* FUNC_MODE = DIF */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); - /* IF_MODE */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xFF); - /* no inv */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); - } else if (standard != DIF_USE_BASEBAND) { - if (standard & V4L2_STD_MN) { - /* lo if big signal */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); - /* FUNC_MODE = DIF */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 23, 24, - function_mode); - /* IF_MODE */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xb); - /* no inv */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); - /* 0x124, AUD_CHAN1_SRC = 0x3 */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AUD_IO_CTRL, 0, 31, 0x00000003); - } else if ((standard == V4L2_STD_PAL_I) | - (standard & V4L2_STD_PAL_D) | - (standard & V4L2_STD_SECAM)) { - /* C2HH setup */ - /* lo if big signal */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); - /* FUNC_MODE = DIF */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 23, 24, - function_mode); - /* IF_MODE */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xF); - /* no inv */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); - } else { - /* default PAL BG */ - /* C2HH setup */ - /* lo if big signal */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1); - /* FUNC_MODE = DIF */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 23, 24, - function_mode); - /* IF_MODE */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xE); - /* no inv */ - status = cx231xx_reg_mask_write(dev, - VID_BLK_I2C_ADDRESS, 32, - AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1); - } - } - - return status; -} - -int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) -{ - int status = 0; - u32 dif_misc_ctrl_value = 0; - u32 func_mode = 0; - - cx231xx_info("%s: setStandard to %x\n", __func__, standard); - - status = vid_blk_read_word(dev, DIF_MISC_CTRL, &dif_misc_ctrl_value); - if (standard != DIF_USE_BASEBAND) - dev->norm = standard; - - switch (dev->model) { - case CX231XX_BOARD_CNXT_CARRAERA: - case CX231XX_BOARD_CNXT_RDE_250: - case CX231XX_BOARD_CNXT_SHELBY: - case CX231XX_BOARD_CNXT_RDU_250: - case CX231XX_BOARD_CNXT_VIDEO_GRABBER: - case CX231XX_BOARD_HAUPPAUGE_EXETER: - func_mode = 0x03; - break; - case CX231XX_BOARD_CNXT_RDE_253S: - case CX231XX_BOARD_CNXT_RDU_253S: - case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL: - case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC: - func_mode = 0x01; - break; - default: - func_mode = 0x01; - } - - status = cx231xx_dif_configure_C2HH_for_low_IF(dev, dev->active_mode, - func_mode, standard); - - if (standard == DIF_USE_BASEBAND) { /* base band */ - /* There is a different SRC_PHASE_INC value - for baseband vs. DIF */ - status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC, 0xDF7DF83); - status = vid_blk_read_word(dev, DIF_MISC_CTRL, - &dif_misc_ctrl_value); - dif_misc_ctrl_value |= FLD_DIF_DIF_BYPASS; - status = vid_blk_write_word(dev, DIF_MISC_CTRL, - dif_misc_ctrl_value); - } else if (standard & V4L2_STD_PAL_D) { - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_IF_REF, 0, 31, 0x444C1380); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_IF_INT_CURRENT, 0, 31, - 0x26001700); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_RF_CURRENT, 0, 31, - 0x00002660); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_VIDEO_AGC_CTRL, 0, 31, - 0x72500800); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_VID_AUD_OVERRIDE, 0, 31, - 0x27000100); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AV_SEP_CTRL, 0, 31, 0x3F3934EA); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_COMP_FLT_CTRL, 0, 31, - 0x00000000); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_SRC_PHASE_INC, 0, 31, - 0x1befbf06); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_SRC_GAIN_CONTROL, 0, 31, - 0x000035e8); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_RPT_VARIANCE, 0, 31, 0x00000000); - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value |= 0x3a023F11; - } else if (standard & V4L2_STD_PAL_I) { - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_IF_REF, 0, 31, 0x444C1380); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_IF_INT_CURRENT, 0, 31, - 0x26001700); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_RF_CURRENT, 0, 31, - 0x00002660); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_VIDEO_AGC_CTRL, 0, 31, - 0x72500800); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_VID_AUD_OVERRIDE, 0, 31, - 0x27000100); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AV_SEP_CTRL, 0, 31, 0x5F39A934); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_COMP_FLT_CTRL, 0, 31, - 0x00000000); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_SRC_PHASE_INC, 0, 31, - 0x1befbf06); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_SRC_GAIN_CONTROL, 0, 31, - 0x000035e8); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_RPT_VARIANCE, 0, 31, 0x00000000); - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value |= 0x3a033F11; - } else if (standard & V4L2_STD_PAL_M) { - /* improved Low Frequency Phase Noise */ - status = vid_blk_write_word(dev, DIF_PLL_CTRL, 0xFF01FF0C); - status = vid_blk_write_word(dev, DIF_PLL_CTRL1, 0xbd038c85); - status = vid_blk_write_word(dev, DIF_PLL_CTRL2, 0x1db4640a); - status = vid_blk_write_word(dev, DIF_PLL_CTRL3, 0x00008800); - status = vid_blk_write_word(dev, DIF_AGC_IF_REF, 0x444C1380); - status = vid_blk_write_word(dev, DIF_AGC_IF_INT_CURRENT, - 0x26001700); - status = vid_blk_write_word(dev, DIF_AGC_RF_CURRENT, - 0x00002660); - status = vid_blk_write_word(dev, DIF_VIDEO_AGC_CTRL, - 0x72500800); - status = vid_blk_write_word(dev, DIF_VID_AUD_OVERRIDE, - 0x27000100); - status = vid_blk_write_word(dev, DIF_AV_SEP_CTRL, 0x012c405d); - status = vid_blk_write_word(dev, DIF_COMP_FLT_CTRL, - 0x009f50c1); - status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC, - 0x1befbf06); - status = vid_blk_write_word(dev, DIF_SRC_GAIN_CONTROL, - 0x000035e8); - status = vid_blk_write_word(dev, DIF_SOFT_RST_CTRL_REVB, - 0x00000000); - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value |= 0x3A0A3F10; - } else if (standard & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) { - /* improved Low Frequency Phase Noise */ - status = vid_blk_write_word(dev, DIF_PLL_CTRL, 0xFF01FF0C); - status = vid_blk_write_word(dev, DIF_PLL_CTRL1, 0xbd038c85); - status = vid_blk_write_word(dev, DIF_PLL_CTRL2, 0x1db4640a); - status = vid_blk_write_word(dev, DIF_PLL_CTRL3, 0x00008800); - status = vid_blk_write_word(dev, DIF_AGC_IF_REF, 0x444C1380); - status = vid_blk_write_word(dev, DIF_AGC_IF_INT_CURRENT, - 0x26001700); - status = vid_blk_write_word(dev, DIF_AGC_RF_CURRENT, - 0x00002660); - status = vid_blk_write_word(dev, DIF_VIDEO_AGC_CTRL, - 0x72500800); - status = vid_blk_write_word(dev, DIF_VID_AUD_OVERRIDE, - 0x27000100); - status = vid_blk_write_word(dev, DIF_AV_SEP_CTRL, - 0x012c405d); - status = vid_blk_write_word(dev, DIF_COMP_FLT_CTRL, - 0x009f50c1); - status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC, - 0x1befbf06); - status = vid_blk_write_word(dev, DIF_SRC_GAIN_CONTROL, - 0x000035e8); - status = vid_blk_write_word(dev, DIF_SOFT_RST_CTRL_REVB, - 0x00000000); - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value = 0x3A093F10; - } else if (standard & - (V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G | - V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1)) { - - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_IF_REF, 0, 31, 0x888C0380); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_CTRL_IF, 0, 31, 0xe0262600); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_CTRL_INT, 0, 31, 0xc2171700); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_CTRL_RF, 0, 31, 0xc2262600); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_IF_INT_CURRENT, 0, 31, - 0x26001700); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_RF_CURRENT, 0, 31, - 0x00002660); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_VID_AUD_OVERRIDE, 0, 31, - 0x27000100); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_COMP_FLT_CTRL, 0, 31, - 0x00000000); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_SRC_PHASE_INC, 0, 31, - 0x1befbf06); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_SRC_GAIN_CONTROL, 0, 31, - 0x000035e8); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_RPT_VARIANCE, 0, 31, 0x00000000); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_VIDEO_AGC_CTRL, 0, 31, - 0xf4000000); - - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value |= 0x3a023F11; - } else if (standard & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) { - /* Is it SECAM_L1? */ - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_IF_REF, 0, 31, 0x888C0380); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_CTRL_IF, 0, 31, 0xe0262600); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_CTRL_INT, 0, 31, 0xc2171700); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_CTRL_RF, 0, 31, 0xc2262600); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_IF_INT_CURRENT, 0, 31, - 0x26001700); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_RF_CURRENT, 0, 31, - 0x00002660); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_VID_AUD_OVERRIDE, 0, 31, - 0x27000100); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_COMP_FLT_CTRL, 0, 31, - 0x00000000); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_SRC_PHASE_INC, 0, 31, - 0x1befbf06); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_SRC_GAIN_CONTROL, 0, 31, - 0x000035e8); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_RPT_VARIANCE, 0, 31, 0x00000000); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_VIDEO_AGC_CTRL, 0, 31, - 0xf2560000); - - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value |= 0x3a023F11; - - } else if (standard & V4L2_STD_NTSC_M) { - /* V4L2_STD_NTSC_M (75 IRE Setup) Or - V4L2_STD_NTSC_M_JP (Japan, 0 IRE Setup) */ - - /* For NTSC the centre frequency of video coming out of - sidewinder is around 7.1MHz or 3.6MHz depending on the - spectral inversion. so for a non spectrally inverted channel - the pll freq word is 0x03420c49 - */ - - status = vid_blk_write_word(dev, DIF_PLL_CTRL, 0x6503BC0C); - status = vid_blk_write_word(dev, DIF_PLL_CTRL1, 0xBD038C85); - status = vid_blk_write_word(dev, DIF_PLL_CTRL2, 0x1DB4640A); - status = vid_blk_write_word(dev, DIF_PLL_CTRL3, 0x00008800); - status = vid_blk_write_word(dev, DIF_AGC_IF_REF, 0x444C0380); - status = vid_blk_write_word(dev, DIF_AGC_IF_INT_CURRENT, - 0x26001700); - status = vid_blk_write_word(dev, DIF_AGC_RF_CURRENT, - 0x00002660); - status = vid_blk_write_word(dev, DIF_VIDEO_AGC_CTRL, - 0x04000800); - status = vid_blk_write_word(dev, DIF_VID_AUD_OVERRIDE, - 0x27000100); - status = vid_blk_write_word(dev, DIF_AV_SEP_CTRL, 0x01296e1f); - - status = vid_blk_write_word(dev, DIF_COMP_FLT_CTRL, - 0x009f50c1); - status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC, - 0x1befbf06); - status = vid_blk_write_word(dev, DIF_SRC_GAIN_CONTROL, - 0x000035e8); - - status = vid_blk_write_word(dev, DIF_AGC_CTRL_IF, 0xC2262600); - status = vid_blk_write_word(dev, DIF_AGC_CTRL_INT, - 0xC2262600); - status = vid_blk_write_word(dev, DIF_AGC_CTRL_RF, 0xC2262600); - - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value |= 0x3a003F10; - } else { - /* default PAL BG */ - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL, 0, 31, 0x6503bc0c); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL1, 0, 31, 0xbd038c85); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL2, 0, 31, 0x1db4640a); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_PLL_CTRL3, 0, 31, 0x00008800); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_IF_REF, 0, 31, 0x444C1380); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_CTRL_IF, 0, 31, 0xDA302600); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_CTRL_INT, 0, 31, 0xDA261700); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_CTRL_RF, 0, 31, 0xDA262600); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_IF_INT_CURRENT, 0, 31, - 0x26001700); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AGC_RF_CURRENT, 0, 31, - 0x00002660); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_VIDEO_AGC_CTRL, 0, 31, - 0x72500800); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_VID_AUD_OVERRIDE, 0, 31, - 0x27000100); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_AV_SEP_CTRL, 0, 31, 0x3F3530EC); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_COMP_FLT_CTRL, 0, 31, - 0x00A653A8); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_SRC_PHASE_INC, 0, 31, - 0x1befbf06); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_SRC_GAIN_CONTROL, 0, 31, - 0x000035e8); - status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32, - DIF_RPT_VARIANCE, 0, 31, 0x00000000); - /* Save the Spec Inversion value */ - dif_misc_ctrl_value &= FLD_DIF_SPEC_INV; - dif_misc_ctrl_value |= 0x3a013F11; - } - - /* The AGC values should be the same for all standards, - AUD_SRC_SEL[19] should always be disabled */ - dif_misc_ctrl_value &= ~FLD_DIF_AUD_SRC_SEL; - - /* It is still possible to get Set Standard calls even when we - are in FM mode. - This is done to override the value for FM. */ - if (dev->active_mode == V4L2_TUNER_RADIO) - dif_misc_ctrl_value = 0x7a080000; - - /* Write the calculated value for misc ontrol register */ - status = vid_blk_write_word(dev, DIF_MISC_CTRL, dif_misc_ctrl_value); - - return status; -} - -int cx231xx_tuner_pre_channel_change(struct cx231xx *dev) -{ - int status = 0; - u32 dwval; - - /* Set the RF and IF k_agc values to 3 */ - status = vid_blk_read_word(dev, DIF_AGC_IF_REF, &dwval); - dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF); - dwval |= 0x33000000; - - status = vid_blk_write_word(dev, DIF_AGC_IF_REF, dwval); - - return status; -} - -int cx231xx_tuner_post_channel_change(struct cx231xx *dev) -{ - int status = 0; - u32 dwval; - cx231xx_info("cx231xx_tuner_post_channel_change dev->tuner_type =0%d\n", - dev->tuner_type); - /* Set the RF and IF k_agc values to 4 for PAL/NTSC and 8 for - * SECAM L/B/D standards */ - status = vid_blk_read_word(dev, DIF_AGC_IF_REF, &dwval); - dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF); - - if (dev->norm & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_B | - V4L2_STD_SECAM_D)) { - if (dev->tuner_type == TUNER_NXP_TDA18271) { - dwval &= ~FLD_DIF_IF_REF; - dwval |= 0x88000300; - } else - dwval |= 0x88000000; - } else { - if (dev->tuner_type == TUNER_NXP_TDA18271) { - dwval &= ~FLD_DIF_IF_REF; - dwval |= 0xCC000300; - } else - dwval |= 0x44000000; - } - - status = vid_blk_write_word(dev, DIF_AGC_IF_REF, dwval); - - return status; -} - -/****************************************************************************** - * I 2 S - B L O C K C O N T R O L functions * - ******************************************************************************/ -int cx231xx_i2s_blk_initialize(struct cx231xx *dev) -{ - int status = 0; - u32 value; - - status = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, - CH_PWR_CTRL1, 1, &value, 1); - /* enables clock to delta-sigma and decimation filter */ - value |= 0x80; - status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, - CH_PWR_CTRL1, 1, value, 1); - /* power up all channel */ - status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, - CH_PWR_CTRL2, 1, 0x00, 1); - - return status; -} - -int cx231xx_i2s_blk_update_power_control(struct cx231xx *dev, - enum AV_MODE avmode) -{ - int status = 0; - u32 value = 0; - - if (avmode != POLARIS_AVMODE_ENXTERNAL_AV) { - status = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, - CH_PWR_CTRL2, 1, &value, 1); - value |= 0xfe; - status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, - CH_PWR_CTRL2, 1, value, 1); - } else { - status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, - CH_PWR_CTRL2, 1, 0x00, 1); - } - - return status; -} - -/* set i2s_blk for audio input types */ -int cx231xx_i2s_blk_set_audio_input(struct cx231xx *dev, u8 audio_input) -{ - int status = 0; - - switch (audio_input) { - case CX231XX_AMUX_LINE_IN: - status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, - CH_PWR_CTRL2, 1, 0x00, 1); - status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, - CH_PWR_CTRL1, 1, 0x80, 1); - break; - case CX231XX_AMUX_VIDEO: - default: - break; - } - - dev->ctl_ainput = audio_input; - - return status; -} - -/****************************************************************************** - * P O W E R C O N T R O L functions * - ******************************************************************************/ -int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode) -{ - u8 value[4] = { 0, 0, 0, 0 }; - u32 tmp = 0; - int status = 0; - - if (dev->power_mode != mode) - dev->power_mode = mode; - else { - cx231xx_info(" setPowerMode::mode = %d, No Change req.\n", - mode); - return 0; - } - - status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value, - 4); - if (status < 0) - return status; - - tmp = *((u32 *) value); - - switch (mode) { - case POLARIS_AVMODE_ENXTERNAL_AV: - - tmp &= (~PWR_MODE_MASK); - - tmp |= PWR_AV_EN; - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - msleep(PWR_SLEEP_INTERVAL); - - tmp |= PWR_ISO_EN; - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, - value, 4); - msleep(PWR_SLEEP_INTERVAL); - - tmp |= POLARIS_AVMODE_ENXTERNAL_AV; - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - - /* reset state of xceive tuner */ - dev->xc_fw_load_done = 0; - break; - - case POLARIS_AVMODE_ANALOGT_TV: - - tmp |= PWR_DEMOD_EN; - tmp |= (I2C_DEMOD_EN); - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - msleep(PWR_SLEEP_INTERVAL); - - if (!(tmp & PWR_TUNER_EN)) { - tmp |= (PWR_TUNER_EN); - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - msleep(PWR_SLEEP_INTERVAL); - } - - if (!(tmp & PWR_AV_EN)) { - tmp |= PWR_AV_EN; - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - msleep(PWR_SLEEP_INTERVAL); - } - if (!(tmp & PWR_ISO_EN)) { - tmp |= PWR_ISO_EN; - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - msleep(PWR_SLEEP_INTERVAL); - } - - if (!(tmp & POLARIS_AVMODE_ANALOGT_TV)) { - tmp |= POLARIS_AVMODE_ANALOGT_TV; - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - msleep(PWR_SLEEP_INTERVAL); - } - - if (dev->board.tuner_type != TUNER_ABSENT) { - /* Enable tuner */ - cx231xx_enable_i2c_port_3(dev, true); - - /* reset the Tuner */ - if (dev->board.tuner_gpio) - cx231xx_gpio_set(dev, dev->board.tuner_gpio); - - if (dev->cx231xx_reset_analog_tuner) - dev->cx231xx_reset_analog_tuner(dev); - } - - break; - - case POLARIS_AVMODE_DIGITAL: - if (!(tmp & PWR_TUNER_EN)) { - tmp |= (PWR_TUNER_EN); - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - msleep(PWR_SLEEP_INTERVAL); - } - if (!(tmp & PWR_AV_EN)) { - tmp |= PWR_AV_EN; - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - msleep(PWR_SLEEP_INTERVAL); - } - if (!(tmp & PWR_ISO_EN)) { - tmp |= PWR_ISO_EN; - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - msleep(PWR_SLEEP_INTERVAL); - } - - tmp &= (~PWR_AV_MODE); - tmp |= POLARIS_AVMODE_DIGITAL | I2C_DEMOD_EN; - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - msleep(PWR_SLEEP_INTERVAL); - - if (!(tmp & PWR_DEMOD_EN)) { - tmp |= PWR_DEMOD_EN; - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - msleep(PWR_SLEEP_INTERVAL); - } - - if (dev->board.tuner_type != TUNER_ABSENT) { - /* - * Enable tuner - * Hauppauge Exeter seems to need to do something different! - */ - if (dev->model == CX231XX_BOARD_HAUPPAUGE_EXETER) - cx231xx_enable_i2c_port_3(dev, false); - else - cx231xx_enable_i2c_port_3(dev, true); - - /* reset the Tuner */ - if (dev->board.tuner_gpio) - cx231xx_gpio_set(dev, dev->board.tuner_gpio); - - if (dev->cx231xx_reset_analog_tuner) - dev->cx231xx_reset_analog_tuner(dev); - } - break; - - default: - break; - } - - msleep(PWR_SLEEP_INTERVAL); - - /* For power saving, only enable Pwr_resetout_n - when digital TV is selected. */ - if (mode == POLARIS_AVMODE_DIGITAL) { - tmp |= PWR_RESETOUT_EN; - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - msleep(PWR_SLEEP_INTERVAL); - } - - /* update power control for afe */ - status = cx231xx_afe_update_power_control(dev, mode); - - /* update power control for i2s_blk */ - status = cx231xx_i2s_blk_update_power_control(dev, mode); - - status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value, - 4); - - return status; -} - -int cx231xx_power_suspend(struct cx231xx *dev) -{ - u8 value[4] = { 0, 0, 0, 0 }; - u32 tmp = 0; - int status = 0; - - status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, - value, 4); - if (status > 0) - return status; - - tmp = *((u32 *) value); - tmp &= (~PWR_MODE_MASK); - - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN, - value, 4); - - return status; -} - -/****************************************************************************** - * S T R E A M C O N T R O L functions * - ******************************************************************************/ -int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask) -{ - u8 value[4] = { 0x0, 0x0, 0x0, 0x0 }; - u32 tmp = 0; - int status = 0; - - cx231xx_info("cx231xx_start_stream():: ep_mask = %x\n", ep_mask); - status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET, - value, 4); - if (status < 0) - return status; - - tmp = *((u32 *) value); - tmp |= ep_mask; - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, EP_MODE_SET, - value, 4); - - return status; -} - -int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask) -{ - u8 value[4] = { 0x0, 0x0, 0x0, 0x0 }; - u32 tmp = 0; - int status = 0; - - cx231xx_info("cx231xx_stop_stream():: ep_mask = %x\n", ep_mask); - status = - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET, value, 4); - if (status < 0) - return status; - - tmp = *((u32 *) value); - tmp &= (~ep_mask); - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, EP_MODE_SET, - value, 4); - - return status; -} - -int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type) -{ - int status = 0; - u32 value = 0; - u8 val[4] = { 0, 0, 0, 0 }; - - if (dev->udev->speed == USB_SPEED_HIGH) { - switch (media_type) { - case Audio: - cx231xx_info("%s: Audio enter HANC\n", __func__); - status = - cx231xx_mode_register(dev, TS_MODE_REG, 0x9300); - break; - - case Vbi: - cx231xx_info("%s: set vanc registers\n", __func__); - status = cx231xx_mode_register(dev, TS_MODE_REG, 0x300); - break; - - case Sliced_cc: - cx231xx_info("%s: set hanc registers\n", __func__); - status = - cx231xx_mode_register(dev, TS_MODE_REG, 0x1300); - break; - - case Raw_Video: - cx231xx_info("%s: set video registers\n", __func__); - status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100); - break; - - case TS1_serial_mode: - cx231xx_info("%s: set ts1 registers", __func__); - - if (dev->board.has_417) { - cx231xx_info(" MPEG\n"); - value &= 0xFFFFFFFC; - value |= 0x3; - - status = cx231xx_mode_register(dev, TS_MODE_REG, value); - - val[0] = 0x04; - val[1] = 0xA3; - val[2] = 0x3B; - val[3] = 0x00; - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - TS1_CFG_REG, val, 4); - - val[0] = 0x00; - val[1] = 0x08; - val[2] = 0x00; - val[3] = 0x08; - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - TS1_LENGTH_REG, val, 4); - - } else { - cx231xx_info(" BDA\n"); - status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101); - status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x010); - } - break; - - case TS1_parallel_mode: - cx231xx_info("%s: set ts1 parallel mode registers\n", - __func__); - status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100); - status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400); - break; - } - } else { - status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101); - } - - return status; -} - -int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type) -{ - int rc = -1; - u32 ep_mask = -1; - struct pcb_config *pcb_config; - - /* get EP for media type */ - pcb_config = (struct pcb_config *)&dev->current_pcb_config; - - if (pcb_config->config_num) { - switch (media_type) { - case Raw_Video: - ep_mask = ENABLE_EP4; /* ep4 [00:1000] */ - break; - case Audio: - ep_mask = ENABLE_EP3; /* ep3 [00:0100] */ - break; - case Vbi: - ep_mask = ENABLE_EP5; /* ep5 [01:0000] */ - break; - case Sliced_cc: - ep_mask = ENABLE_EP6; /* ep6 [10:0000] */ - break; - case TS1_serial_mode: - case TS1_parallel_mode: - ep_mask = ENABLE_EP1; /* ep1 [00:0001] */ - break; - case TS2: - ep_mask = ENABLE_EP2; /* ep2 [00:0010] */ - break; - } - } - - if (start) { - rc = cx231xx_initialize_stream_xfer(dev, media_type); - - if (rc < 0) - return rc; - - /* enable video capture */ - if (ep_mask > 0) - rc = cx231xx_start_stream(dev, ep_mask); - } else { - /* disable video capture */ - if (ep_mask > 0) - rc = cx231xx_stop_stream(dev, ep_mask); - } - - if (dev->mode == CX231XX_ANALOG_MODE) - ;/* do any in Analog mode */ - else - ;/* do any in digital mode */ - - return rc; -} -EXPORT_SYMBOL_GPL(cx231xx_capture_start); - -/***************************************************************************** -* G P I O B I T control functions * -******************************************************************************/ -int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val) -{ - int status = 0; - - status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 0); - - return status; -} - -int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val) -{ - int status = 0; - - status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 1); - - return status; -} - -/* -* cx231xx_set_gpio_direction -* Sets the direction of the GPIO pin to input or output -* -* Parameters : -* pin_number : The GPIO Pin number to program the direction for -* from 0 to 31 -* pin_value : The Direction of the GPIO Pin under reference. -* 0 = Input direction -* 1 = Output direction -*/ -int cx231xx_set_gpio_direction(struct cx231xx *dev, - int pin_number, int pin_value) -{ - int status = 0; - u32 value = 0; - - /* Check for valid pin_number - if 32 , bail out */ - if (pin_number >= 32) - return -EINVAL; - - /* input */ - if (pin_value == 0) - value = dev->gpio_dir & (~(1 << pin_number)); /* clear */ - else - value = dev->gpio_dir | (1 << pin_number); - - status = cx231xx_set_gpio_bit(dev, value, (u8 *) &dev->gpio_val); - - /* cache the value for future */ - dev->gpio_dir = value; - - return status; -} - -/* -* cx231xx_set_gpio_value -* Sets the value of the GPIO pin to Logic high or low. The Pin under -* reference should ALREADY BE SET IN OUTPUT MODE !!!!!!!!! -* -* Parameters : -* pin_number : The GPIO Pin number to program the direction for -* pin_value : The value of the GPIO Pin under reference. -* 0 = set it to 0 -* 1 = set it to 1 -*/ -int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value) -{ - int status = 0; - u32 value = 0; - - /* Check for valid pin_number - if 0xFF , bail out */ - if (pin_number >= 32) - return -EINVAL; - - /* first do a sanity check - if the Pin is not output, make it output */ - if ((dev->gpio_dir & (1 << pin_number)) == 0x00) { - /* It was in input mode */ - value = dev->gpio_dir | (1 << pin_number); - dev->gpio_dir = value; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *) &dev->gpio_val); - value = 0; - } - - if (pin_value == 0) - value = dev->gpio_val & (~(1 << pin_number)); - else - value = dev->gpio_val | (1 << pin_number); - - /* store the value */ - dev->gpio_val = value; - - /* toggle bit0 of GP_IO */ - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - - return status; -} - -/***************************************************************************** -* G P I O I2C related functions * -******************************************************************************/ -int cx231xx_gpio_i2c_start(struct cx231xx *dev) -{ - int status = 0; - - /* set SCL to output 1 ; set SDA to output 1 */ - dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio; - dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio; - dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; - dev->gpio_val |= 1 << dev->board.tuner_sda_gpio; - - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - if (status < 0) - return -EINVAL; - - /* set SCL to output 1; set SDA to output 0 */ - dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; - dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); - - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - if (status < 0) - return -EINVAL; - - /* set SCL to output 0; set SDA to output 0 */ - dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); - - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - if (status < 0) - return -EINVAL; - - return status; -} - -int cx231xx_gpio_i2c_end(struct cx231xx *dev) -{ - int status = 0; - - /* set SCL to output 0; set SDA to output 0 */ - dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio; - dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio; - - dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); - - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - if (status < 0) - return -EINVAL; - - /* set SCL to output 1; set SDA to output 0 */ - dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; - dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); - - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - if (status < 0) - return -EINVAL; - - /* set SCL to input ,release SCL cable control - set SDA to input ,release SDA cable control */ - dev->gpio_dir &= ~(1 << dev->board.tuner_scl_gpio); - dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio); - - status = - cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - if (status < 0) - return -EINVAL; - - return status; -} - -int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data) -{ - int status = 0; - u8 i; - - /* set SCL to output ; set SDA to output */ - dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio; - dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio; - - for (i = 0; i < 8; i++) { - if (((data << i) & 0x80) == 0) { - /* set SCL to output 0; set SDA to output 0 */ - dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *)&dev->gpio_val); - - /* set SCL to output 1; set SDA to output 0 */ - dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *)&dev->gpio_val); - - /* set SCL to output 0; set SDA to output 0 */ - dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *)&dev->gpio_val); - } else { - /* set SCL to output 0; set SDA to output 1 */ - dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - dev->gpio_val |= 1 << dev->board.tuner_sda_gpio; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *)&dev->gpio_val); - - /* set SCL to output 1; set SDA to output 1 */ - dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *)&dev->gpio_val); - - /* set SCL to output 0; set SDA to output 1 */ - dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *)&dev->gpio_val); - } - } - return status; -} - -int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf) -{ - u8 value = 0; - int status = 0; - u32 gpio_logic_value = 0; - u8 i; - - /* read byte */ - for (i = 0; i < 8; i++) { /* send write I2c addr */ - - /* set SCL to output 0; set SDA to input */ - dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *)&dev->gpio_val); - - /* set SCL to output 1; set SDA to input */ - dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, - (u8 *)&dev->gpio_val); - - /* get SDA data bit */ - gpio_logic_value = dev->gpio_val; - status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, - (u8 *)&dev->gpio_val); - if ((dev->gpio_val & (1 << dev->board.tuner_sda_gpio)) != 0) - value |= (1 << (8 - i - 1)); - - dev->gpio_val = gpio_logic_value; - } - - /* set SCL to output 0,finish the read latest SCL signal. - !!!set SDA to input, never to modify SDA direction at - the same times */ - dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - - /* store the value */ - *buf = value & 0xff; - - return status; -} - -int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev) -{ - int status = 0; - u32 gpio_logic_value = 0; - int nCnt = 10; - int nInit = nCnt; - - /* clock stretch; set SCL to input; set SDA to input; - get SCL value till SCL = 1 */ - dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio); - dev->gpio_dir &= ~(1 << dev->board.tuner_scl_gpio); - - gpio_logic_value = dev->gpio_val; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - - do { - msleep(2); - status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, - (u8 *)&dev->gpio_val); - nCnt--; - } while (((dev->gpio_val & - (1 << dev->board.tuner_scl_gpio)) == 0) && - (nCnt > 0)); - - if (nCnt == 0) - cx231xx_info("No ACK after %d msec -GPIO I2C failed!", - nInit * 10); - - /* - * readAck - * through clock stretch, slave has given a SCL signal, - * so the SDA data can be directly read. - */ - status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - - if ((dev->gpio_val & 1 << dev->board.tuner_sda_gpio) == 0) { - dev->gpio_val = gpio_logic_value; - dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); - status = 0; - } else { - dev->gpio_val = gpio_logic_value; - dev->gpio_val |= (1 << dev->board.tuner_sda_gpio); - } - - /* read SDA end, set the SCL to output 0, after this operation, - SDA direction can be changed. */ - dev->gpio_val = gpio_logic_value; - dev->gpio_dir |= (1 << dev->board.tuner_scl_gpio); - dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - - return status; -} - -int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev) -{ - int status = 0; - - /* set SDA to ouput */ - dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - - /* set SCL = 0 (output); set SDA = 0 (output) */ - dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio); - dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - - /* set SCL = 1 (output); set SDA = 0 (output) */ - dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - - /* set SCL = 0 (output); set SDA = 0 (output) */ - dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - - /* set SDA to input,and then the slave will read data from SDA. */ - dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - - return status; -} - -int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev) -{ - int status = 0; - - /* set scl to output ; set sda to input */ - dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio; - dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - - /* set scl to output 0; set sda to input */ - dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio); - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - - /* set scl to output 1; set sda to input */ - dev->gpio_val |= 1 << dev->board.tuner_scl_gpio; - status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val); - - return status; -} - -/***************************************************************************** -* G P I O I2C related functions * -******************************************************************************/ -/* cx231xx_gpio_i2c_read - * Function to read data from gpio based I2C interface - */ -int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len) -{ - int status = 0; - int i = 0; - - /* get the lock */ - mutex_lock(&dev->gpio_i2c_lock); - - /* start */ - status = cx231xx_gpio_i2c_start(dev); - - /* write dev_addr */ - status = cx231xx_gpio_i2c_write_byte(dev, (dev_addr << 1) + 1); - - /* readAck */ - status = cx231xx_gpio_i2c_read_ack(dev); - - /* read data */ - for (i = 0; i < len; i++) { - /* read data */ - buf[i] = 0; - status = cx231xx_gpio_i2c_read_byte(dev, &buf[i]); - - if ((i + 1) != len) { - /* only do write ack if we more length */ - status = cx231xx_gpio_i2c_write_ack(dev); - } - } - - /* write NAK - inform reads are complete */ - status = cx231xx_gpio_i2c_write_nak(dev); - - /* write end */ - status = cx231xx_gpio_i2c_end(dev); - - /* release the lock */ - mutex_unlock(&dev->gpio_i2c_lock); - - return status; -} - -/* cx231xx_gpio_i2c_write - * Function to write data to gpio based I2C interface - */ -int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len) -{ - int i = 0; - - /* get the lock */ - mutex_lock(&dev->gpio_i2c_lock); - - /* start */ - cx231xx_gpio_i2c_start(dev); - - /* write dev_addr */ - cx231xx_gpio_i2c_write_byte(dev, dev_addr << 1); - - /* read Ack */ - cx231xx_gpio_i2c_read_ack(dev); - - for (i = 0; i < len; i++) { - /* Write data */ - cx231xx_gpio_i2c_write_byte(dev, buf[i]); - - /* read Ack */ - cx231xx_gpio_i2c_read_ack(dev); - } - - /* write End */ - cx231xx_gpio_i2c_end(dev); - - /* release the lock */ - mutex_unlock(&dev->gpio_i2c_lock); - - return 0; -} diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c deleted file mode 100644 index 02d4d36735d3..000000000000 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ /dev/null @@ -1,1370 +0,0 @@ -/* - cx231xx-cards.c - driver for Conexant Cx23100/101/102 - USB video capture devices - - Copyright (C) 2008 <srinivasa.deevi at conexant dot com> - Based on em28xx driver - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/usb.h> -#include <media/tuner.h> -#include <media/tveeprom.h> -#include <media/v4l2-common.h> -#include <media/v4l2-chip-ident.h> - -#include <media/cx25840.h> -#include "dvb-usb-ids.h" -#include "xc5000.h" -#include "tda18271.h" - -#include "cx231xx.h" - -static int tuner = -1; -module_param(tuner, int, 0444); -MODULE_PARM_DESC(tuner, "tuner type"); - -static int transfer_mode = 1; -module_param(transfer_mode, int, 0444); -MODULE_PARM_DESC(transfer_mode, "transfer mode (1-ISO or 0-BULK)"); - -static unsigned int disable_ir; -module_param(disable_ir, int, 0444); -MODULE_PARM_DESC(disable_ir, "disable infrared remote support"); - -/* Bitmask marking allocated devices from 0 to CX231XX_MAXBOARDS */ -static unsigned long cx231xx_devused; - -/* - * Reset sequences for analog/digital modes - */ - -static struct cx231xx_reg_seq RDE250_XCV_TUNER[] = { - {0x03, 0x01, 10}, - {0x03, 0x00, 30}, - {0x03, 0x01, 10}, - {-1, -1, -1}, -}; - -/* - * Board definitions - */ -struct cx231xx_board cx231xx_boards[] = { - [CX231XX_BOARD_UNKNOWN] = { - .name = "Unknown CX231xx video grabber", - .tuner_type = TUNER_ABSENT, - .input = {{ - .type = CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_3_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << 8) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - } - }, - }, - [CX231XX_BOARD_CNXT_CARRAERA] = { - .name = "Conexant Hybrid TV - CARRAERA", - .tuner_type = TUNER_XC5000, - .tuner_addr = 0x61, - .tuner_gpio = RDE250_XCV_TUNER, - .tuner_sif_gpio = 0x05, - .tuner_scl_gpio = 0x1a, - .tuner_sda_gpio = 0x1b, - .decoder = CX231XX_AVDECODER, - .output_mode = OUT_MODE_VIP11, - .demod_xfer_mode = 0, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x0c, - .gpio_pin_status_mask = 0x4001000, - .tuner_i2c_master = 1, - .demod_i2c_master = 2, - .has_dvb = 1, - .demod_addr = 0x02, - .norm = V4L2_STD_PAL, - - .input = {{ - .type = CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_3_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << 8) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - } - }, - }, - [CX231XX_BOARD_CNXT_SHELBY] = { - .name = "Conexant Hybrid TV - SHELBY", - .tuner_type = TUNER_XC5000, - .tuner_addr = 0x61, - .tuner_gpio = RDE250_XCV_TUNER, - .tuner_sif_gpio = 0x05, - .tuner_scl_gpio = 0x1a, - .tuner_sda_gpio = 0x1b, - .decoder = CX231XX_AVDECODER, - .output_mode = OUT_MODE_VIP11, - .demod_xfer_mode = 0, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x0c, - .gpio_pin_status_mask = 0x4001000, - .tuner_i2c_master = 1, - .demod_i2c_master = 2, - .has_dvb = 1, - .demod_addr = 0x32, - .norm = V4L2_STD_NTSC, - - .input = {{ - .type = CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_3_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << 8) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - } - }, - }, - [CX231XX_BOARD_CNXT_RDE_253S] = { - .name = "Conexant Hybrid TV - RDE253S", - .tuner_type = TUNER_NXP_TDA18271, - .tuner_addr = 0x60, - .tuner_gpio = RDE250_XCV_TUNER, - .tuner_sif_gpio = 0x05, - .tuner_scl_gpio = 0x1a, - .tuner_sda_gpio = 0x1b, - .decoder = CX231XX_AVDECODER, - .output_mode = OUT_MODE_VIP11, - .demod_xfer_mode = 0, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x1c, - .gpio_pin_status_mask = 0x4001000, - .tuner_i2c_master = 1, - .demod_i2c_master = 2, - .has_dvb = 1, - .demod_addr = 0x02, - .norm = V4L2_STD_PAL, - - .input = {{ - .type = CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_3_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << 8) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - } - }, - }, - - [CX231XX_BOARD_CNXT_RDU_253S] = { - .name = "Conexant Hybrid TV - RDU253S", - .tuner_type = TUNER_NXP_TDA18271, - .tuner_addr = 0x60, - .tuner_gpio = RDE250_XCV_TUNER, - .tuner_sif_gpio = 0x05, - .tuner_scl_gpio = 0x1a, - .tuner_sda_gpio = 0x1b, - .decoder = CX231XX_AVDECODER, - .output_mode = OUT_MODE_VIP11, - .demod_xfer_mode = 0, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x1c, - .gpio_pin_status_mask = 0x4001000, - .tuner_i2c_master = 1, - .demod_i2c_master = 2, - .has_dvb = 1, - .demod_addr = 0x02, - .norm = V4L2_STD_PAL, - - .input = {{ - .type = CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_3_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << 8) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - } - }, - }, - [CX231XX_BOARD_CNXT_VIDEO_GRABBER] = { - .name = "Conexant VIDEO GRABBER", - .tuner_type = TUNER_ABSENT, - .decoder = CX231XX_AVDECODER, - .output_mode = OUT_MODE_VIP11, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x1c, - .gpio_pin_status_mask = 0x4001000, - .norm = V4L2_STD_PAL, - .no_alt_vanc = 1, - .external_av = 1, - .has_417 = 1, - - .input = {{ - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << 8) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - } - }, - }, - [CX231XX_BOARD_CNXT_RDE_250] = { - .name = "Conexant Hybrid TV - rde 250", - .tuner_type = TUNER_XC5000, - .tuner_addr = 0x61, - .tuner_gpio = RDE250_XCV_TUNER, - .tuner_sif_gpio = 0x05, - .tuner_scl_gpio = 0x1a, - .tuner_sda_gpio = 0x1b, - .decoder = CX231XX_AVDECODER, - .output_mode = OUT_MODE_VIP11, - .demod_xfer_mode = 0, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x0c, - .gpio_pin_status_mask = 0x4001000, - .tuner_i2c_master = 1, - .demod_i2c_master = 2, - .has_dvb = 1, - .demod_addr = 0x02, - .norm = V4L2_STD_PAL, - - .input = {{ - .type = CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = NULL, - } - }, - }, - [CX231XX_BOARD_CNXT_RDU_250] = { - .name = "Conexant Hybrid TV - RDU 250", - .tuner_type = TUNER_XC5000, - .tuner_addr = 0x61, - .tuner_gpio = RDE250_XCV_TUNER, - .tuner_sif_gpio = 0x05, - .tuner_scl_gpio = 0x1a, - .tuner_sda_gpio = 0x1b, - .decoder = CX231XX_AVDECODER, - .output_mode = OUT_MODE_VIP11, - .demod_xfer_mode = 0, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x0c, - .gpio_pin_status_mask = 0x4001000, - .tuner_i2c_master = 1, - .demod_i2c_master = 2, - .has_dvb = 1, - .demod_addr = 0x32, - .norm = V4L2_STD_NTSC, - - .input = {{ - .type = CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = NULL, - } - }, - }, - [CX231XX_BOARD_HAUPPAUGE_EXETER] = { - .name = "Hauppauge EXETER", - .tuner_type = TUNER_NXP_TDA18271, - .tuner_addr = 0x60, - .tuner_gpio = RDE250_XCV_TUNER, - .tuner_sif_gpio = 0x05, - .tuner_scl_gpio = 0x1a, - .tuner_sda_gpio = 0x1b, - .decoder = CX231XX_AVDECODER, - .output_mode = OUT_MODE_VIP11, - .demod_xfer_mode = 0, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x0c, - .gpio_pin_status_mask = 0x4001000, - .tuner_i2c_master = 1, - .demod_i2c_master = 2, - .has_dvb = 1, - .demod_addr = 0x0e, - .norm = V4L2_STD_NTSC, - - .input = {{ - .type = CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_3_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << 8) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - } }, - }, - [CX231XX_BOARD_HAUPPAUGE_USBLIVE2] = { - .name = "Hauppauge USB Live 2", - .tuner_type = TUNER_ABSENT, - .decoder = CX231XX_AVDECODER, - .output_mode = OUT_MODE_VIP11, - .demod_xfer_mode = 0, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x0c, - .gpio_pin_status_mask = 0x4001000, - .norm = V4L2_STD_NTSC, - .no_alt_vanc = 1, - .external_av = 1, - .dont_use_port_3 = 1, - .input = {{ - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << 8) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - } }, - }, - [CX231XX_BOARD_KWORLD_UB430_USB_HYBRID] = { - .name = "Kworld UB430 USB Hybrid", - .tuner_type = TUNER_NXP_TDA18271, - .tuner_addr = 0x60, - .decoder = CX231XX_AVDECODER, - .output_mode = OUT_MODE_VIP11, - .demod_xfer_mode = 0, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x11, /* According with PV cxPolaris.inf file */ - .tuner_sif_gpio = -1, - .tuner_scl_gpio = -1, - .tuner_sda_gpio = -1, - .gpio_pin_status_mask = 0x4001000, - .tuner_i2c_master = 2, - .demod_i2c_master = 1, - .ir_i2c_master = 2, - .has_dvb = 1, - .demod_addr = 0x10, - .norm = V4L2_STD_PAL_M, - .input = {{ - .type = CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_3_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << 8) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - } }, - }, - [CX231XX_BOARD_PV_PLAYTV_USB_HYBRID] = { - .name = "Pixelview PlayTV USB Hybrid", - .tuner_type = TUNER_NXP_TDA18271, - .tuner_addr = 0x60, - .decoder = CX231XX_AVDECODER, - .output_mode = OUT_MODE_VIP11, - .demod_xfer_mode = 0, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x00, /* According with PV cxPolaris.inf file */ - .tuner_sif_gpio = -1, - .tuner_scl_gpio = -1, - .tuner_sda_gpio = -1, - .gpio_pin_status_mask = 0x4001000, - .tuner_i2c_master = 2, - .demod_i2c_master = 1, - .ir_i2c_master = 2, - .rc_map_name = RC_MAP_PIXELVIEW_002T, - .has_dvb = 1, - .demod_addr = 0x10, - .norm = V4L2_STD_PAL_M, - .input = {{ - .type = CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_3_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << 8) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - } }, - }, - [CX231XX_BOARD_PV_XCAPTURE_USB] = { - .name = "Pixelview Xcapture USB", - .tuner_type = TUNER_ABSENT, - .decoder = CX231XX_AVDECODER, - .output_mode = OUT_MODE_VIP11, - .demod_xfer_mode = 0, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x0c, - .gpio_pin_status_mask = 0x4001000, - .norm = V4L2_STD_NTSC, - .no_alt_vanc = 1, - .external_av = 1, - .dont_use_port_3 = 1, - - .input = {{ - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << 8) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - } - }, - }, - - [CX231XX_BOARD_ICONBIT_U100] = { - .name = "Iconbit Analog Stick U100 FM", - .tuner_type = TUNER_ABSENT, - .decoder = CX231XX_AVDECODER, - .output_mode = OUT_MODE_VIP11, - .demod_xfer_mode = 0, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x1C, - .gpio_pin_status_mask = 0x4001000, - - .input = {{ - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << 8) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - } }, - }, - [CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL] = { - .name = "Hauppauge WinTV USB2 FM (PAL)", - .tuner_type = TUNER_NXP_TDA18271, - .tuner_addr = 0x60, - .tuner_gpio = RDE250_XCV_TUNER, - .tuner_sif_gpio = 0x05, - .tuner_scl_gpio = 0x1a, - .tuner_sda_gpio = 0x1b, - .decoder = CX231XX_AVDECODER, - .output_mode = OUT_MODE_VIP11, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x0c, - .gpio_pin_status_mask = 0x4001000, - .tuner_i2c_master = 1, - .norm = V4L2_STD_PAL, - - .input = {{ - .type = CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_3_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << 8) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - } }, - }, - [CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC] = { - .name = "Hauppauge WinTV USB2 FM (NTSC)", - .tuner_type = TUNER_NXP_TDA18271, - .tuner_addr = 0x60, - .tuner_gpio = RDE250_XCV_TUNER, - .tuner_sif_gpio = 0x05, - .tuner_scl_gpio = 0x1a, - .tuner_sda_gpio = 0x1b, - .decoder = CX231XX_AVDECODER, - .output_mode = OUT_MODE_VIP11, - .ctl_pin_status_mask = 0xFFFFFFC4, - .agc_analog_digital_select_gpio = 0x0c, - .gpio_pin_status_mask = 0x4001000, - .tuner_i2c_master = 1, - .norm = V4L2_STD_NTSC, - - .input = {{ - .type = CX231XX_VMUX_TELEVISION, - .vmux = CX231XX_VIN_3_1, - .amux = CX231XX_AMUX_VIDEO, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_COMPOSITE1, - .vmux = CX231XX_VIN_2_1, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - }, { - .type = CX231XX_VMUX_SVIDEO, - .vmux = CX231XX_VIN_1_1 | - (CX231XX_VIN_1_2 << 8) | - CX25840_SVIDEO_ON, - .amux = CX231XX_AMUX_LINE_IN, - .gpio = NULL, - } }, - }, -}; -const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); - -/* table of devices that work with this driver */ -struct usb_device_id cx231xx_id_table[] = { - {USB_DEVICE(0x0572, 0x5A3C), - .driver_info = CX231XX_BOARD_UNKNOWN}, - {USB_DEVICE(0x0572, 0x58A2), - .driver_info = CX231XX_BOARD_CNXT_CARRAERA}, - {USB_DEVICE(0x0572, 0x58A1), - .driver_info = CX231XX_BOARD_CNXT_SHELBY}, - {USB_DEVICE(0x0572, 0x58A4), - .driver_info = CX231XX_BOARD_CNXT_RDE_253S}, - {USB_DEVICE(0x0572, 0x58A5), - .driver_info = CX231XX_BOARD_CNXT_RDU_253S}, - {USB_DEVICE(0x0572, 0x58A6), - .driver_info = CX231XX_BOARD_CNXT_VIDEO_GRABBER}, - {USB_DEVICE(0x0572, 0x589E), - .driver_info = CX231XX_BOARD_CNXT_RDE_250}, - {USB_DEVICE(0x0572, 0x58A0), - .driver_info = CX231XX_BOARD_CNXT_RDU_250}, - {USB_DEVICE(0x2040, 0xb110), - .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL}, - {USB_DEVICE(0x2040, 0xb111), - .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC}, - {USB_DEVICE(0x2040, 0xb120), - .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER}, - {USB_DEVICE(0x2040, 0xb140), - .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER}, - {USB_DEVICE(0x2040, 0xc200), - .driver_info = CX231XX_BOARD_HAUPPAUGE_USBLIVE2}, - {USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000, 0x4001), - .driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID}, - {USB_DEVICE(USB_VID_PIXELVIEW, 0x5014), - .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB}, - {USB_DEVICE(0x1b80, 0xe424), - .driver_info = CX231XX_BOARD_KWORLD_UB430_USB_HYBRID}, - {USB_DEVICE(0x1f4d, 0x0237), - .driver_info = CX231XX_BOARD_ICONBIT_U100}, - {}, -}; - -MODULE_DEVICE_TABLE(usb, cx231xx_id_table); - -/* cx231xx_tuner_callback - * will be used to reset XC5000 tuner using GPIO pin - */ - -int cx231xx_tuner_callback(void *ptr, int component, int command, int arg) -{ - int rc = 0; - struct cx231xx *dev = ptr; - - if (dev->tuner_type == TUNER_XC5000) { - if (command == XC5000_TUNER_RESET) { - cx231xx_info - ("Tuner CB: RESET: cmd %d : tuner type %d \n", - command, dev->tuner_type); - cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, - 1); - msleep(10); - cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, - 0); - msleep(330); - cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, - 1); - msleep(10); - } - } else if (dev->tuner_type == TUNER_NXP_TDA18271) { - switch (command) { - case TDA18271_CALLBACK_CMD_AGC_ENABLE: - if (dev->model == CX231XX_BOARD_PV_PLAYTV_USB_HYBRID) - rc = cx231xx_set_agc_analog_digital_mux_select(dev, arg); - break; - default: - rc = -EINVAL; - break; - } - } - return rc; -} -EXPORT_SYMBOL_GPL(cx231xx_tuner_callback); - -void cx231xx_reset_out(struct cx231xx *dev) -{ - cx231xx_set_gpio_value(dev, CX23417_RESET, 1); - msleep(200); - cx231xx_set_gpio_value(dev, CX23417_RESET, 0); - msleep(200); - cx231xx_set_gpio_value(dev, CX23417_RESET, 1); -} -void cx231xx_enable_OSC(struct cx231xx *dev) -{ - cx231xx_set_gpio_value(dev, CX23417_OSC_EN, 1); -} -void cx231xx_sleep_s5h1432(struct cx231xx *dev) -{ - cx231xx_set_gpio_value(dev, SLEEP_S5H1432, 0); -} - -static inline void cx231xx_set_model(struct cx231xx *dev) -{ - memcpy(&dev->board, &cx231xx_boards[dev->model], sizeof(dev->board)); -} - -/* Since cx231xx_pre_card_setup() requires a proper dev->model, - * this won't work for boards with generic PCI IDs - */ -void cx231xx_pre_card_setup(struct cx231xx *dev) -{ - - cx231xx_set_model(dev); - - cx231xx_info("Identified as %s (card=%d)\n", - dev->board.name, dev->model); - - /* set the direction for GPIO pins */ - if (dev->board.tuner_gpio) { - cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1); - cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1); - } - if (dev->board.tuner_sif_gpio >= 0) - cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1); - - /* request some modules if any required */ - - /* set the mode to Analog mode initially */ - cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); - - /* Unlock device */ - /* cx231xx_set_mode(dev, CX231XX_SUSPEND); */ - -} - -static void cx231xx_config_tuner(struct cx231xx *dev) -{ - struct tuner_setup tun_setup; - struct v4l2_frequency f; - - if (dev->tuner_type == TUNER_ABSENT) - return; - - tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; - tun_setup.type = dev->tuner_type; - tun_setup.addr = dev->tuner_addr; - tun_setup.tuner_callback = cx231xx_tuner_callback; - - tuner_call(dev, tuner, s_type_addr, &tun_setup); - -#if 0 - if (tun_setup.type == TUNER_XC5000) { - static struct xc2028_ctrl ctrl = { - .fname = XC5000_DEFAULT_FIRMWARE, - .max_len = 64, - .demod = 0; - }; - struct v4l2_priv_tun_config cfg = { - .tuner = dev->tuner_type, - .priv = &ctrl, - }; - tuner_call(dev, tuner, s_config, &cfg); - } -#endif - /* configure tuner */ - f.tuner = 0; - f.type = V4L2_TUNER_ANALOG_TV; - f.frequency = 9076; /* just a magic number */ - dev->ctl_freq = f.frequency; - call_all(dev, tuner, s_frequency, &f); - -} - -void cx231xx_card_setup(struct cx231xx *dev) -{ - - cx231xx_set_model(dev); - - dev->tuner_type = cx231xx_boards[dev->model].tuner_type; - if (cx231xx_boards[dev->model].tuner_addr) - dev->tuner_addr = cx231xx_boards[dev->model].tuner_addr; - - /* request some modules */ - if (dev->board.decoder == CX231XX_AVDECODER) { - dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_bus[0].i2c_adap, - "cx25840", 0x88 >> 1, NULL); - if (dev->sd_cx25840 == NULL) - cx231xx_info("cx25840 subdev registration failure\n"); - cx25840_call(dev, core, load_fw); - - } - - /* Initialize the tuner */ - if (dev->board.tuner_type != TUNER_ABSENT) { - dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap, - "tuner", - dev->tuner_addr, NULL); - if (dev->sd_tuner == NULL) - cx231xx_info("tuner subdev registration failure\n"); - else - cx231xx_config_tuner(dev); - } -} - -/* - * cx231xx_config() - * inits registers with sane defaults - */ -int cx231xx_config(struct cx231xx *dev) -{ - /* TBD need to add cx231xx specific code */ - dev->mute = 1; /* maybe not the right place... */ - dev->volume = 0x1f; - - return 0; -} - -/* - * cx231xx_config_i2c() - * configure i2c attached devices - */ -void cx231xx_config_i2c(struct cx231xx *dev) -{ - /* u32 input = INPUT(dev->video_input)->vmux; */ - - call_all(dev, video, s_stream, 1); -} - -/* - * cx231xx_realease_resources() - * unregisters the v4l2,i2c and usb devices - * called when the device gets disconected or at module unload -*/ -void cx231xx_release_resources(struct cx231xx *dev) -{ - cx231xx_release_analog_resources(dev); - - cx231xx_remove_from_devlist(dev); - - cx231xx_ir_exit(dev); - - /* Release I2C buses */ - cx231xx_dev_uninit(dev); - - /* delete v4l2 device */ - v4l2_device_unregister(&dev->v4l2_dev); - - usb_put_dev(dev->udev); - - /* Mark device as unused */ - clear_bit(dev->devno, &cx231xx_devused); - - kfree(dev->video_mode.alt_max_pkt_size); - kfree(dev->vbi_mode.alt_max_pkt_size); - kfree(dev->sliced_cc_mode.alt_max_pkt_size); - kfree(dev->ts1_mode.alt_max_pkt_size); - kfree(dev); -} - -/* - * cx231xx_init_dev() - * allocates and inits the device structs, registers i2c bus and v4l device - */ -static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev, - int minor) -{ - int retval = -ENOMEM; - int errCode; - unsigned int maxh, maxw; - - dev->udev = udev; - mutex_init(&dev->lock); - mutex_init(&dev->ctrl_urb_lock); - mutex_init(&dev->gpio_i2c_lock); - mutex_init(&dev->i2c_lock); - - spin_lock_init(&dev->video_mode.slock); - spin_lock_init(&dev->vbi_mode.slock); - spin_lock_init(&dev->sliced_cc_mode.slock); - - init_waitqueue_head(&dev->open); - init_waitqueue_head(&dev->wait_frame); - init_waitqueue_head(&dev->wait_stream); - - dev->cx231xx_read_ctrl_reg = cx231xx_read_ctrl_reg; - dev->cx231xx_write_ctrl_reg = cx231xx_write_ctrl_reg; - dev->cx231xx_send_usb_command = cx231xx_send_usb_command; - dev->cx231xx_gpio_i2c_read = cx231xx_gpio_i2c_read; - dev->cx231xx_gpio_i2c_write = cx231xx_gpio_i2c_write; - - /* Query cx231xx to find what pcb config it is related to */ - initialize_cx231xx(dev); - - /*To workaround error number=-71 on EP0 for VideoGrabber, - need set alt here.*/ - if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER || - dev->model == CX231XX_BOARD_HAUPPAUGE_USBLIVE2) { - cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3); - cx231xx_set_alt_setting(dev, INDEX_VANC, 1); - } - /* Cx231xx pre card setup */ - cx231xx_pre_card_setup(dev); - - errCode = cx231xx_config(dev); - if (errCode) { - cx231xx_errdev("error configuring device\n"); - return -ENOMEM; - } - - /* set default norm */ - dev->norm = dev->board.norm; - - /* register i2c bus */ - errCode = cx231xx_dev_init(dev); - if (errCode < 0) { - cx231xx_dev_uninit(dev); - cx231xx_errdev("%s: cx231xx_i2c_register - errCode [%d]!\n", - __func__, errCode); - return errCode; - } - - /* Do board specific init */ - cx231xx_card_setup(dev); - - /* configure the device */ - cx231xx_config_i2c(dev); - - maxw = norm_maxw(dev); - maxh = norm_maxh(dev); - - /* set default image size */ - dev->width = maxw; - dev->height = maxh; - dev->interlaced = 0; - dev->video_input = 0; - - errCode = cx231xx_config(dev); - if (errCode < 0) { - cx231xx_errdev("%s: cx231xx_config - errCode [%d]!\n", - __func__, errCode); - return errCode; - } - - /* init video dma queues */ - INIT_LIST_HEAD(&dev->video_mode.vidq.active); - INIT_LIST_HEAD(&dev->video_mode.vidq.queued); - - /* init vbi dma queues */ - INIT_LIST_HEAD(&dev->vbi_mode.vidq.active); - INIT_LIST_HEAD(&dev->vbi_mode.vidq.queued); - - /* Reset other chips required if they are tied up with GPIO pins */ - cx231xx_add_into_devlist(dev); - - if (dev->board.has_417) { - printk(KERN_INFO "attach 417 %d\n", dev->model); - if (cx231xx_417_register(dev) < 0) { - printk(KERN_ERR - "%s() Failed to register 417 on VID_B\n", - __func__); - } - } - - retval = cx231xx_register_analog_devices(dev); - if (retval < 0) { - cx231xx_release_resources(dev); - return retval; - } - - cx231xx_ir_init(dev); - - cx231xx_init_extension(dev); - - return 0; -} - -#if defined(CONFIG_MODULES) && defined(MODULE) -static void request_module_async(struct work_struct *work) -{ - struct cx231xx *dev = container_of(work, - struct cx231xx, request_module_wk); - - if (dev->has_alsa_audio) - request_module("cx231xx-alsa"); - - if (dev->board.has_dvb) - request_module("cx231xx-dvb"); - -} - -static void request_modules(struct cx231xx *dev) -{ - INIT_WORK(&dev->request_module_wk, request_module_async); - schedule_work(&dev->request_module_wk); -} - -static void flush_request_modules(struct cx231xx *dev) -{ - flush_work_sync(&dev->request_module_wk); -} -#else -#define request_modules(dev) -#define flush_request_modules(dev) -#endif /* CONFIG_MODULES */ - -/* - * cx231xx_usb_probe() - * checks for supported devices - */ -static int cx231xx_usb_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_device *udev; - struct usb_interface *uif; - struct cx231xx *dev = NULL; - int retval = -ENODEV; - int nr = 0, ifnum; - int i, isoc_pipe = 0; - char *speed; - struct usb_interface_assoc_descriptor *assoc_desc; - - udev = usb_get_dev(interface_to_usbdev(interface)); - ifnum = interface->altsetting[0].desc.bInterfaceNumber; - - /* - * Interface number 0 - IR interface (handled by mceusb driver) - * Interface number 1 - AV interface (handled by this driver) - */ - if (ifnum != 1) - return -ENODEV; - - /* Check to see next free device and mark as used */ - do { - nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS); - if (nr >= CX231XX_MAXBOARDS) { - /* No free device slots */ - cx231xx_err(DRIVER_NAME ": Supports only %i devices.\n", - CX231XX_MAXBOARDS); - return -ENOMEM; - } - } while (test_and_set_bit(nr, &cx231xx_devused)); - - /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - cx231xx_err(DRIVER_NAME ": out of memory!\n"); - clear_bit(nr, &cx231xx_devused); - return -ENOMEM; - } - - snprintf(dev->name, 29, "cx231xx #%d", nr); - dev->devno = nr; - dev->model = id->driver_info; - dev->video_mode.alt = -1; - - dev->interface_count++; - /* reset gpio dir and value */ - dev->gpio_dir = 0; - dev->gpio_val = 0; - dev->xc_fw_load_done = 0; - dev->has_alsa_audio = 1; - dev->power_mode = -1; - atomic_set(&dev->devlist_count, 0); - - /* 0 - vbi ; 1 -sliced cc mode */ - dev->vbi_or_sliced_cc_mode = 0; - - /* get maximum no.of IAD interfaces */ - assoc_desc = udev->actconfig->intf_assoc[0]; - dev->max_iad_interface_count = assoc_desc->bInterfaceCount; - - /* init CIR module TBD */ - - /*mode_tv: digital=1 or analog=0*/ - dev->mode_tv = 0; - - dev->USE_ISO = transfer_mode; - - switch (udev->speed) { - case USB_SPEED_LOW: - speed = "1.5"; - break; - case USB_SPEED_UNKNOWN: - case USB_SPEED_FULL: - speed = "12"; - break; - case USB_SPEED_HIGH: - speed = "480"; - break; - default: - speed = "unknown"; - } - - cx231xx_info("New device %s %s @ %s Mbps " - "(%04x:%04x) with %d interfaces\n", - udev->manufacturer ? udev->manufacturer : "", - udev->product ? udev->product : "", - speed, - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), - dev->max_iad_interface_count); - - /* increment interface count */ - dev->interface_count++; - - /* get device number */ - nr = dev->devno; - - assoc_desc = udev->actconfig->intf_assoc[0]; - if (assoc_desc->bFirstInterface != ifnum) { - cx231xx_err(DRIVER_NAME ": Not found " - "matching IAD interface\n"); - clear_bit(dev->devno, &cx231xx_devused); - kfree(dev); - dev = NULL; - return -ENODEV; - } - - cx231xx_info("registering interface %d\n", ifnum); - - /* save our data pointer in this interface device */ - usb_set_intfdata(interface, dev); - - /* - * AV device initialization - only done at the last interface - */ - - /* Create v4l2 device */ - retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); - if (retval) { - cx231xx_errdev("v4l2_device_register failed\n"); - clear_bit(dev->devno, &cx231xx_devused); - kfree(dev); - dev = NULL; - return -EIO; - } - /* allocate device struct */ - retval = cx231xx_init_dev(dev, udev, nr); - if (retval) { - clear_bit(dev->devno, &cx231xx_devused); - v4l2_device_unregister(&dev->v4l2_dev); - kfree(dev); - dev = NULL; - usb_set_intfdata(interface, NULL); - - return retval; - } - - /* compute alternate max packet sizes for video */ - uif = udev->actconfig->interface[dev->current_pcb_config. - hs_config_info[0].interface_info.video_index + 1]; - - dev->video_mode.end_point_addr = le16_to_cpu(uif->altsetting[0]. - endpoint[isoc_pipe].desc.bEndpointAddress); - - dev->video_mode.num_alt = uif->num_altsetting; - cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", - dev->video_mode.end_point_addr, - dev->video_mode.num_alt); - dev->video_mode.alt_max_pkt_size = - kmalloc(32 * dev->video_mode.num_alt, GFP_KERNEL); - - if (dev->video_mode.alt_max_pkt_size == NULL) { - cx231xx_errdev("out of memory!\n"); - clear_bit(dev->devno, &cx231xx_devused); - v4l2_device_unregister(&dev->v4l2_dev); - kfree(dev); - dev = NULL; - return -ENOMEM; - } - - for (i = 0; i < dev->video_mode.num_alt; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. - desc.wMaxPacketSize); - dev->video_mode.alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - cx231xx_info("Alternate setting %i, max size= %i\n", i, - dev->video_mode.alt_max_pkt_size[i]); - } - - /* compute alternate max packet sizes for vbi */ - uif = udev->actconfig->interface[dev->current_pcb_config. - hs_config_info[0].interface_info. - vanc_index + 1]; - - dev->vbi_mode.end_point_addr = - le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc. - bEndpointAddress); - - dev->vbi_mode.num_alt = uif->num_altsetting; - cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", - dev->vbi_mode.end_point_addr, - dev->vbi_mode.num_alt); - dev->vbi_mode.alt_max_pkt_size = - kmalloc(32 * dev->vbi_mode.num_alt, GFP_KERNEL); - - if (dev->vbi_mode.alt_max_pkt_size == NULL) { - cx231xx_errdev("out of memory!\n"); - clear_bit(dev->devno, &cx231xx_devused); - v4l2_device_unregister(&dev->v4l2_dev); - kfree(dev); - dev = NULL; - return -ENOMEM; - } - - for (i = 0; i < dev->vbi_mode.num_alt; i++) { - u16 tmp = - le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. - desc.wMaxPacketSize); - dev->vbi_mode.alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - cx231xx_info("Alternate setting %i, max size= %i\n", i, - dev->vbi_mode.alt_max_pkt_size[i]); - } - - /* compute alternate max packet sizes for sliced CC */ - uif = udev->actconfig->interface[dev->current_pcb_config. - hs_config_info[0].interface_info. - hanc_index + 1]; - - dev->sliced_cc_mode.end_point_addr = - le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc. - bEndpointAddress); - - dev->sliced_cc_mode.num_alt = uif->num_altsetting; - cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", - dev->sliced_cc_mode.end_point_addr, - dev->sliced_cc_mode.num_alt); - dev->sliced_cc_mode.alt_max_pkt_size = - kmalloc(32 * dev->sliced_cc_mode.num_alt, GFP_KERNEL); - - if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { - cx231xx_errdev("out of memory!\n"); - clear_bit(dev->devno, &cx231xx_devused); - v4l2_device_unregister(&dev->v4l2_dev); - kfree(dev); - dev = NULL; - return -ENOMEM; - } - - for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. - desc.wMaxPacketSize); - dev->sliced_cc_mode.alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - cx231xx_info("Alternate setting %i, max size= %i\n", i, - dev->sliced_cc_mode.alt_max_pkt_size[i]); - } - - if (dev->current_pcb_config.ts1_source != 0xff) { - /* compute alternate max packet sizes for TS1 */ - uif = udev->actconfig->interface[dev->current_pcb_config. - hs_config_info[0]. - interface_info. - ts1_index + 1]; - - dev->ts1_mode.end_point_addr = - le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe]. - desc.bEndpointAddress); - - dev->ts1_mode.num_alt = uif->num_altsetting; - cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", - dev->ts1_mode.end_point_addr, - dev->ts1_mode.num_alt); - dev->ts1_mode.alt_max_pkt_size = - kmalloc(32 * dev->ts1_mode.num_alt, GFP_KERNEL); - - if (dev->ts1_mode.alt_max_pkt_size == NULL) { - cx231xx_errdev("out of memory!\n"); - clear_bit(dev->devno, &cx231xx_devused); - v4l2_device_unregister(&dev->v4l2_dev); - kfree(dev); - dev = NULL; - return -ENOMEM; - } - - for (i = 0; i < dev->ts1_mode.num_alt; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i]. - endpoint[isoc_pipe].desc. - wMaxPacketSize); - dev->ts1_mode.alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - cx231xx_info("Alternate setting %i, max size= %i\n", i, - dev->ts1_mode.alt_max_pkt_size[i]); - } - } - - if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) { - cx231xx_enable_OSC(dev); - cx231xx_reset_out(dev); - cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3); - } - - if (dev->model == CX231XX_BOARD_CNXT_RDE_253S) - cx231xx_sleep_s5h1432(dev); - - /* load other modules required */ - request_modules(dev); - - return 0; -} - -/* - * cx231xx_usb_disconnect() - * called when the device gets diconencted - * video device will be unregistered on v4l2_close in case it is still open - */ -static void cx231xx_usb_disconnect(struct usb_interface *interface) -{ - struct cx231xx *dev; - - dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - if (!dev) - return; - - if (!dev->udev) - return; - - dev->state |= DEV_DISCONNECTED; - - flush_request_modules(dev); - - /* wait until all current v4l2 io is finished then deallocate - resources */ - mutex_lock(&dev->lock); - - wake_up_interruptible_all(&dev->open); - - if (dev->users) { - cx231xx_warn - ("device %s is open! Deregistration and memory " - "deallocation are deferred on close.\n", - video_device_node_name(dev->vdev)); - - /* Even having users, it is safe to remove the RC i2c driver */ - cx231xx_ir_exit(dev); - - if (dev->USE_ISO) - cx231xx_uninit_isoc(dev); - else - cx231xx_uninit_bulk(dev); - wake_up_interruptible(&dev->wait_frame); - wake_up_interruptible(&dev->wait_stream); - } else { - } - - cx231xx_close_extension(dev); - - mutex_unlock(&dev->lock); - - if (!dev->users) - cx231xx_release_resources(dev); -} - -static struct usb_driver cx231xx_usb_driver = { - .name = "cx231xx", - .probe = cx231xx_usb_probe, - .disconnect = cx231xx_usb_disconnect, - .id_table = cx231xx_id_table, -}; - -module_usb_driver(cx231xx_usb_driver); diff --git a/drivers/media/video/cx231xx/cx231xx-conf-reg.h b/drivers/media/video/cx231xx/cx231xx-conf-reg.h deleted file mode 100644 index 25593f212abf..000000000000 --- a/drivers/media/video/cx231xx/cx231xx-conf-reg.h +++ /dev/null @@ -1,495 +0,0 @@ -/* - cx231xx_conf-reg.h - driver for Conexant Cx23100/101/102 USB - video capture devices - - Copyright (C) 2008 <srinivasa.deevi at conexant dot com> - - 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. - */ - -#ifndef _POLARIS_REG_H_ -#define _POLARIS_REG_H_ - -#define BOARD_CFG_STAT 0x0 -#define TS_MODE_REG 0x4 -#define TS1_CFG_REG 0x8 -#define TS1_LENGTH_REG 0xc -#define TS2_CFG_REG 0x10 -#define TS2_LENGTH_REG 0x14 -#define EP_MODE_SET 0x18 -#define CIR_PWR_PTN1 0x1c -#define CIR_PWR_PTN2 0x20 -#define CIR_PWR_PTN3 0x24 -#define CIR_PWR_MASK0 0x28 -#define CIR_PWR_MASK1 0x2c -#define CIR_PWR_MASK2 0x30 -#define CIR_GAIN 0x34 -#define CIR_CAR_REG 0x38 -#define CIR_OT_CFG1 0x40 -#define CIR_OT_CFG2 0x44 -#define GBULK_BIT_EN 0x68 -#define PWR_CTL_EN 0x74 - -/* Polaris Endpoints capture mask for register EP_MODE_SET */ -#define ENABLE_EP1 0x01 /* Bit[0]=1 */ -#define ENABLE_EP2 0x02 /* Bit[1]=1 */ -#define ENABLE_EP3 0x04 /* Bit[2]=1 */ -#define ENABLE_EP4 0x08 /* Bit[3]=1 */ -#define ENABLE_EP5 0x10 /* Bit[4]=1 */ -#define ENABLE_EP6 0x20 /* Bit[5]=1 */ - -/* Bit definition for register PWR_CTL_EN */ -#define PWR_MODE_MASK 0x17f -#define PWR_AV_EN 0x08 /* bit3 */ -#define PWR_ISO_EN 0x40 /* bit6 */ -#define PWR_AV_MODE 0x30 /* bit4,5 */ -#define PWR_TUNER_EN 0x04 /* bit2 */ -#define PWR_DEMOD_EN 0x02 /* bit1 */ -#define I2C_DEMOD_EN 0x01 /* bit0 */ -#define PWR_RESETOUT_EN 0x100 /* bit8 */ - -enum AV_MODE{ - POLARIS_AVMODE_DEFAULT = 0, - POLARIS_AVMODE_DIGITAL = 0x10, - POLARIS_AVMODE_ANALOGT_TV = 0x20, - POLARIS_AVMODE_ENXTERNAL_AV = 0x30, - -}; - -/* Colibri Registers */ - -#define SINGLE_ENDED 0x0 -#define LOW_IF 0x4 -#define EU_IF 0x9 -#define US_IF 0xa - -#define SUP_BLK_TUNE1 0x00 -#define SUP_BLK_TUNE2 0x01 -#define SUP_BLK_TUNE3 0x02 -#define SUP_BLK_XTAL 0x03 -#define SUP_BLK_PLL1 0x04 -#define SUP_BLK_PLL2 0x05 -#define SUP_BLK_PLL3 0x06 -#define SUP_BLK_REF 0x07 -#define SUP_BLK_PWRDN 0x08 -#define SUP_BLK_TESTPAD 0x09 -#define ADC_COM_INT5_STAB_REF 0x0a -#define ADC_COM_QUANT 0x0b -#define ADC_COM_BIAS1 0x0c -#define ADC_COM_BIAS2 0x0d -#define ADC_COM_BIAS3 0x0e -#define TESTBUS_CTRL 0x12 - -#define FLD_PWRDN_TUNING_BIAS 0x10 -#define FLD_PWRDN_ENABLE_PLL 0x08 -#define FLD_PWRDN_PD_BANDGAP 0x04 -#define FLD_PWRDN_PD_BIAS 0x02 -#define FLD_PWRDN_PD_TUNECK 0x01 - - -#define ADC_STATUS_CH1 0x20 -#define ADC_STATUS_CH2 0x40 -#define ADC_STATUS_CH3 0x60 - -#define ADC_STATUS2_CH1 0x21 -#define ADC_STATUS2_CH2 0x41 -#define ADC_STATUS2_CH3 0x61 - -#define ADC_CAL_ATEST_CH1 0x22 -#define ADC_CAL_ATEST_CH2 0x42 -#define ADC_CAL_ATEST_CH3 0x62 - -#define ADC_PWRDN_CLAMP_CH1 0x23 -#define ADC_PWRDN_CLAMP_CH2 0x43 -#define ADC_PWRDN_CLAMP_CH3 0x63 - -#define ADC_CTRL_DAC23_CH1 0x24 -#define ADC_CTRL_DAC23_CH2 0x44 -#define ADC_CTRL_DAC23_CH3 0x64 - -#define ADC_CTRL_DAC1_CH1 0x25 -#define ADC_CTRL_DAC1_CH2 0x45 -#define ADC_CTRL_DAC1_CH3 0x65 - -#define ADC_DCSERVO_DEM_CH1 0x26 -#define ADC_DCSERVO_DEM_CH2 0x46 -#define ADC_DCSERVO_DEM_CH3 0x66 - -#define ADC_FB_FRCRST_CH1 0x27 -#define ADC_FB_FRCRST_CH2 0x47 -#define ADC_FB_FRCRST_CH3 0x67 - -#define ADC_INPUT_CH1 0x28 -#define ADC_INPUT_CH2 0x48 -#define ADC_INPUT_CH3 0x68 -#define INPUT_SEL_MASK 0x30 /* [5:4] in_sel */ - -#define ADC_NTF_PRECLMP_EN_CH1 0x29 -#define ADC_NTF_PRECLMP_EN_CH2 0x49 -#define ADC_NTF_PRECLMP_EN_CH3 0x69 - -#define ADC_QGAIN_RES_TRM_CH1 0x2a -#define ADC_QGAIN_RES_TRM_CH2 0x4a -#define ADC_QGAIN_RES_TRM_CH3 0x6a - -#define ADC_SOC_PRECLMP_TERM_CH1 0x2b -#define ADC_SOC_PRECLMP_TERM_CH2 0x4b -#define ADC_SOC_PRECLMP_TERM_CH3 0x6b - -#define TESTBUS_CTRL_CH1 0x32 -#define TESTBUS_CTRL_CH2 0x52 -#define TESTBUS_CTRL_CH3 0x72 - -/****************************************************************************** - * DIF registers * - ******************************************************************************/ -#define DIRECT_IF_REVB_BASE 0x00300 - -/*****************************************************************************/ -#define DIF_PLL_FREQ_WORD (DIRECT_IF_REVB_BASE + 0x00000000) -/*****************************************************************************/ -#define FLD_DIF_PLL_LOCK 0x80000000 -/* Reserved [30:29] */ -#define FLD_DIF_PLL_FREE_RUN 0x10000000 -#define FLD_DIF_PLL_FREQ 0x0fffffff - -/*****************************************************************************/ -#define DIF_PLL_CTRL (DIRECT_IF_REVB_BASE + 0x00000004) -/*****************************************************************************/ -#define FLD_DIF_KD_PD 0xff000000 -/* Reserved [23:20] */ -#define FLD_DIF_KDS_PD 0x000f0000 -#define FLD_DIF_KI_PD 0x0000ff00 -/* Reserved [7:4] */ -#define FLD_DIF_KIS_PD 0x0000000f - -/*****************************************************************************/ -#define DIF_PLL_CTRL1 (DIRECT_IF_REVB_BASE + 0x00000008) -/*****************************************************************************/ -#define FLD_DIF_KD_FD 0xff000000 -/* Reserved [23:20] */ -#define FLD_DIF_KDS_FD 0x000f0000 -#define FLD_DIF_KI_FD 0x0000ff00 -#define FLD_DIF_SIG_PROP_SZ 0x000000f0 -#define FLD_DIF_KIS_FD 0x0000000f - -/*****************************************************************************/ -#define DIF_PLL_CTRL2 (DIRECT_IF_REVB_BASE + 0x0000000c) -/*****************************************************************************/ -#define FLD_DIF_PLL_AGC_REF 0xfff00000 -#define FLD_DIF_PLL_AGC_KI 0x000f0000 -/* Reserved [15] */ -#define FLD_DIF_FREQ_LIMIT 0x00007000 -#define FLD_DIF_K_FD 0x00000f00 -#define FLD_DIF_DOWNSMPL_FD 0x000000ff - -/*****************************************************************************/ -#define DIF_PLL_CTRL3 (DIRECT_IF_REVB_BASE + 0x00000010) -/*****************************************************************************/ -/* Reserved [31:16] */ -#define FLD_DIF_PLL_AGC_EN 0x00008000 -/* Reserved [14:12] */ -#define FLD_DIF_PLL_MAN_GAIN 0x00000fff - -/*****************************************************************************/ -#define DIF_AGC_IF_REF (DIRECT_IF_REVB_BASE + 0x00000014) -/*****************************************************************************/ -#define FLD_DIF_K_AGC_RF 0xf0000000 -#define FLD_DIF_K_AGC_IF 0x0f000000 -#define FLD_DIF_K_AGC_INT 0x00f00000 -/* Reserved [19:12] */ -#define FLD_DIF_IF_REF 0x00000fff - -/*****************************************************************************/ -#define DIF_AGC_CTRL_IF (DIRECT_IF_REVB_BASE + 0x00000018) -/*****************************************************************************/ -#define FLD_DIF_IF_MAX 0xff000000 -#define FLD_DIF_IF_MIN 0x00ff0000 -#define FLD_DIF_IF_AGC 0x0000ffff - -/*****************************************************************************/ -#define DIF_AGC_CTRL_INT (DIRECT_IF_REVB_BASE + 0x0000001c) -/*****************************************************************************/ -#define FLD_DIF_INT_MAX 0xff000000 -#define FLD_DIF_INT_MIN 0x00ff0000 -#define FLD_DIF_INT_AGC 0x0000ffff - -/*****************************************************************************/ -#define DIF_AGC_CTRL_RF (DIRECT_IF_REVB_BASE + 0x00000020) -/*****************************************************************************/ -#define FLD_DIF_RF_MAX 0xff000000 -#define FLD_DIF_RF_MIN 0x00ff0000 -#define FLD_DIF_RF_AGC 0x0000ffff - -/*****************************************************************************/ -#define DIF_AGC_IF_INT_CURRENT (DIRECT_IF_REVB_BASE + 0x00000024) -/*****************************************************************************/ -#define FLD_DIF_IF_AGC_IN 0xffff0000 -#define FLD_DIF_INT_AGC_IN 0x0000ffff - -/*****************************************************************************/ -#define DIF_AGC_RF_CURRENT (DIRECT_IF_REVB_BASE + 0x00000028) -/*****************************************************************************/ -/* Reserved [31:16] */ -#define FLD_DIF_RF_AGC_IN 0x0000ffff - -/*****************************************************************************/ -#define DIF_VIDEO_AGC_CTRL (DIRECT_IF_REVB_BASE + 0x0000002c) -/*****************************************************************************/ -#define FLD_DIF_AFD 0xc0000000 -#define FLD_DIF_K_VID_AGC 0x30000000 -#define FLD_DIF_LINE_LENGTH 0x0fff0000 -#define FLD_DIF_AGC_GAIN 0x0000ffff - -/*****************************************************************************/ -#define DIF_VID_AUD_OVERRIDE (DIRECT_IF_REVB_BASE + 0x00000030) -/*****************************************************************************/ -#define FLD_DIF_AUDIO_AGC_OVERRIDE 0x80000000 -/* Reserved [30:30] */ -#define FLD_DIF_AUDIO_MAN_GAIN 0x3f000000 -/* Reserved [23:17] */ -#define FLD_DIF_VID_AGC_OVERRIDE 0x00010000 -#define FLD_DIF_VID_MAN_GAIN 0x0000ffff - -/*****************************************************************************/ -#define DIF_AV_SEP_CTRL (DIRECT_IF_REVB_BASE + 0x00000034) -/*****************************************************************************/ -#define FLD_DIF_LPF_FREQ 0xc0000000 -#define FLD_DIF_AV_PHASE_INC 0x3f000000 -#define FLD_DIF_AUDIO_FREQ 0x00ffffff - -/*****************************************************************************/ -#define DIF_COMP_FLT_CTRL (DIRECT_IF_REVB_BASE + 0x00000038) -/*****************************************************************************/ -/* Reserved [31:24] */ -#define FLD_DIF_IIR23_R2 0x00ff0000 -#define FLD_DIF_IIR23_R1 0x0000ff00 -#define FLD_DIF_IIR1_R1 0x000000ff - -/*****************************************************************************/ -#define DIF_MISC_CTRL (DIRECT_IF_REVB_BASE + 0x0000003c) -/*****************************************************************************/ -#define FLD_DIF_DIF_BYPASS 0x80000000 -#define FLD_DIF_FM_NYQ_GAIN 0x40000000 -#define FLD_DIF_RF_AGC_ENA 0x20000000 -#define FLD_DIF_INT_AGC_ENA 0x10000000 -#define FLD_DIF_IF_AGC_ENA 0x08000000 -#define FLD_DIF_FORCE_RF_IF_LOCK 0x04000000 -#define FLD_DIF_VIDEO_AGC_ENA 0x02000000 -#define FLD_DIF_RF_AGC_INV 0x01000000 -#define FLD_DIF_INT_AGC_INV 0x00800000 -#define FLD_DIF_IF_AGC_INV 0x00400000 -#define FLD_DIF_SPEC_INV 0x00200000 -#define FLD_DIF_AUD_FULL_BW 0x00100000 -#define FLD_DIF_AUD_SRC_SEL 0x00080000 -/* Reserved [18] */ -#define FLD_DIF_IF_FREQ 0x00030000 -/* Reserved [15:14] */ -#define FLD_DIF_TIP_OFFSET 0x00003f00 -/* Reserved [7:5] */ -#define FLD_DIF_DITHER_ENA 0x00000010 -/* Reserved [3:1] */ -#define FLD_DIF_RF_IF_LOCK 0x00000001 - -/*****************************************************************************/ -#define DIF_SRC_PHASE_INC (DIRECT_IF_REVB_BASE + 0x00000040) -/*****************************************************************************/ -/* Reserved [31:29] */ -#define FLD_DIF_PHASE_INC 0x1fffffff - -/*****************************************************************************/ -#define DIF_SRC_GAIN_CONTROL (DIRECT_IF_REVB_BASE + 0x00000044) -/*****************************************************************************/ -/* Reserved [31:16] */ -#define FLD_DIF_SRC_KI 0x0000ff00 -#define FLD_DIF_SRC_KD 0x000000ff - -/*****************************************************************************/ -#define DIF_BPF_COEFF01 (DIRECT_IF_REVB_BASE + 0x00000048) -/*****************************************************************************/ -/* Reserved [31:19] */ -#define FLD_DIF_BPF_COEFF_0 0x00070000 -/* Reserved [15:4] */ -#define FLD_DIF_BPF_COEFF_1 0x0000000f - -/*****************************************************************************/ -#define DIF_BPF_COEFF23 (DIRECT_IF_REVB_BASE + 0x0000004c) -/*****************************************************************************/ -/* Reserved [31:22] */ -#define FLD_DIF_BPF_COEFF_2 0x003f0000 -/* Reserved [15:7] */ -#define FLD_DIF_BPF_COEFF_3 0x0000007f - -/*****************************************************************************/ -#define DIF_BPF_COEFF45 (DIRECT_IF_REVB_BASE + 0x00000050) -/*****************************************************************************/ -/* Reserved [31:24] */ -#define FLD_DIF_BPF_COEFF_4 0x00ff0000 -/* Reserved [15:8] */ -#define FLD_DIF_BPF_COEFF_5 0x000000ff - -/*****************************************************************************/ -#define DIF_BPF_COEFF67 (DIRECT_IF_REVB_BASE + 0x00000054) -/*****************************************************************************/ -/* Reserved [31:25] */ -#define FLD_DIF_BPF_COEFF_6 0x01ff0000 -/* Reserved [15:9] */ -#define FLD_DIF_BPF_COEFF_7 0x000001ff - -/*****************************************************************************/ -#define DIF_BPF_COEFF89 (DIRECT_IF_REVB_BASE + 0x00000058) -/*****************************************************************************/ -/* Reserved [31:26] */ -#define FLD_DIF_BPF_COEFF_8 0x03ff0000 -/* Reserved [15:10] */ -#define FLD_DIF_BPF_COEFF_9 0x000003ff - -/*****************************************************************************/ -#define DIF_BPF_COEFF1011 (DIRECT_IF_REVB_BASE + 0x0000005c) -/*****************************************************************************/ -/* Reserved [31:27] */ -#define FLD_DIF_BPF_COEFF_10 0x07ff0000 -/* Reserved [15:11] */ -#define FLD_DIF_BPF_COEFF_11 0x000007ff - -/*****************************************************************************/ -#define DIF_BPF_COEFF1213 (DIRECT_IF_REVB_BASE + 0x00000060) -/*****************************************************************************/ -/* Reserved [31:27] */ -#define FLD_DIF_BPF_COEFF_12 0x07ff0000 -/* Reserved [15:12] */ -#define FLD_DIF_BPF_COEFF_13 0x00000fff - -/*****************************************************************************/ -#define DIF_BPF_COEFF1415 (DIRECT_IF_REVB_BASE + 0x00000064) -/*****************************************************************************/ -/* Reserved [31:28] */ -#define FLD_DIF_BPF_COEFF_14 0x0fff0000 -/* Reserved [15:12] */ -#define FLD_DIF_BPF_COEFF_15 0x00000fff - -/*****************************************************************************/ -#define DIF_BPF_COEFF1617 (DIRECT_IF_REVB_BASE + 0x00000068) -/*****************************************************************************/ -/* Reserved [31:29] */ -#define FLD_DIF_BPF_COEFF_16 0x1fff0000 -/* Reserved [15:13] */ -#define FLD_DIF_BPF_COEFF_17 0x00001fff - -/*****************************************************************************/ -#define DIF_BPF_COEFF1819 (DIRECT_IF_REVB_BASE + 0x0000006c) -/*****************************************************************************/ -/* Reserved [31:29] */ -#define FLD_DIF_BPF_COEFF_18 0x1fff0000 -/* Reserved [15:13] */ -#define FLD_DIF_BPF_COEFF_19 0x00001fff - -/*****************************************************************************/ -#define DIF_BPF_COEFF2021 (DIRECT_IF_REVB_BASE + 0x00000070) -/*****************************************************************************/ -/* Reserved [31:29] */ -#define FLD_DIF_BPF_COEFF_20 0x1fff0000 -/* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_21 0x00003fff - -/*****************************************************************************/ -#define DIF_BPF_COEFF2223 (DIRECT_IF_REVB_BASE + 0x00000074) -/*****************************************************************************/ -/* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_22 0x3fff0000 -/* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_23 0x00003fff - -/*****************************************************************************/ -#define DIF_BPF_COEFF2425 (DIRECT_IF_REVB_BASE + 0x00000078) -/*****************************************************************************/ -/* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_24 0x3fff0000 -/* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_25 0x00003fff - -/*****************************************************************************/ -#define DIF_BPF_COEFF2627 (DIRECT_IF_REVB_BASE + 0x0000007c) -/*****************************************************************************/ -/* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_26 0x3fff0000 -/* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_27 0x00003fff - -/*****************************************************************************/ -#define DIF_BPF_COEFF2829 (DIRECT_IF_REVB_BASE + 0x00000080) -/*****************************************************************************/ -/* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_28 0x3fff0000 -/* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_29 0x00003fff - -/*****************************************************************************/ -#define DIF_BPF_COEFF3031 (DIRECT_IF_REVB_BASE + 0x00000084) -/*****************************************************************************/ -/* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_30 0x3fff0000 -/* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_31 0x00003fff - -/*****************************************************************************/ -#define DIF_BPF_COEFF3233 (DIRECT_IF_REVB_BASE + 0x00000088) -/*****************************************************************************/ -/* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_32 0x3fff0000 -/* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_33 0x00003fff - -/*****************************************************************************/ -#define DIF_BPF_COEFF3435 (DIRECT_IF_REVB_BASE + 0x0000008c) -/*****************************************************************************/ -/* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_34 0x3fff0000 -/* Reserved [15:14] */ -#define FLD_DIF_BPF_COEFF_35 0x00003fff - -/*****************************************************************************/ -#define DIF_BPF_COEFF36 (DIRECT_IF_REVB_BASE + 0x00000090) -/*****************************************************************************/ -/* Reserved [31:30] */ -#define FLD_DIF_BPF_COEFF_36 0x3fff0000 -/* Reserved [15:0] */ - -/*****************************************************************************/ -#define DIF_RPT_VARIANCE (DIRECT_IF_REVB_BASE + 0x00000094) -/*****************************************************************************/ -/* Reserved [31:20] */ -#define FLD_DIF_RPT_VARIANCE 0x000fffff - -/*****************************************************************************/ -#define DIF_SOFT_RST_CTRL_REVB (DIRECT_IF_REVB_BASE + 0x00000098) -/*****************************************************************************/ -/* Reserved [31:8] */ -#define FLD_DIF_DIF_SOFT_RST 0x00000080 -#define FLD_DIF_DIF_REG_RST_MSK 0x00000040 -#define FLD_DIF_AGC_RST_MSK 0x00000020 -#define FLD_DIF_CMP_RST_MSK 0x00000010 -#define FLD_DIF_AVS_RST_MSK 0x00000008 -#define FLD_DIF_NYQ_RST_MSK 0x00000004 -#define FLD_DIF_DIF_SRC_RST_MSK 0x00000002 -#define FLD_DIF_PLL_RST_MSK 0x00000001 - -/*****************************************************************************/ -#define DIF_PLL_FREQ_ERR (DIRECT_IF_REVB_BASE + 0x0000009c) -/*****************************************************************************/ -/* Reserved [31:25] */ -#define FLD_DIF_CTL_IP 0x01ffffff - -#endif diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c deleted file mode 100644 index 05358d486135..000000000000 --- a/drivers/media/video/cx231xx/cx231xx-core.c +++ /dev/null @@ -1,1736 +0,0 @@ -/* - cx231xx-core.c - driver for Conexant Cx23100/101/102 - USB video capture devices - - Copyright (C) 2008 <srinivasa.deevi at conexant dot com> - Based on em28xx driver - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/init.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/vmalloc.h> -#include <media/v4l2-common.h> -#include <media/tuner.h> - -#include "cx231xx.h" -#include "cx231xx-reg.h" - -/* #define ENABLE_DEBUG_ISOC_FRAMES */ - -static unsigned int core_debug; -module_param(core_debug, int, 0644); -MODULE_PARM_DESC(core_debug, "enable debug messages [core]"); - -#define cx231xx_coredbg(fmt, arg...) do {\ - if (core_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __func__ , ##arg); } while (0) - -static unsigned int reg_debug; -module_param(reg_debug, int, 0644); -MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]"); - -static int alt = CX231XX_PINOUT; -module_param(alt, int, 0644); -MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); - -#define cx231xx_isocdbg(fmt, arg...) do {\ - if (core_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __func__ , ##arg); } while (0) - -/***************************************************************** -* Device control list functions * -******************************************************************/ - -LIST_HEAD(cx231xx_devlist); -static DEFINE_MUTEX(cx231xx_devlist_mutex); - -/* - * cx231xx_realease_resources() - * unregisters the v4l2,i2c and usb devices - * called when the device gets disconected or at module unload -*/ -void cx231xx_remove_from_devlist(struct cx231xx *dev) -{ - if (dev == NULL) - return; - if (dev->udev == NULL) - return; - - if (atomic_read(&dev->devlist_count) > 0) { - mutex_lock(&cx231xx_devlist_mutex); - list_del(&dev->devlist); - atomic_dec(&dev->devlist_count); - mutex_unlock(&cx231xx_devlist_mutex); - } -}; - -void cx231xx_add_into_devlist(struct cx231xx *dev) -{ - mutex_lock(&cx231xx_devlist_mutex); - list_add_tail(&dev->devlist, &cx231xx_devlist); - atomic_inc(&dev->devlist_count); - mutex_unlock(&cx231xx_devlist_mutex); -}; - -static LIST_HEAD(cx231xx_extension_devlist); - -int cx231xx_register_extension(struct cx231xx_ops *ops) -{ - struct cx231xx *dev = NULL; - - mutex_lock(&cx231xx_devlist_mutex); - list_add_tail(&ops->next, &cx231xx_extension_devlist); - list_for_each_entry(dev, &cx231xx_devlist, devlist) - ops->init(dev); - - printk(KERN_INFO DRIVER_NAME ": %s initialized\n", ops->name); - mutex_unlock(&cx231xx_devlist_mutex); - return 0; -} -EXPORT_SYMBOL(cx231xx_register_extension); - -void cx231xx_unregister_extension(struct cx231xx_ops *ops) -{ - struct cx231xx *dev = NULL; - - mutex_lock(&cx231xx_devlist_mutex); - list_for_each_entry(dev, &cx231xx_devlist, devlist) - ops->fini(dev); - - - printk(KERN_INFO DRIVER_NAME ": %s removed\n", ops->name); - list_del(&ops->next); - mutex_unlock(&cx231xx_devlist_mutex); -} -EXPORT_SYMBOL(cx231xx_unregister_extension); - -void cx231xx_init_extension(struct cx231xx *dev) -{ - struct cx231xx_ops *ops = NULL; - - mutex_lock(&cx231xx_devlist_mutex); - if (!list_empty(&cx231xx_extension_devlist)) { - list_for_each_entry(ops, &cx231xx_extension_devlist, next) { - if (ops->init) - ops->init(dev); - } - } - mutex_unlock(&cx231xx_devlist_mutex); -} - -void cx231xx_close_extension(struct cx231xx *dev) -{ - struct cx231xx_ops *ops = NULL; - - mutex_lock(&cx231xx_devlist_mutex); - if (!list_empty(&cx231xx_extension_devlist)) { - list_for_each_entry(ops, &cx231xx_extension_devlist, next) { - if (ops->fini) - ops->fini(dev); - } - } - mutex_unlock(&cx231xx_devlist_mutex); -} - -/**************************************************************** -* U S B related functions * -*****************************************************************/ -int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, - struct cx231xx_i2c_xfer_data *req_data) -{ - int status = 0; - struct cx231xx *dev = i2c_bus->dev; - struct VENDOR_REQUEST_IN ven_req; - - u8 saddr_len = 0; - u8 _i2c_period = 0; - u8 _i2c_nostop = 0; - u8 _i2c_reserve = 0; - - if (dev->state & DEV_DISCONNECTED) - return -ENODEV; - - /* Get the I2C period, nostop and reserve parameters */ - _i2c_period = i2c_bus->i2c_period; - _i2c_nostop = i2c_bus->i2c_nostop; - _i2c_reserve = i2c_bus->i2c_reserve; - - saddr_len = req_data->saddr_len; - - /* Set wValue */ - if (saddr_len == 1) /* need check saddr_len == 0 */ - ven_req.wValue = - req_data-> - dev_addr << 9 | _i2c_period << 4 | saddr_len << 2 | - _i2c_nostop << 1 | I2C_SYNC | _i2c_reserve << 6; - else - ven_req.wValue = - req_data-> - dev_addr << 9 | _i2c_period << 4 | saddr_len << 2 | - _i2c_nostop << 1 | I2C_SYNC | _i2c_reserve << 6; - - /* set channel number */ - if (req_data->direction & I2C_M_RD) { - /* channel number, for read,spec required channel_num +4 */ - ven_req.bRequest = i2c_bus->nr + 4; - } else - ven_req.bRequest = i2c_bus->nr; /* channel number, */ - - /* set index value */ - switch (saddr_len) { - case 0: - ven_req.wIndex = 0; /* need check */ - break; - case 1: - ven_req.wIndex = (req_data->saddr_dat & 0xff); - break; - case 2: - ven_req.wIndex = req_data->saddr_dat; - break; - } - - /* set wLength value */ - ven_req.wLength = req_data->buf_size; - - /* set bData value */ - ven_req.bData = 0; - - /* set the direction */ - if (req_data->direction) { - ven_req.direction = USB_DIR_IN; - memset(req_data->p_buffer, 0x00, ven_req.wLength); - } else - ven_req.direction = USB_DIR_OUT; - - /* set the buffer for read / write */ - ven_req.pBuff = req_data->p_buffer; - - - /* call common vendor command request */ - status = cx231xx_send_vendor_cmd(dev, &ven_req); - if (status < 0) { - cx231xx_info - ("UsbInterface::sendCommand, failed with status -%d\n", - status); - } - - return status; -} -EXPORT_SYMBOL_GPL(cx231xx_send_usb_command); - -/* - * Sends/Receives URB control messages, assuring to use a kalloced buffer - * for all operations (dev->urb_buf), to avoid using stacked buffers, as - * they aren't safe for usage with USB, due to DMA restrictions. - * Also implements the debug code for control URB's. - */ -static int __usb_control_msg(struct cx231xx *dev, unsigned int pipe, - __u8 request, __u8 requesttype, __u16 value, __u16 index, - void *data, __u16 size, int timeout) -{ - int rc, i; - - if (reg_debug) { - printk(KERN_DEBUG "%s: (pipe 0x%08x): " - "%s: %02x %02x %02x %02x %02x %02x %02x %02x ", - dev->name, - pipe, - (requesttype & USB_DIR_IN) ? "IN" : "OUT", - requesttype, - request, - value & 0xff, value >> 8, - index & 0xff, index >> 8, - size & 0xff, size >> 8); - if (!(requesttype & USB_DIR_IN)) { - printk(KERN_CONT ">>>"); - for (i = 0; i < size; i++) - printk(KERN_CONT " %02x", - ((unsigned char *)data)[i]); - } - } - - /* Do the real call to usb_control_msg */ - mutex_lock(&dev->ctrl_urb_lock); - if (!(requesttype & USB_DIR_IN) && size) - memcpy(dev->urb_buf, data, size); - rc = usb_control_msg(dev->udev, pipe, request, requesttype, value, - index, dev->urb_buf, size, timeout); - if ((requesttype & USB_DIR_IN) && size) - memcpy(data, dev->urb_buf, size); - mutex_unlock(&dev->ctrl_urb_lock); - - if (reg_debug) { - if (unlikely(rc < 0)) { - printk(KERN_CONT "FAILED!\n"); - return rc; - } - - if ((requesttype & USB_DIR_IN)) { - printk(KERN_CONT "<<<"); - for (i = 0; i < size; i++) - printk(KERN_CONT " %02x", - ((unsigned char *)data)[i]); - } - printk(KERN_CONT "\n"); - } - - return rc; -} - - -/* - * cx231xx_read_ctrl_reg() - * reads data from the usb device specifying bRequest and wValue - */ -int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, - char *buf, int len) -{ - u8 val = 0; - int ret; - int pipe = usb_rcvctrlpipe(dev->udev, 0); - - if (dev->state & DEV_DISCONNECTED) - return -ENODEV; - - if (len > URB_MAX_CTRL_SIZE) - return -EINVAL; - - switch (len) { - case 1: - val = ENABLE_ONE_BYTE; - break; - case 2: - val = ENABLE_TWE_BYTE; - break; - case 3: - val = ENABLE_THREE_BYTE; - break; - case 4: - val = ENABLE_FOUR_BYTE; - break; - default: - val = 0xFF; /* invalid option */ - } - - if (val == 0xFF) - return -EINVAL; - - ret = __usb_control_msg(dev, pipe, req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - val, reg, buf, len, HZ); - return ret; -} - -int cx231xx_send_vendor_cmd(struct cx231xx *dev, - struct VENDOR_REQUEST_IN *ven_req) -{ - int ret; - int pipe = 0; - int unsend_size = 0; - u8 *pdata; - - if (dev->state & DEV_DISCONNECTED) - return -ENODEV; - - if ((ven_req->wLength > URB_MAX_CTRL_SIZE)) - return -EINVAL; - - if (ven_req->direction) - pipe = usb_rcvctrlpipe(dev->udev, 0); - else - pipe = usb_sndctrlpipe(dev->udev, 0); - - /* - * If the cx23102 read more than 4 bytes with i2c bus, - * need chop to 4 byte per request - */ - if ((ven_req->wLength > 4) && ((ven_req->bRequest == 0x4) || - (ven_req->bRequest == 0x5) || - (ven_req->bRequest == 0x6))) { - unsend_size = 0; - pdata = ven_req->pBuff; - - - unsend_size = ven_req->wLength; - - /* the first package */ - ven_req->wValue = ven_req->wValue & 0xFFFB; - ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x2; - ret = __usb_control_msg(dev, pipe, ven_req->bRequest, - ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - ven_req->wValue, ven_req->wIndex, pdata, - 0x0004, HZ); - unsend_size = unsend_size - 4; - - /* the middle package */ - ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x42; - while (unsend_size - 4 > 0) { - pdata = pdata + 4; - ret = __usb_control_msg(dev, pipe, - ven_req->bRequest, - ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - ven_req->wValue, ven_req->wIndex, pdata, - 0x0004, HZ); - unsend_size = unsend_size - 4; - } - - /* the last package */ - ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x40; - pdata = pdata + 4; - ret = __usb_control_msg(dev, pipe, ven_req->bRequest, - ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - ven_req->wValue, ven_req->wIndex, pdata, - unsend_size, HZ); - } else { - ret = __usb_control_msg(dev, pipe, ven_req->bRequest, - ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - ven_req->wValue, ven_req->wIndex, - ven_req->pBuff, ven_req->wLength, HZ); - } - - return ret; -} - -/* - * cx231xx_write_ctrl_reg() - * sends data to the usb device, specifying bRequest - */ -int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf, - int len) -{ - u8 val = 0; - int ret; - int pipe = usb_sndctrlpipe(dev->udev, 0); - - if (dev->state & DEV_DISCONNECTED) - return -ENODEV; - - if ((len < 1) || (len > URB_MAX_CTRL_SIZE)) - return -EINVAL; - - switch (len) { - case 1: - val = ENABLE_ONE_BYTE; - break; - case 2: - val = ENABLE_TWE_BYTE; - break; - case 3: - val = ENABLE_THREE_BYTE; - break; - case 4: - val = ENABLE_FOUR_BYTE; - break; - default: - val = 0xFF; /* invalid option */ - } - - if (val == 0xFF) - return -EINVAL; - - if (reg_debug) { - int byte; - - cx231xx_isocdbg("(pipe 0x%08x): " - "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>", - pipe, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - req, 0, val, reg & 0xff, - reg >> 8, len & 0xff, len >> 8); - - for (byte = 0; byte < len; byte++) - cx231xx_isocdbg(" %02x", (unsigned char)buf[byte]); - cx231xx_isocdbg("\n"); - } - - ret = __usb_control_msg(dev, pipe, req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - val, reg, buf, len, HZ); - - return ret; -} - -/**************************************************************** -* USB Alternate Setting functions * -*****************************************************************/ - -int cx231xx_set_video_alternate(struct cx231xx *dev) -{ - int errCode, prev_alt = dev->video_mode.alt; - unsigned int min_pkt_size = dev->width * 2 + 4; - u32 usb_interface_index = 0; - - /* When image size is bigger than a certain value, - the frame size should be increased, otherwise, only - green screen will be received. - */ - if (dev->width * 2 * dev->height > 720 * 240 * 2) - min_pkt_size *= 2; - - if (dev->width > 360) { - /* resolutions: 720,704,640 */ - dev->video_mode.alt = 3; - } else if (dev->width > 180) { - /* resolutions: 360,352,320,240 */ - dev->video_mode.alt = 2; - } else if (dev->width > 0) { - /* resolutions: 180,176,160,128,88 */ - dev->video_mode.alt = 1; - } else { - /* Change to alt0 BULK to release USB bandwidth */ - dev->video_mode.alt = 0; - } - - if (dev->USE_ISO == 0) - dev->video_mode.alt = 0; - - cx231xx_coredbg("dev->video_mode.alt= %d\n", dev->video_mode.alt); - - /* Get the correct video interface Index */ - usb_interface_index = - dev->current_pcb_config.hs_config_info[0].interface_info. - video_index + 1; - - if (dev->video_mode.alt != prev_alt) { - cx231xx_coredbg("minimum isoc packet size: %u (alt=%d)\n", - min_pkt_size, dev->video_mode.alt); - - if (dev->video_mode.alt_max_pkt_size != NULL) - dev->video_mode.max_pkt_size = - dev->video_mode.alt_max_pkt_size[dev->video_mode.alt]; - cx231xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n", - dev->video_mode.alt, - dev->video_mode.max_pkt_size); - errCode = - usb_set_interface(dev->udev, usb_interface_index, - dev->video_mode.alt); - if (errCode < 0) { - cx231xx_errdev - ("cannot change alt number to %d (error=%i)\n", - dev->video_mode.alt, errCode); - return errCode; - } - } - return 0; -} - -int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt) -{ - int status = 0; - u32 usb_interface_index = 0; - u32 max_pkt_size = 0; - - switch (index) { - case INDEX_TS1: - usb_interface_index = - dev->current_pcb_config.hs_config_info[0].interface_info. - ts1_index + 1; - dev->ts1_mode.alt = alt; - if (dev->ts1_mode.alt_max_pkt_size != NULL) - max_pkt_size = dev->ts1_mode.max_pkt_size = - dev->ts1_mode.alt_max_pkt_size[dev->ts1_mode.alt]; - break; - case INDEX_TS2: - usb_interface_index = - dev->current_pcb_config.hs_config_info[0].interface_info. - ts2_index + 1; - break; - case INDEX_AUDIO: - usb_interface_index = - dev->current_pcb_config.hs_config_info[0].interface_info. - audio_index + 1; - dev->adev.alt = alt; - if (dev->adev.alt_max_pkt_size != NULL) - max_pkt_size = dev->adev.max_pkt_size = - dev->adev.alt_max_pkt_size[dev->adev.alt]; - break; - case INDEX_VIDEO: - usb_interface_index = - dev->current_pcb_config.hs_config_info[0].interface_info. - video_index + 1; - dev->video_mode.alt = alt; - if (dev->video_mode.alt_max_pkt_size != NULL) - max_pkt_size = dev->video_mode.max_pkt_size = - dev->video_mode.alt_max_pkt_size[dev->video_mode. - alt]; - break; - case INDEX_VANC: - if (dev->board.no_alt_vanc) - return 0; - usb_interface_index = - dev->current_pcb_config.hs_config_info[0].interface_info. - vanc_index + 1; - dev->vbi_mode.alt = alt; - if (dev->vbi_mode.alt_max_pkt_size != NULL) - max_pkt_size = dev->vbi_mode.max_pkt_size = - dev->vbi_mode.alt_max_pkt_size[dev->vbi_mode.alt]; - break; - case INDEX_HANC: - usb_interface_index = - dev->current_pcb_config.hs_config_info[0].interface_info. - hanc_index + 1; - dev->sliced_cc_mode.alt = alt; - if (dev->sliced_cc_mode.alt_max_pkt_size != NULL) - max_pkt_size = dev->sliced_cc_mode.max_pkt_size = - dev->sliced_cc_mode.alt_max_pkt_size[dev-> - sliced_cc_mode. - alt]; - break; - default: - break; - } - - if (alt > 0 && max_pkt_size == 0) { - cx231xx_errdev - ("can't change interface %d alt no. to %d: Max. Pkt size = 0\n", - usb_interface_index, alt); - /*To workaround error number=-71 on EP0 for videograbber, - need add following codes.*/ - if (dev->board.no_alt_vanc) - return -1; - } - - cx231xx_coredbg("setting alternate %d with wMaxPacketSize=%u," - "Interface = %d\n", alt, max_pkt_size, - usb_interface_index); - - if (usb_interface_index > 0) { - status = usb_set_interface(dev->udev, usb_interface_index, alt); - if (status < 0) { - cx231xx_errdev - ("can't change interface %d alt no. to %d (err=%i)\n", - usb_interface_index, alt, status); - return status; - } - } - - return status; -} -EXPORT_SYMBOL_GPL(cx231xx_set_alt_setting); - -int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio) -{ - int rc = 0; - - if (!gpio) - return rc; - - /* Send GPIO reset sequences specified at board entry */ - while (gpio->sleep >= 0) { - rc = cx231xx_set_gpio_value(dev, gpio->bit, gpio->val); - if (rc < 0) - return rc; - - if (gpio->sleep > 0) - msleep(gpio->sleep); - - gpio++; - } - return rc; -} - -int cx231xx_demod_reset(struct cx231xx *dev) -{ - - u8 status = 0; - u8 value[4] = { 0, 0, 0, 0 }; - - status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, - value, 4); - - cx231xx_coredbg("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN, - value[0], value[1], value[2], value[3]); - - cx231xx_coredbg("Enter cx231xx_demod_reset()\n"); - - value[1] = (u8) 0x3; - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - msleep(10); - - value[1] = (u8) 0x0; - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - msleep(10); - - value[1] = (u8) 0x3; - status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - PWR_CTL_EN, value, 4); - msleep(10); - - - - status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, - value, 4); - - cx231xx_coredbg("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN, - value[0], value[1], value[2], value[3]); - - return status; -} -EXPORT_SYMBOL_GPL(cx231xx_demod_reset); -int is_fw_load(struct cx231xx *dev) -{ - return cx231xx_check_fw(dev); -} -EXPORT_SYMBOL_GPL(is_fw_load); - -int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) -{ - int errCode = 0; - - if (dev->mode == set_mode) - return 0; - - if (set_mode == CX231XX_SUSPEND) { - /* Set the chip in power saving mode */ - dev->mode = set_mode; - } - - /* Resource is locked */ - if (dev->mode != CX231XX_SUSPEND) - return -EINVAL; - - dev->mode = set_mode; - - if (dev->mode == CX231XX_DIGITAL_MODE)/* Set Digital power mode */ { - /* set AGC mode to Digital */ - switch (dev->model) { - case CX231XX_BOARD_CNXT_CARRAERA: - case CX231XX_BOARD_CNXT_RDE_250: - case CX231XX_BOARD_CNXT_SHELBY: - case CX231XX_BOARD_CNXT_RDU_250: - errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0); - break; - case CX231XX_BOARD_CNXT_RDE_253S: - case CX231XX_BOARD_CNXT_RDU_253S: - errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); - break; - case CX231XX_BOARD_HAUPPAUGE_EXETER: - errCode = cx231xx_set_power_mode(dev, - POLARIS_AVMODE_DIGITAL); - break; - default: - break; - } - } else/* Set Analog Power mode */ { - /* set AGC mode to Analog */ - switch (dev->model) { - case CX231XX_BOARD_CNXT_CARRAERA: - case CX231XX_BOARD_CNXT_RDE_250: - case CX231XX_BOARD_CNXT_SHELBY: - case CX231XX_BOARD_CNXT_RDU_250: - errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); - break; - case CX231XX_BOARD_CNXT_RDE_253S: - case CX231XX_BOARD_CNXT_RDU_253S: - case CX231XX_BOARD_HAUPPAUGE_EXETER: - case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: - case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL: - case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC: - errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0); - break; - default: - break; - } - } - - return errCode ? -EINVAL : 0; -} -EXPORT_SYMBOL_GPL(cx231xx_set_mode); - -int cx231xx_ep5_bulkout(struct cx231xx *dev, u8 *firmware, u16 size) -{ - int errCode = 0; - int actlen, ret = -ENOMEM; - u32 *buffer; - - buffer = kzalloc(4096, GFP_KERNEL); - if (buffer == NULL) { - cx231xx_info("out of mem\n"); - return -ENOMEM; - } - memcpy(&buffer[0], firmware, 4096); - - ret = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 5), - buffer, 4096, &actlen, 2000); - - if (ret) - cx231xx_info("bulk message failed: %d (%d/%d)", ret, - size, actlen); - else { - errCode = actlen != size ? -1 : 0; - } - kfree(buffer); - return errCode; -} - -/***************************************************************** -* URB Streaming functions * -******************************************************************/ - -/* - * IRQ callback, called by URB callback - */ -static void cx231xx_isoc_irq_callback(struct urb *urb) -{ - struct cx231xx_dmaqueue *dma_q = urb->context; - struct cx231xx_video_mode *vmode = - container_of(dma_q, struct cx231xx_video_mode, vidq); - struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode); - int i; - - switch (urb->status) { - case 0: /* success */ - case -ETIMEDOUT: /* NAK */ - break; - case -ECONNRESET: /* kill */ - case -ENOENT: - case -ESHUTDOWN: - return; - default: /* error */ - cx231xx_isocdbg("urb completition error %d.\n", urb->status); - break; - } - - /* Copy data from URB */ - spin_lock(&dev->video_mode.slock); - dev->video_mode.isoc_ctl.isoc_copy(dev, urb); - spin_unlock(&dev->video_mode.slock); - - /* Reset urb buffers */ - for (i = 0; i < urb->number_of_packets; i++) { - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = 0; - } - - urb->status = usb_submit_urb(urb, GFP_ATOMIC); - if (urb->status) { - cx231xx_isocdbg("urb resubmit failed (error=%i)\n", - urb->status); - } -} -/***************************************************************** -* URB Streaming functions * -******************************************************************/ - -/* - * IRQ callback, called by URB callback - */ -static void cx231xx_bulk_irq_callback(struct urb *urb) -{ - struct cx231xx_dmaqueue *dma_q = urb->context; - struct cx231xx_video_mode *vmode = - container_of(dma_q, struct cx231xx_video_mode, vidq); - struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode); - - switch (urb->status) { - case 0: /* success */ - case -ETIMEDOUT: /* NAK */ - break; - case -ECONNRESET: /* kill */ - case -ENOENT: - case -ESHUTDOWN: - return; - default: /* error */ - cx231xx_isocdbg("urb completition error %d.\n", urb->status); - break; - } - - /* Copy data from URB */ - spin_lock(&dev->video_mode.slock); - dev->video_mode.bulk_ctl.bulk_copy(dev, urb); - spin_unlock(&dev->video_mode.slock); - - /* Reset urb buffers */ - urb->status = usb_submit_urb(urb, GFP_ATOMIC); - if (urb->status) { - cx231xx_isocdbg("urb resubmit failed (error=%i)\n", - urb->status); - } -} -/* - * Stop and Deallocate URBs - */ -void cx231xx_uninit_isoc(struct cx231xx *dev) -{ - struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq; - struct urb *urb; - int i; - - cx231xx_isocdbg("cx231xx: called cx231xx_uninit_isoc\n"); - - dev->video_mode.isoc_ctl.nfields = -1; - for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) { - urb = dev->video_mode.isoc_ctl.urb[i]; - if (urb) { - if (!irqs_disabled()) - usb_kill_urb(urb); - else - usb_unlink_urb(urb); - - if (dev->video_mode.isoc_ctl.transfer_buffer[i]) { - usb_free_coherent(dev->udev, - urb->transfer_buffer_length, - dev->video_mode.isoc_ctl. - transfer_buffer[i], - urb->transfer_dma); - } - usb_free_urb(urb); - dev->video_mode.isoc_ctl.urb[i] = NULL; - } - dev->video_mode.isoc_ctl.transfer_buffer[i] = NULL; - } - - kfree(dev->video_mode.isoc_ctl.urb); - kfree(dev->video_mode.isoc_ctl.transfer_buffer); - kfree(dma_q->p_left_data); - - dev->video_mode.isoc_ctl.urb = NULL; - dev->video_mode.isoc_ctl.transfer_buffer = NULL; - dev->video_mode.isoc_ctl.num_bufs = 0; - dma_q->p_left_data = NULL; - - if (dev->mode_tv == 0) - cx231xx_capture_start(dev, 0, Raw_Video); - else - cx231xx_capture_start(dev, 0, TS1_serial_mode); - - -} -EXPORT_SYMBOL_GPL(cx231xx_uninit_isoc); - -/* - * Stop and Deallocate URBs - */ -void cx231xx_uninit_bulk(struct cx231xx *dev) -{ - struct urb *urb; - int i; - - cx231xx_isocdbg("cx231xx: called cx231xx_uninit_bulk\n"); - - dev->video_mode.bulk_ctl.nfields = -1; - for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) { - urb = dev->video_mode.bulk_ctl.urb[i]; - if (urb) { - if (!irqs_disabled()) - usb_kill_urb(urb); - else - usb_unlink_urb(urb); - - if (dev->video_mode.bulk_ctl.transfer_buffer[i]) { - usb_free_coherent(dev->udev, - urb->transfer_buffer_length, - dev->video_mode.isoc_ctl. - transfer_buffer[i], - urb->transfer_dma); - } - usb_free_urb(urb); - dev->video_mode.bulk_ctl.urb[i] = NULL; - } - dev->video_mode.bulk_ctl.transfer_buffer[i] = NULL; - } - - kfree(dev->video_mode.bulk_ctl.urb); - kfree(dev->video_mode.bulk_ctl.transfer_buffer); - - dev->video_mode.bulk_ctl.urb = NULL; - dev->video_mode.bulk_ctl.transfer_buffer = NULL; - dev->video_mode.bulk_ctl.num_bufs = 0; - - if (dev->mode_tv == 0) - cx231xx_capture_start(dev, 0, Raw_Video); - else - cx231xx_capture_start(dev, 0, TS1_serial_mode); - - -} -EXPORT_SYMBOL_GPL(cx231xx_uninit_bulk); - -/* - * Allocate URBs and start IRQ - */ -int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, - int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct cx231xx *dev, struct urb *urb)) -{ - struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq; - int i; - int sb_size, pipe; - struct urb *urb; - int j, k; - int rc; - - /* De-allocates all pending stuff */ - cx231xx_uninit_isoc(dev); - - dma_q->p_left_data = kzalloc(4096, GFP_KERNEL); - if (dma_q->p_left_data == NULL) { - cx231xx_info("out of mem\n"); - return -ENOMEM; - } - - - - dev->video_mode.isoc_ctl.isoc_copy = isoc_copy; - dev->video_mode.isoc_ctl.num_bufs = num_bufs; - dma_q->pos = 0; - dma_q->is_partial_line = 0; - dma_q->last_sav = 0; - dma_q->current_field = -1; - dma_q->field1_done = 0; - dma_q->lines_per_field = dev->height / 2; - dma_q->bytes_left_in_line = dev->width << 1; - dma_q->lines_completed = 0; - dma_q->mpeg_buffer_done = 0; - dma_q->left_data_count = 0; - dma_q->mpeg_buffer_completed = 0; - dma_q->add_ps_package_head = CX231XX_NEED_ADD_PS_PACKAGE_HEAD; - dma_q->ps_head[0] = 0x00; - dma_q->ps_head[1] = 0x00; - dma_q->ps_head[2] = 0x01; - dma_q->ps_head[3] = 0xBA; - for (i = 0; i < 8; i++) - dma_q->partial_buf[i] = 0; - - dev->video_mode.isoc_ctl.urb = - kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); - if (!dev->video_mode.isoc_ctl.urb) { - cx231xx_errdev("cannot alloc memory for usb buffers\n"); - return -ENOMEM; - } - - dev->video_mode.isoc_ctl.transfer_buffer = - kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); - if (!dev->video_mode.isoc_ctl.transfer_buffer) { - cx231xx_errdev("cannot allocate memory for usbtransfer\n"); - kfree(dev->video_mode.isoc_ctl.urb); - return -ENOMEM; - } - - dev->video_mode.isoc_ctl.max_pkt_size = max_pkt_size; - dev->video_mode.isoc_ctl.buf = NULL; - - sb_size = max_packets * dev->video_mode.isoc_ctl.max_pkt_size; - - if (dev->mode_tv == 1) - dev->video_mode.end_point_addr = 0x81; - else - dev->video_mode.end_point_addr = 0x84; - - - /* allocate urbs and transfer buffers */ - for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) { - urb = usb_alloc_urb(max_packets, GFP_KERNEL); - if (!urb) { - cx231xx_err("cannot alloc isoc_ctl.urb %i\n", i); - cx231xx_uninit_isoc(dev); - return -ENOMEM; - } - dev->video_mode.isoc_ctl.urb[i] = urb; - - dev->video_mode.isoc_ctl.transfer_buffer[i] = - usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL, - &urb->transfer_dma); - if (!dev->video_mode.isoc_ctl.transfer_buffer[i]) { - cx231xx_err("unable to allocate %i bytes for transfer" - " buffer %i%s\n", - sb_size, i, - in_interrupt() ? " while in int" : ""); - cx231xx_uninit_isoc(dev); - return -ENOMEM; - } - memset(dev->video_mode.isoc_ctl.transfer_buffer[i], 0, sb_size); - - pipe = - usb_rcvisocpipe(dev->udev, dev->video_mode.end_point_addr); - - usb_fill_int_urb(urb, dev->udev, pipe, - dev->video_mode.isoc_ctl.transfer_buffer[i], - sb_size, cx231xx_isoc_irq_callback, dma_q, 1); - - urb->number_of_packets = max_packets; - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - - k = 0; - for (j = 0; j < max_packets; j++) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = - dev->video_mode.isoc_ctl.max_pkt_size; - k += dev->video_mode.isoc_ctl.max_pkt_size; - } - } - - init_waitqueue_head(&dma_q->wq); - - /* submit urbs and enables IRQ */ - for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) { - rc = usb_submit_urb(dev->video_mode.isoc_ctl.urb[i], - GFP_ATOMIC); - if (rc) { - cx231xx_err("submit of urb %i failed (error=%i)\n", i, - rc); - cx231xx_uninit_isoc(dev); - return rc; - } - } - - if (dev->mode_tv == 0) - cx231xx_capture_start(dev, 1, Raw_Video); - else - cx231xx_capture_start(dev, 1, TS1_serial_mode); - - return 0; -} -EXPORT_SYMBOL_GPL(cx231xx_init_isoc); - -/* - * Allocate URBs and start IRQ - */ -int cx231xx_init_bulk(struct cx231xx *dev, int max_packets, - int num_bufs, int max_pkt_size, - int (*bulk_copy) (struct cx231xx *dev, struct urb *urb)) -{ - struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq; - int i; - int sb_size, pipe; - struct urb *urb; - int rc; - - dev->video_input = dev->video_input > 2 ? 2 : dev->video_input; - - cx231xx_coredbg("Setting Video mux to %d\n", dev->video_input); - - video_mux(dev, dev->video_input); - - /* De-allocates all pending stuff */ - cx231xx_uninit_bulk(dev); - - dev->video_mode.bulk_ctl.bulk_copy = bulk_copy; - dev->video_mode.bulk_ctl.num_bufs = num_bufs; - dma_q->pos = 0; - dma_q->is_partial_line = 0; - dma_q->last_sav = 0; - dma_q->current_field = -1; - dma_q->field1_done = 0; - dma_q->lines_per_field = dev->height / 2; - dma_q->bytes_left_in_line = dev->width << 1; - dma_q->lines_completed = 0; - dma_q->mpeg_buffer_done = 0; - dma_q->left_data_count = 0; - dma_q->mpeg_buffer_completed = 0; - dma_q->ps_head[0] = 0x00; - dma_q->ps_head[1] = 0x00; - dma_q->ps_head[2] = 0x01; - dma_q->ps_head[3] = 0xBA; - for (i = 0; i < 8; i++) - dma_q->partial_buf[i] = 0; - - dev->video_mode.bulk_ctl.urb = - kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); - if (!dev->video_mode.bulk_ctl.urb) { - cx231xx_errdev("cannot alloc memory for usb buffers\n"); - return -ENOMEM; - } - - dev->video_mode.bulk_ctl.transfer_buffer = - kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); - if (!dev->video_mode.bulk_ctl.transfer_buffer) { - cx231xx_errdev("cannot allocate memory for usbtransfer\n"); - kfree(dev->video_mode.bulk_ctl.urb); - return -ENOMEM; - } - - dev->video_mode.bulk_ctl.max_pkt_size = max_pkt_size; - dev->video_mode.bulk_ctl.buf = NULL; - - sb_size = max_packets * dev->video_mode.bulk_ctl.max_pkt_size; - - if (dev->mode_tv == 1) - dev->video_mode.end_point_addr = 0x81; - else - dev->video_mode.end_point_addr = 0x84; - - - /* allocate urbs and transfer buffers */ - for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) { - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - cx231xx_err("cannot alloc bulk_ctl.urb %i\n", i); - cx231xx_uninit_bulk(dev); - return -ENOMEM; - } - dev->video_mode.bulk_ctl.urb[i] = urb; - urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; - - dev->video_mode.bulk_ctl.transfer_buffer[i] = - usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL, - &urb->transfer_dma); - if (!dev->video_mode.bulk_ctl.transfer_buffer[i]) { - cx231xx_err("unable to allocate %i bytes for transfer" - " buffer %i%s\n", - sb_size, i, - in_interrupt() ? " while in int" : ""); - cx231xx_uninit_bulk(dev); - return -ENOMEM; - } - memset(dev->video_mode.bulk_ctl.transfer_buffer[i], 0, sb_size); - - pipe = usb_rcvbulkpipe(dev->udev, - dev->video_mode.end_point_addr); - usb_fill_bulk_urb(urb, dev->udev, pipe, - dev->video_mode.bulk_ctl.transfer_buffer[i], - sb_size, cx231xx_bulk_irq_callback, dma_q); - } - - init_waitqueue_head(&dma_q->wq); - - /* submit urbs and enables IRQ */ - for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) { - rc = usb_submit_urb(dev->video_mode.bulk_ctl.urb[i], - GFP_ATOMIC); - if (rc) { - cx231xx_err("submit of urb %i failed (error=%i)\n", i, - rc); - cx231xx_uninit_bulk(dev); - return rc; - } - } - - if (dev->mode_tv == 0) - cx231xx_capture_start(dev, 1, Raw_Video); - else - cx231xx_capture_start(dev, 1, TS1_serial_mode); - - return 0; -} -EXPORT_SYMBOL_GPL(cx231xx_init_bulk); -void cx231xx_stop_TS1(struct cx231xx *dev) -{ - u8 val[4] = { 0, 0, 0, 0 }; - - val[0] = 0x00; - val[1] = 0x03; - val[2] = 0x00; - val[3] = 0x00; - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - TS_MODE_REG, val, 4); - - val[0] = 0x00; - val[1] = 0x70; - val[2] = 0x04; - val[3] = 0x00; - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - TS1_CFG_REG, val, 4); -} -/* EXPORT_SYMBOL_GPL(cx231xx_stop_TS1); */ -void cx231xx_start_TS1(struct cx231xx *dev) -{ - u8 val[4] = { 0, 0, 0, 0 }; - - val[0] = 0x03; - val[1] = 0x03; - val[2] = 0x00; - val[3] = 0x00; - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - TS_MODE_REG, val, 4); - - val[0] = 0x04; - val[1] = 0xA3; - val[2] = 0x3B; - val[3] = 0x00; - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, - TS1_CFG_REG, val, 4); -} -/* EXPORT_SYMBOL_GPL(cx231xx_start_TS1); */ -/***************************************************************** -* Device Init/UnInit functions * -******************************************************************/ -int cx231xx_dev_init(struct cx231xx *dev) -{ - int errCode = 0; - - /* Initialize I2C bus */ - - /* External Master 1 Bus */ - dev->i2c_bus[0].nr = 0; - dev->i2c_bus[0].dev = dev; - dev->i2c_bus[0].i2c_period = I2C_SPEED_100K; /* 100 KHz */ - dev->i2c_bus[0].i2c_nostop = 0; - dev->i2c_bus[0].i2c_reserve = 0; - - /* External Master 2 Bus */ - dev->i2c_bus[1].nr = 1; - dev->i2c_bus[1].dev = dev; - dev->i2c_bus[1].i2c_period = I2C_SPEED_100K; /* 100 KHz */ - dev->i2c_bus[1].i2c_nostop = 0; - dev->i2c_bus[1].i2c_reserve = 0; - - /* Internal Master 3 Bus */ - dev->i2c_bus[2].nr = 2; - dev->i2c_bus[2].dev = dev; - dev->i2c_bus[2].i2c_period = I2C_SPEED_100K; /* 100kHz */ - dev->i2c_bus[2].i2c_nostop = 0; - dev->i2c_bus[2].i2c_reserve = 0; - - /* register I2C buses */ - cx231xx_i2c_register(&dev->i2c_bus[0]); - cx231xx_i2c_register(&dev->i2c_bus[1]); - cx231xx_i2c_register(&dev->i2c_bus[2]); - - /* init hardware */ - /* Note : with out calling set power mode function, - afe can not be set up correctly */ - if (dev->board.external_av) { - errCode = cx231xx_set_power_mode(dev, - POLARIS_AVMODE_ENXTERNAL_AV); - if (errCode < 0) { - cx231xx_errdev - ("%s: Failed to set Power - errCode [%d]!\n", - __func__, errCode); - return errCode; - } - } else { - errCode = cx231xx_set_power_mode(dev, - POLARIS_AVMODE_ANALOGT_TV); - if (errCode < 0) { - cx231xx_errdev - ("%s: Failed to set Power - errCode [%d]!\n", - __func__, errCode); - return errCode; - } - } - - /* reset the Tuner, if it is a Xceive tuner */ - if ((dev->board.tuner_type == TUNER_XC5000) || - (dev->board.tuner_type == TUNER_XC2028)) - cx231xx_gpio_set(dev, dev->board.tuner_gpio); - - /* initialize Colibri block */ - errCode = cx231xx_afe_init_super_block(dev, 0x23c); - if (errCode < 0) { - cx231xx_errdev - ("%s: cx231xx_afe init super block - errCode [%d]!\n", - __func__, errCode); - return errCode; - } - errCode = cx231xx_afe_init_channels(dev); - if (errCode < 0) { - cx231xx_errdev - ("%s: cx231xx_afe init channels - errCode [%d]!\n", - __func__, errCode); - return errCode; - } - - /* Set DIF in By pass mode */ - errCode = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); - if (errCode < 0) { - cx231xx_errdev - ("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n", - __func__, errCode); - return errCode; - } - - /* I2S block related functions */ - errCode = cx231xx_i2s_blk_initialize(dev); - if (errCode < 0) { - cx231xx_errdev - ("%s: cx231xx_i2s block initialize - errCode [%d]!\n", - __func__, errCode); - return errCode; - } - - /* init control pins */ - errCode = cx231xx_init_ctrl_pin_status(dev); - if (errCode < 0) { - cx231xx_errdev("%s: cx231xx_init ctrl pins - errCode [%d]!\n", - __func__, errCode); - return errCode; - } - - /* set AGC mode to Analog */ - switch (dev->model) { - case CX231XX_BOARD_CNXT_CARRAERA: - case CX231XX_BOARD_CNXT_RDE_250: - case CX231XX_BOARD_CNXT_SHELBY: - case CX231XX_BOARD_CNXT_RDU_250: - errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); - break; - case CX231XX_BOARD_CNXT_RDE_253S: - case CX231XX_BOARD_CNXT_RDU_253S: - case CX231XX_BOARD_HAUPPAUGE_EXETER: - case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: - case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL: - case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC: - errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0); - break; - default: - break; - } - if (errCode < 0) { - cx231xx_errdev - ("%s: cx231xx_AGC mode to Analog - errCode [%d]!\n", - __func__, errCode); - return errCode; - } - - /* set all alternate settings to zero initially */ - cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0); - cx231xx_set_alt_setting(dev, INDEX_VANC, 0); - cx231xx_set_alt_setting(dev, INDEX_HANC, 0); - if (dev->board.has_dvb) - cx231xx_set_alt_setting(dev, INDEX_TS1, 0); - - /* set the I2C master port to 3 on channel 1 */ - errCode = cx231xx_enable_i2c_port_3(dev, true); - - return errCode; -} -EXPORT_SYMBOL_GPL(cx231xx_dev_init); - -void cx231xx_dev_uninit(struct cx231xx *dev) -{ - /* Un Initialize I2C bus */ - cx231xx_i2c_unregister(&dev->i2c_bus[2]); - cx231xx_i2c_unregister(&dev->i2c_bus[1]); - cx231xx_i2c_unregister(&dev->i2c_bus[0]); -} -EXPORT_SYMBOL_GPL(cx231xx_dev_uninit); - -/***************************************************************** -* G P I O related functions * -******************************************************************/ -int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val, - u8 len, u8 request, u8 direction) -{ - int status = 0; - struct VENDOR_REQUEST_IN ven_req; - - /* Set wValue */ - ven_req.wValue = (u16) (gpio_bit >> 16 & 0xffff); - - /* set request */ - if (!request) { - if (direction) - ven_req.bRequest = VRT_GET_GPIO; /* 0x8 gpio */ - else - ven_req.bRequest = VRT_SET_GPIO; /* 0x9 gpio */ - } else { - if (direction) - ven_req.bRequest = VRT_GET_GPIE; /* 0xa gpie */ - else - ven_req.bRequest = VRT_SET_GPIE; /* 0xb gpie */ - } - - /* set index value */ - ven_req.wIndex = (u16) (gpio_bit & 0xffff); - - /* set wLength value */ - ven_req.wLength = len; - - /* set bData value */ - ven_req.bData = 0; - - /* set the buffer for read / write */ - ven_req.pBuff = gpio_val; - - /* set the direction */ - if (direction) { - ven_req.direction = USB_DIR_IN; - memset(ven_req.pBuff, 0x00, ven_req.wLength); - } else - ven_req.direction = USB_DIR_OUT; - - - /* call common vendor command request */ - status = cx231xx_send_vendor_cmd(dev, &ven_req); - if (status < 0) { - cx231xx_info - ("UsbInterface::sendCommand, failed with status -%d\n", - status); - } - - return status; -} -EXPORT_SYMBOL_GPL(cx231xx_send_gpio_cmd); - -/***************************************************************** - * C O N T R O L - Register R E A D / W R I T E functions * - *****************************************************************/ -int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode) -{ - u8 value[4] = { 0x0, 0x0, 0x0, 0x0 }; - u32 tmp = 0; - int status = 0; - - status = - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, address, value, 4); - if (status < 0) - return status; - - tmp = *((u32 *) value); - tmp |= mode; - - value[0] = (u8) tmp; - value[1] = (u8) (tmp >> 8); - value[2] = (u8) (tmp >> 16); - value[3] = (u8) (tmp >> 24); - - status = - cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, address, value, 4); - - return status; -} - -/***************************************************************** - * I 2 C Internal C O N T R O L functions * - *****************************************************************/ -int cx231xx_read_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr, - u8 saddr_len, u32 *data, u8 data_len, int master) -{ - int status = 0; - struct cx231xx_i2c_xfer_data req_data; - u8 value[64] = "0"; - - if (saddr_len == 0) - saddr = 0; - else if (saddr_len == 1) - saddr &= 0xff; - - /* prepare xfer_data struct */ - req_data.dev_addr = dev_addr >> 1; - req_data.direction = I2C_M_RD; - req_data.saddr_len = saddr_len; - req_data.saddr_dat = saddr; - req_data.buf_size = data_len; - req_data.p_buffer = (u8 *) value; - - /* usb send command */ - if (master == 0) - status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], - &req_data); - else if (master == 1) - status = dev->cx231xx_send_usb_command(&dev->i2c_bus[1], - &req_data); - else if (master == 2) - status = dev->cx231xx_send_usb_command(&dev->i2c_bus[2], - &req_data); - - if (status >= 0) { - /* Copy the data read back to main buffer */ - if (data_len == 1) - *data = value[0]; - else if (data_len == 4) - *data = - value[0] | value[1] << 8 | value[2] << 16 | value[3] - << 24; - else if (data_len > 4) - *data = value[saddr]; - } - - return status; -} - -int cx231xx_write_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr, - u8 saddr_len, u32 data, u8 data_len, int master) -{ - int status = 0; - u8 value[4] = { 0, 0, 0, 0 }; - struct cx231xx_i2c_xfer_data req_data; - - value[0] = (u8) data; - value[1] = (u8) (data >> 8); - value[2] = (u8) (data >> 16); - value[3] = (u8) (data >> 24); - - if (saddr_len == 0) - saddr = 0; - else if (saddr_len == 1) - saddr &= 0xff; - - /* prepare xfer_data struct */ - req_data.dev_addr = dev_addr >> 1; - req_data.direction = 0; - req_data.saddr_len = saddr_len; - req_data.saddr_dat = saddr; - req_data.buf_size = data_len; - req_data.p_buffer = value; - - /* usb send command */ - if (master == 0) - status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], - &req_data); - else if (master == 1) - status = dev->cx231xx_send_usb_command(&dev->i2c_bus[1], - &req_data); - else if (master == 2) - status = dev->cx231xx_send_usb_command(&dev->i2c_bus[2], - &req_data); - - return status; -} - -int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, - u8 saddr_len, u32 *data, u8 data_len) -{ - int status = 0; - struct cx231xx_i2c_xfer_data req_data; - u8 value[4] = { 0, 0, 0, 0 }; - - if (saddr_len == 0) - saddr = 0; - else if (saddr_len == 1) - saddr &= 0xff; - - /* prepare xfer_data struct */ - req_data.dev_addr = dev_addr >> 1; - req_data.direction = I2C_M_RD; - req_data.saddr_len = saddr_len; - req_data.saddr_dat = saddr; - req_data.buf_size = data_len; - req_data.p_buffer = (u8 *) value; - - /* usb send command */ - status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data); - - if (status >= 0) { - /* Copy the data read back to main buffer */ - if (data_len == 1) - *data = value[0]; - else - *data = - value[0] | value[1] << 8 | value[2] << 16 | value[3] - << 24; - } - - return status; -} - -int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, - u8 saddr_len, u32 data, u8 data_len) -{ - int status = 0; - u8 value[4] = { 0, 0, 0, 0 }; - struct cx231xx_i2c_xfer_data req_data; - - value[0] = (u8) data; - value[1] = (u8) (data >> 8); - value[2] = (u8) (data >> 16); - value[3] = (u8) (data >> 24); - - if (saddr_len == 0) - saddr = 0; - else if (saddr_len == 1) - saddr &= 0xff; - - /* prepare xfer_data struct */ - req_data.dev_addr = dev_addr >> 1; - req_data.direction = 0; - req_data.saddr_len = saddr_len; - req_data.saddr_dat = saddr; - req_data.buf_size = data_len; - req_data.p_buffer = value; - - /* usb send command */ - status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data); - - return status; -} - -int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size, - u16 register_address, u8 bit_start, u8 bit_end, - u32 value) -{ - int status = 0; - u32 tmp; - u32 mask = 0; - int i; - - if (bit_start > (size - 1) || bit_end > (size - 1)) - return -1; - - if (size == 8) { - status = - cx231xx_read_i2c_data(dev, dev_addr, register_address, 2, - &tmp, 1); - } else { - status = - cx231xx_read_i2c_data(dev, dev_addr, register_address, 2, - &tmp, 4); - } - - if (status < 0) - return status; - - mask = 1 << bit_end; - for (i = bit_end; i > bit_start && i > 0; i--) - mask = mask + (1 << (i - 1)); - - value <<= bit_start; - - if (size == 8) { - tmp &= ~mask; - tmp |= value; - tmp &= 0xff; - status = - cx231xx_write_i2c_data(dev, dev_addr, register_address, 2, - tmp, 1); - } else { - tmp &= ~mask; - tmp |= value; - status = - cx231xx_write_i2c_data(dev, dev_addr, register_address, 2, - tmp, 4); - } - - return status; -} - -int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr, - u16 saddr, u32 mask, u32 value) -{ - u32 temp; - int status = 0; - - status = cx231xx_read_i2c_data(dev, dev_addr, saddr, 2, &temp, 4); - - if (status < 0) - return status; - - temp &= ~mask; - temp |= value; - - status = cx231xx_write_i2c_data(dev, dev_addr, saddr, 2, temp, 4); - - return status; -} - -u32 cx231xx_set_field(u32 field_mask, u32 data) -{ - u32 temp; - - for (temp = field_mask; (temp & 1) == 0; temp >>= 1) - data <<= 1; - - return data; -} diff --git a/drivers/media/video/cx231xx/cx231xx-dif.h b/drivers/media/video/cx231xx/cx231xx-dif.h deleted file mode 100644 index 2b63c2f6d3b0..000000000000 --- a/drivers/media/video/cx231xx/cx231xx-dif.h +++ /dev/null @@ -1,3178 +0,0 @@ -/* - * cx231xx-dif.h - driver for Conexant Cx23100/101/102 USB video capture devices - * - * Copyright {C} 2009 <Bill.Liu@conexant.com> - * - * 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. - */ - -#ifndef _CX231XX_DIF_H -#define _CX231XX_DIF_H - -#include "cx231xx-reg.h" - -struct dif_settings{ - u32 if_freq; - u32 register_address; - u32 value; -}; - -static struct dif_settings Dif_set_array[] = { - -/*case 3000000:*/ -/* BEGIN - DIF BPF register values from 30_quant.dat*/ -{3000000, DIF_BPF_COEFF01, 0x00000002}, -{3000000, DIF_BPF_COEFF23, 0x00080012}, -{3000000, DIF_BPF_COEFF45, 0x001e0024}, -{3000000, DIF_BPF_COEFF67, 0x001bfff8}, -{3000000, DIF_BPF_COEFF89, 0xffb4ff50}, -{3000000, DIF_BPF_COEFF1011, 0xfed8fe68}, -{3000000, DIF_BPF_COEFF1213, 0xfe24fe34}, -{3000000, DIF_BPF_COEFF1415, 0xfebaffc7}, -{3000000, DIF_BPF_COEFF1617, 0x014d031f}, -{3000000, DIF_BPF_COEFF1819, 0x04f0065d}, -{3000000, DIF_BPF_COEFF2021, 0x07010688}, -{3000000, DIF_BPF_COEFF2223, 0x04c901d6}, -{3000000, DIF_BPF_COEFF2425, 0xfe00f9d3}, -{3000000, DIF_BPF_COEFF2627, 0xf600f342}, -{3000000, DIF_BPF_COEFF2829, 0xf235f337}, -{3000000, DIF_BPF_COEFF3031, 0xf64efb22}, -{3000000, DIF_BPF_COEFF3233, 0x0105070f}, -{3000000, DIF_BPF_COEFF3435, 0x0c460fce}, -{3000000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 30_quant.dat*/ - - -/*case 3100000:*/ -/* BEGIN - DIF BPF register values from 31_quant.dat*/ -{3100000, DIF_BPF_COEFF01, 0x00000001}, -{3100000, DIF_BPF_COEFF23, 0x00070012}, -{3100000, DIF_BPF_COEFF45, 0x00220032}, -{3100000, DIF_BPF_COEFF67, 0x00370026}, -{3100000, DIF_BPF_COEFF89, 0xfff0ff91}, -{3100000, DIF_BPF_COEFF1011, 0xff0efe7c}, -{3100000, DIF_BPF_COEFF1213, 0xfe01fdcc}, -{3100000, DIF_BPF_COEFF1415, 0xfe0afedb}, -{3100000, DIF_BPF_COEFF1617, 0x00440224}, -{3100000, DIF_BPF_COEFF1819, 0x0434060c}, -{3100000, DIF_BPF_COEFF2021, 0x0738074e}, -{3100000, DIF_BPF_COEFF2223, 0x06090361}, -{3100000, DIF_BPF_COEFF2425, 0xff99fb39}, -{3100000, DIF_BPF_COEFF2627, 0xf6fef3b6}, -{3100000, DIF_BPF_COEFF2829, 0xf21af2a5}, -{3100000, DIF_BPF_COEFF3031, 0xf573fa33}, -{3100000, DIF_BPF_COEFF3233, 0x0034067d}, -{3100000, DIF_BPF_COEFF3435, 0x0bfb0fb9}, -{3100000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 31_quant.dat*/ - - -/*case 3200000:*/ -/* BEGIN - DIF BPF register values from 32_quant.dat*/ -{3200000, DIF_BPF_COEFF01, 0x00000000}, -{3200000, DIF_BPF_COEFF23, 0x0004000e}, -{3200000, DIF_BPF_COEFF45, 0x00200038}, -{3200000, DIF_BPF_COEFF67, 0x004c004f}, -{3200000, DIF_BPF_COEFF89, 0x002fffdf}, -{3200000, DIF_BPF_COEFF1011, 0xff5cfeb6}, -{3200000, DIF_BPF_COEFF1213, 0xfe0dfd92}, -{3200000, DIF_BPF_COEFF1415, 0xfd7ffe03}, -{3200000, DIF_BPF_COEFF1617, 0xff36010a}, -{3200000, DIF_BPF_COEFF1819, 0x03410575}, -{3200000, DIF_BPF_COEFF2021, 0x072607d2}, -{3200000, DIF_BPF_COEFF2223, 0x071804d5}, -{3200000, DIF_BPF_COEFF2425, 0x0134fcb7}, -{3200000, DIF_BPF_COEFF2627, 0xf81ff451}, -{3200000, DIF_BPF_COEFF2829, 0xf223f22e}, -{3200000, DIF_BPF_COEFF3031, 0xf4a7f94b}, -{3200000, DIF_BPF_COEFF3233, 0xff6405e8}, -{3200000, DIF_BPF_COEFF3435, 0x0bae0fa4}, -{3200000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 32_quant.dat*/ - - -/*case 3300000:*/ -/* BEGIN - DIF BPF register values from 33_quant.dat*/ -{3300000, DIF_BPF_COEFF01, 0x0000ffff}, -{3300000, DIF_BPF_COEFF23, 0x00000008}, -{3300000, DIF_BPF_COEFF45, 0x001a0036}, -{3300000, DIF_BPF_COEFF67, 0x0056006d}, -{3300000, DIF_BPF_COEFF89, 0x00670030}, -{3300000, DIF_BPF_COEFF1011, 0xffbdff10}, -{3300000, DIF_BPF_COEFF1213, 0xfe46fd8d}, -{3300000, DIF_BPF_COEFF1415, 0xfd25fd4f}, -{3300000, DIF_BPF_COEFF1617, 0xfe35ffe0}, -{3300000, DIF_BPF_COEFF1819, 0x0224049f}, -{3300000, DIF_BPF_COEFF2021, 0x06c9080e}, -{3300000, DIF_BPF_COEFF2223, 0x07ef0627}, -{3300000, DIF_BPF_COEFF2425, 0x02c9fe45}, -{3300000, DIF_BPF_COEFF2627, 0xf961f513}, -{3300000, DIF_BPF_COEFF2829, 0xf250f1d2}, -{3300000, DIF_BPF_COEFF3031, 0xf3ecf869}, -{3300000, DIF_BPF_COEFF3233, 0xfe930552}, -{3300000, DIF_BPF_COEFF3435, 0x0b5f0f8f}, -{3300000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 33_quant.dat*/ - - -/*case 3400000:*/ -/* BEGIN - DIF BPF register values from 34_quant.dat*/ -{3400000, DIF_BPF_COEFF01, 0xfffffffe}, -{3400000, DIF_BPF_COEFF23, 0xfffd0001}, -{3400000, DIF_BPF_COEFF45, 0x000f002c}, -{3400000, DIF_BPF_COEFF67, 0x0054007d}, -{3400000, DIF_BPF_COEFF89, 0x0093007c}, -{3400000, DIF_BPF_COEFF1011, 0x0024ff82}, -{3400000, DIF_BPF_COEFF1213, 0xfea6fdbb}, -{3400000, DIF_BPF_COEFF1415, 0xfd03fcca}, -{3400000, DIF_BPF_COEFF1617, 0xfd51feb9}, -{3400000, DIF_BPF_COEFF1819, 0x00eb0392}, -{3400000, DIF_BPF_COEFF2021, 0x06270802}, -{3400000, DIF_BPF_COEFF2223, 0x08880750}, -{3400000, DIF_BPF_COEFF2425, 0x044dffdb}, -{3400000, DIF_BPF_COEFF2627, 0xfabdf5f8}, -{3400000, DIF_BPF_COEFF2829, 0xf2a0f193}, -{3400000, DIF_BPF_COEFF3031, 0xf342f78f}, -{3400000, DIF_BPF_COEFF3233, 0xfdc404b9}, -{3400000, DIF_BPF_COEFF3435, 0x0b0e0f78}, -{3400000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 34_quant.dat*/ - - -/*case 3500000:*/ -/* BEGIN - DIF BPF register values from 35_quant.dat*/ -{3500000, DIF_BPF_COEFF01, 0xfffffffd}, -{3500000, DIF_BPF_COEFF23, 0xfffafff9}, -{3500000, DIF_BPF_COEFF45, 0x0002001b}, -{3500000, DIF_BPF_COEFF67, 0x0046007d}, -{3500000, DIF_BPF_COEFF89, 0x00ad00ba}, -{3500000, DIF_BPF_COEFF1011, 0x00870000}, -{3500000, DIF_BPF_COEFF1213, 0xff26fe1a}, -{3500000, DIF_BPF_COEFF1415, 0xfd1bfc7e}, -{3500000, DIF_BPF_COEFF1617, 0xfc99fda4}, -{3500000, DIF_BPF_COEFF1819, 0xffa5025c}, -{3500000, DIF_BPF_COEFF2021, 0x054507ad}, -{3500000, DIF_BPF_COEFF2223, 0x08dd0847}, -{3500000, DIF_BPF_COEFF2425, 0x05b80172}, -{3500000, DIF_BPF_COEFF2627, 0xfc2ef6ff}, -{3500000, DIF_BPF_COEFF2829, 0xf313f170}, -{3500000, DIF_BPF_COEFF3031, 0xf2abf6bd}, -{3500000, DIF_BPF_COEFF3233, 0xfcf6041f}, -{3500000, DIF_BPF_COEFF3435, 0x0abc0f61}, -{3500000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 35_quant.dat*/ - - -/*case 3600000:*/ -/* BEGIN - DIF BPF register values from 36_quant.dat*/ -{3600000, DIF_BPF_COEFF01, 0xfffffffd}, -{3600000, DIF_BPF_COEFF23, 0xfff8fff3}, -{3600000, DIF_BPF_COEFF45, 0xfff50006}, -{3600000, DIF_BPF_COEFF67, 0x002f006c}, -{3600000, DIF_BPF_COEFF89, 0x00b200e3}, -{3600000, DIF_BPF_COEFF1011, 0x00dc007e}, -{3600000, DIF_BPF_COEFF1213, 0xffb9fea0}, -{3600000, DIF_BPF_COEFF1415, 0xfd6bfc71}, -{3600000, DIF_BPF_COEFF1617, 0xfc17fcb1}, -{3600000, DIF_BPF_COEFF1819, 0xfe65010b}, -{3600000, DIF_BPF_COEFF2021, 0x042d0713}, -{3600000, DIF_BPF_COEFF2223, 0x08ec0906}, -{3600000, DIF_BPF_COEFF2425, 0x07020302}, -{3600000, DIF_BPF_COEFF2627, 0xfdaff823}, -{3600000, DIF_BPF_COEFF2829, 0xf3a7f16a}, -{3600000, DIF_BPF_COEFF3031, 0xf228f5f5}, -{3600000, DIF_BPF_COEFF3233, 0xfc2a0384}, -{3600000, DIF_BPF_COEFF3435, 0x0a670f4a}, -{3600000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 36_quant.dat*/ - - -/*case 3700000:*/ -/* BEGIN - DIF BPF register values from 37_quant.dat*/ -{3700000, DIF_BPF_COEFF01, 0x0000fffd}, -{3700000, DIF_BPF_COEFF23, 0xfff7ffef}, -{3700000, DIF_BPF_COEFF45, 0xffe9fff1}, -{3700000, DIF_BPF_COEFF67, 0x0010004d}, -{3700000, DIF_BPF_COEFF89, 0x00a100f2}, -{3700000, DIF_BPF_COEFF1011, 0x011a00f0}, -{3700000, DIF_BPF_COEFF1213, 0x0053ff44}, -{3700000, DIF_BPF_COEFF1415, 0xfdedfca2}, -{3700000, DIF_BPF_COEFF1617, 0xfbd3fbef}, -{3700000, DIF_BPF_COEFF1819, 0xfd39ffae}, -{3700000, DIF_BPF_COEFF2021, 0x02ea0638}, -{3700000, DIF_BPF_COEFF2223, 0x08b50987}, -{3700000, DIF_BPF_COEFF2425, 0x08230483}, -{3700000, DIF_BPF_COEFF2627, 0xff39f960}, -{3700000, DIF_BPF_COEFF2829, 0xf45bf180}, -{3700000, DIF_BPF_COEFF3031, 0xf1b8f537}, -{3700000, DIF_BPF_COEFF3233, 0xfb6102e7}, -{3700000, DIF_BPF_COEFF3435, 0x0a110f32}, -{3700000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 37_quant.dat*/ - - -/*case 3800000:*/ -/* BEGIN - DIF BPF register values from 38_quant.dat*/ -{3800000, DIF_BPF_COEFF01, 0x0000fffe}, -{3800000, DIF_BPF_COEFF23, 0xfff9ffee}, -{3800000, DIF_BPF_COEFF45, 0xffe1ffdd}, -{3800000, DIF_BPF_COEFF67, 0xfff00024}, -{3800000, DIF_BPF_COEFF89, 0x007c00e5}, -{3800000, DIF_BPF_COEFF1011, 0x013a014a}, -{3800000, DIF_BPF_COEFF1213, 0x00e6fff8}, -{3800000, DIF_BPF_COEFF1415, 0xfe98fd0f}, -{3800000, DIF_BPF_COEFF1617, 0xfbd3fb67}, -{3800000, DIF_BPF_COEFF1819, 0xfc32fe54}, -{3800000, DIF_BPF_COEFF2021, 0x01880525}, -{3800000, DIF_BPF_COEFF2223, 0x083909c7}, -{3800000, DIF_BPF_COEFF2425, 0x091505ee}, -{3800000, DIF_BPF_COEFF2627, 0x00c7fab3}, -{3800000, DIF_BPF_COEFF2829, 0xf52df1b4}, -{3800000, DIF_BPF_COEFF3031, 0xf15df484}, -{3800000, DIF_BPF_COEFF3233, 0xfa9b0249}, -{3800000, DIF_BPF_COEFF3435, 0x09ba0f19}, -{3800000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 38_quant.dat*/ - - -/*case 3900000:*/ -/* BEGIN - DIF BPF register values from 39_quant.dat*/ -{3900000, DIF_BPF_COEFF01, 0x00000000}, -{3900000, DIF_BPF_COEFF23, 0xfffbfff0}, -{3900000, DIF_BPF_COEFF45, 0xffdeffcf}, -{3900000, DIF_BPF_COEFF67, 0xffd1fff6}, -{3900000, DIF_BPF_COEFF89, 0x004800be}, -{3900000, DIF_BPF_COEFF1011, 0x01390184}, -{3900000, DIF_BPF_COEFF1213, 0x016300ac}, -{3900000, DIF_BPF_COEFF1415, 0xff5efdb1}, -{3900000, DIF_BPF_COEFF1617, 0xfc17fb23}, -{3900000, DIF_BPF_COEFF1819, 0xfb5cfd0d}, -{3900000, DIF_BPF_COEFF2021, 0x001703e4}, -{3900000, DIF_BPF_COEFF2223, 0x077b09c4}, -{3900000, DIF_BPF_COEFF2425, 0x09d2073c}, -{3900000, DIF_BPF_COEFF2627, 0x0251fc18}, -{3900000, DIF_BPF_COEFF2829, 0xf61cf203}, -{3900000, DIF_BPF_COEFF3031, 0xf118f3dc}, -{3900000, DIF_BPF_COEFF3233, 0xf9d801aa}, -{3900000, DIF_BPF_COEFF3435, 0x09600eff}, -{3900000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 39_quant.dat*/ - - -/*case 4000000:*/ -/* BEGIN - DIF BPF register values from 40_quant.dat*/ -{4000000, DIF_BPF_COEFF01, 0x00000001}, -{4000000, DIF_BPF_COEFF23, 0xfffefff4}, -{4000000, DIF_BPF_COEFF45, 0xffe1ffc8}, -{4000000, DIF_BPF_COEFF67, 0xffbaffca}, -{4000000, DIF_BPF_COEFF89, 0x000b0082}, -{4000000, DIF_BPF_COEFF1011, 0x01170198}, -{4000000, DIF_BPF_COEFF1213, 0x01c10152}, -{4000000, DIF_BPF_COEFF1415, 0x0030fe7b}, -{4000000, DIF_BPF_COEFF1617, 0xfc99fb24}, -{4000000, DIF_BPF_COEFF1819, 0xfac3fbe9}, -{4000000, DIF_BPF_COEFF2021, 0xfea5027f}, -{4000000, DIF_BPF_COEFF2223, 0x0683097f}, -{4000000, DIF_BPF_COEFF2425, 0x0a560867}, -{4000000, DIF_BPF_COEFF2627, 0x03d2fd89}, -{4000000, DIF_BPF_COEFF2829, 0xf723f26f}, -{4000000, DIF_BPF_COEFF3031, 0xf0e8f341}, -{4000000, DIF_BPF_COEFF3233, 0xf919010a}, -{4000000, DIF_BPF_COEFF3435, 0x09060ee5}, -{4000000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 40_quant.dat*/ - - -/*case 4100000:*/ -/* BEGIN - DIF BPF register values from 41_quant.dat*/ -{4100000, DIF_BPF_COEFF01, 0x00010002}, -{4100000, DIF_BPF_COEFF23, 0x0002fffb}, -{4100000, DIF_BPF_COEFF45, 0xffe8ffca}, -{4100000, DIF_BPF_COEFF67, 0xffacffa4}, -{4100000, DIF_BPF_COEFF89, 0xffcd0036}, -{4100000, DIF_BPF_COEFF1011, 0x00d70184}, -{4100000, DIF_BPF_COEFF1213, 0x01f601dc}, -{4100000, DIF_BPF_COEFF1415, 0x00ffff60}, -{4100000, DIF_BPF_COEFF1617, 0xfd51fb6d}, -{4100000, DIF_BPF_COEFF1819, 0xfa6efaf5}, -{4100000, DIF_BPF_COEFF2021, 0xfd410103}, -{4100000, DIF_BPF_COEFF2223, 0x055708f9}, -{4100000, DIF_BPF_COEFF2425, 0x0a9e0969}, -{4100000, DIF_BPF_COEFF2627, 0x0543ff02}, -{4100000, DIF_BPF_COEFF2829, 0xf842f2f5}, -{4100000, DIF_BPF_COEFF3031, 0xf0cef2b2}, -{4100000, DIF_BPF_COEFF3233, 0xf85e006b}, -{4100000, DIF_BPF_COEFF3435, 0x08aa0ecb}, -{4100000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 41_quant.dat*/ - - -/*case 4200000:*/ -/* BEGIN - DIF BPF register values from 42_quant.dat*/ -{4200000, DIF_BPF_COEFF01, 0x00010003}, -{4200000, DIF_BPF_COEFF23, 0x00050003}, -{4200000, DIF_BPF_COEFF45, 0xfff3ffd3}, -{4200000, DIF_BPF_COEFF67, 0xffaaff8b}, -{4200000, DIF_BPF_COEFF89, 0xff95ffe5}, -{4200000, DIF_BPF_COEFF1011, 0x0080014a}, -{4200000, DIF_BPF_COEFF1213, 0x01fe023f}, -{4200000, DIF_BPF_COEFF1415, 0x01ba0050}, -{4200000, DIF_BPF_COEFF1617, 0xfe35fbf8}, -{4200000, DIF_BPF_COEFF1819, 0xfa62fa3b}, -{4200000, DIF_BPF_COEFF2021, 0xfbf9ff7e}, -{4200000, DIF_BPF_COEFF2223, 0x04010836}, -{4200000, DIF_BPF_COEFF2425, 0x0aa90a3d}, -{4200000, DIF_BPF_COEFF2627, 0x069f007f}, -{4200000, DIF_BPF_COEFF2829, 0xf975f395}, -{4200000, DIF_BPF_COEFF3031, 0xf0cbf231}, -{4200000, DIF_BPF_COEFF3233, 0xf7a9ffcb}, -{4200000, DIF_BPF_COEFF3435, 0x084c0eaf}, -{4200000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 42_quant.dat*/ - - -/*case 4300000:*/ -/* BEGIN - DIF BPF register values from 43_quant.dat*/ -{4300000, DIF_BPF_COEFF01, 0x00010003}, -{4300000, DIF_BPF_COEFF23, 0x0008000a}, -{4300000, DIF_BPF_COEFF45, 0x0000ffe4}, -{4300000, DIF_BPF_COEFF67, 0xffb4ff81}, -{4300000, DIF_BPF_COEFF89, 0xff6aff96}, -{4300000, DIF_BPF_COEFF1011, 0x001c00f0}, -{4300000, DIF_BPF_COEFF1213, 0x01d70271}, -{4300000, DIF_BPF_COEFF1415, 0x0254013b}, -{4300000, DIF_BPF_COEFF1617, 0xff36fcbd}, -{4300000, DIF_BPF_COEFF1819, 0xfa9ff9c5}, -{4300000, DIF_BPF_COEFF2021, 0xfadbfdfe}, -{4300000, DIF_BPF_COEFF2223, 0x028c073b}, -{4300000, DIF_BPF_COEFF2425, 0x0a750adf}, -{4300000, DIF_BPF_COEFF2627, 0x07e101fa}, -{4300000, DIF_BPF_COEFF2829, 0xfab8f44e}, -{4300000, DIF_BPF_COEFF3031, 0xf0ddf1be}, -{4300000, DIF_BPF_COEFF3233, 0xf6f9ff2b}, -{4300000, DIF_BPF_COEFF3435, 0x07ed0e94}, -{4300000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 43_quant.dat*/ - - -/*case 4400000:*/ -/* BEGIN - DIF BPF register values from 44_quant.dat*/ -{4400000, DIF_BPF_COEFF01, 0x00000003}, -{4400000, DIF_BPF_COEFF23, 0x0009000f}, -{4400000, DIF_BPF_COEFF45, 0x000efff8}, -{4400000, DIF_BPF_COEFF67, 0xffc9ff87}, -{4400000, DIF_BPF_COEFF89, 0xff52ff54}, -{4400000, DIF_BPF_COEFF1011, 0xffb5007e}, -{4400000, DIF_BPF_COEFF1213, 0x01860270}, -{4400000, DIF_BPF_COEFF1415, 0x02c00210}, -{4400000, DIF_BPF_COEFF1617, 0x0044fdb2}, -{4400000, DIF_BPF_COEFF1819, 0xfb22f997}, -{4400000, DIF_BPF_COEFF2021, 0xf9f2fc90}, -{4400000, DIF_BPF_COEFF2223, 0x0102060f}, -{4400000, DIF_BPF_COEFF2425, 0x0a050b4c}, -{4400000, DIF_BPF_COEFF2627, 0x0902036e}, -{4400000, DIF_BPF_COEFF2829, 0xfc0af51e}, -{4400000, DIF_BPF_COEFF3031, 0xf106f15a}, -{4400000, DIF_BPF_COEFF3233, 0xf64efe8b}, -{4400000, DIF_BPF_COEFF3435, 0x078d0e77}, -{4400000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 44_quant.dat*/ - - -/*case 4500000:*/ -/* BEGIN - DIF BPF register values from 45_quant.dat*/ -{4500000, DIF_BPF_COEFF01, 0x00000002}, -{4500000, DIF_BPF_COEFF23, 0x00080012}, -{4500000, DIF_BPF_COEFF45, 0x0019000e}, -{4500000, DIF_BPF_COEFF67, 0xffe5ff9e}, -{4500000, DIF_BPF_COEFF89, 0xff4fff25}, -{4500000, DIF_BPF_COEFF1011, 0xff560000}, -{4500000, DIF_BPF_COEFF1213, 0x0112023b}, -{4500000, DIF_BPF_COEFF1415, 0x02f702c0}, -{4500000, DIF_BPF_COEFF1617, 0x014dfec8}, -{4500000, DIF_BPF_COEFF1819, 0xfbe5f9b3}, -{4500000, DIF_BPF_COEFF2021, 0xf947fb41}, -{4500000, DIF_BPF_COEFF2223, 0xff7004b9}, -{4500000, DIF_BPF_COEFF2425, 0x095a0b81}, -{4500000, DIF_BPF_COEFF2627, 0x0a0004d8}, -{4500000, DIF_BPF_COEFF2829, 0xfd65f603}, -{4500000, DIF_BPF_COEFF3031, 0xf144f104}, -{4500000, DIF_BPF_COEFF3233, 0xf5aafdec}, -{4500000, DIF_BPF_COEFF3435, 0x072b0e5a}, -{4500000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 45_quant.dat*/ - - -/*case 4600000:*/ -/* BEGIN - DIF BPF register values from 46_quant.dat*/ -{4600000, DIF_BPF_COEFF01, 0x00000001}, -{4600000, DIF_BPF_COEFF23, 0x00060012}, -{4600000, DIF_BPF_COEFF45, 0x00200022}, -{4600000, DIF_BPF_COEFF67, 0x0005ffc1}, -{4600000, DIF_BPF_COEFF89, 0xff61ff10}, -{4600000, DIF_BPF_COEFF1011, 0xff09ff82}, -{4600000, DIF_BPF_COEFF1213, 0x008601d7}, -{4600000, DIF_BPF_COEFF1415, 0x02f50340}, -{4600000, DIF_BPF_COEFF1617, 0x0241fff0}, -{4600000, DIF_BPF_COEFF1819, 0xfcddfa19}, -{4600000, DIF_BPF_COEFF2021, 0xf8e2fa1e}, -{4600000, DIF_BPF_COEFF2223, 0xfde30343}, -{4600000, DIF_BPF_COEFF2425, 0x08790b7f}, -{4600000, DIF_BPF_COEFF2627, 0x0ad50631}, -{4600000, DIF_BPF_COEFF2829, 0xfec7f6fc}, -{4600000, DIF_BPF_COEFF3031, 0xf198f0bd}, -{4600000, DIF_BPF_COEFF3233, 0xf50dfd4e}, -{4600000, DIF_BPF_COEFF3435, 0x06c90e3d}, -{4600000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 46_quant.dat*/ - - -/*case 4700000:*/ -/* BEGIN - DIF BPF register values from 47_quant.dat*/ -{4700000, DIF_BPF_COEFF01, 0x0000ffff}, -{4700000, DIF_BPF_COEFF23, 0x0003000f}, -{4700000, DIF_BPF_COEFF45, 0x00220030}, -{4700000, DIF_BPF_COEFF67, 0x0025ffed}, -{4700000, DIF_BPF_COEFF89, 0xff87ff15}, -{4700000, DIF_BPF_COEFF1011, 0xfed6ff10}, -{4700000, DIF_BPF_COEFF1213, 0xffed014c}, -{4700000, DIF_BPF_COEFF1415, 0x02b90386}, -{4700000, DIF_BPF_COEFF1617, 0x03110119}, -{4700000, DIF_BPF_COEFF1819, 0xfdfefac4}, -{4700000, DIF_BPF_COEFF2021, 0xf8c6f92f}, -{4700000, DIF_BPF_COEFF2223, 0xfc6701b7}, -{4700000, DIF_BPF_COEFF2425, 0x07670b44}, -{4700000, DIF_BPF_COEFF2627, 0x0b7e0776}, -{4700000, DIF_BPF_COEFF2829, 0x002df807}, -{4700000, DIF_BPF_COEFF3031, 0xf200f086}, -{4700000, DIF_BPF_COEFF3233, 0xf477fcb1}, -{4700000, DIF_BPF_COEFF3435, 0x06650e1e}, -{4700000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 47_quant.dat*/ - - -/*case 4800000:*/ -/* BEGIN - DIF BPF register values from 48_quant.dat*/ -{4800000, DIF_BPF_COEFF01, 0xfffffffe}, -{4800000, DIF_BPF_COEFF23, 0xffff0009}, -{4800000, DIF_BPF_COEFF45, 0x001e0038}, -{4800000, DIF_BPF_COEFF67, 0x003f001b}, -{4800000, DIF_BPF_COEFF89, 0xffbcff36}, -{4800000, DIF_BPF_COEFF1011, 0xfec2feb6}, -{4800000, DIF_BPF_COEFF1213, 0xff5600a5}, -{4800000, DIF_BPF_COEFF1415, 0x0248038d}, -{4800000, DIF_BPF_COEFF1617, 0x03b00232}, -{4800000, DIF_BPF_COEFF1819, 0xff39fbab}, -{4800000, DIF_BPF_COEFF2021, 0xf8f4f87f}, -{4800000, DIF_BPF_COEFF2223, 0xfb060020}, -{4800000, DIF_BPF_COEFF2425, 0x062a0ad2}, -{4800000, DIF_BPF_COEFF2627, 0x0bf908a3}, -{4800000, DIF_BPF_COEFF2829, 0x0192f922}, -{4800000, DIF_BPF_COEFF3031, 0xf27df05e}, -{4800000, DIF_BPF_COEFF3233, 0xf3e8fc14}, -{4800000, DIF_BPF_COEFF3435, 0x06000e00}, -{4800000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 48_quant.dat*/ - - -/*case 4900000:*/ -/* BEGIN - DIF BPF register values from 49_quant.dat*/ -{4900000, DIF_BPF_COEFF01, 0xfffffffd}, -{4900000, DIF_BPF_COEFF23, 0xfffc0002}, -{4900000, DIF_BPF_COEFF45, 0x00160037}, -{4900000, DIF_BPF_COEFF67, 0x00510046}, -{4900000, DIF_BPF_COEFF89, 0xfff9ff6d}, -{4900000, DIF_BPF_COEFF1011, 0xfed0fe7c}, -{4900000, DIF_BPF_COEFF1213, 0xfecefff0}, -{4900000, DIF_BPF_COEFF1415, 0x01aa0356}, -{4900000, DIF_BPF_COEFF1617, 0x0413032b}, -{4900000, DIF_BPF_COEFF1819, 0x007ffcc5}, -{4900000, DIF_BPF_COEFF2021, 0xf96cf812}, -{4900000, DIF_BPF_COEFF2223, 0xf9cefe87}, -{4900000, DIF_BPF_COEFF2425, 0x04c90a2c}, -{4900000, DIF_BPF_COEFF2627, 0x0c4309b4}, -{4900000, DIF_BPF_COEFF2829, 0x02f3fa4a}, -{4900000, DIF_BPF_COEFF3031, 0xf30ef046}, -{4900000, DIF_BPF_COEFF3233, 0xf361fb7a}, -{4900000, DIF_BPF_COEFF3435, 0x059b0de0}, -{4900000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 49_quant.dat*/ - - -/*case 5000000:*/ -/* BEGIN - DIF BPF register values from 50_quant.dat*/ -{5000000, DIF_BPF_COEFF01, 0xfffffffd}, -{5000000, DIF_BPF_COEFF23, 0xfff9fffa}, -{5000000, DIF_BPF_COEFF45, 0x000a002d}, -{5000000, DIF_BPF_COEFF67, 0x00570067}, -{5000000, DIF_BPF_COEFF89, 0x0037ffb5}, -{5000000, DIF_BPF_COEFF1011, 0xfefffe68}, -{5000000, DIF_BPF_COEFF1213, 0xfe62ff3d}, -{5000000, DIF_BPF_COEFF1415, 0x00ec02e3}, -{5000000, DIF_BPF_COEFF1617, 0x043503f6}, -{5000000, DIF_BPF_COEFF1819, 0x01befe05}, -{5000000, DIF_BPF_COEFF2021, 0xfa27f7ee}, -{5000000, DIF_BPF_COEFF2223, 0xf8c6fcf8}, -{5000000, DIF_BPF_COEFF2425, 0x034c0954}, -{5000000, DIF_BPF_COEFF2627, 0x0c5c0aa4}, -{5000000, DIF_BPF_COEFF2829, 0x044cfb7e}, -{5000000, DIF_BPF_COEFF3031, 0xf3b1f03f}, -{5000000, DIF_BPF_COEFF3233, 0xf2e2fae1}, -{5000000, DIF_BPF_COEFF3435, 0x05340dc0}, -{5000000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 50_quant.dat*/ - - -/*case 5100000:*/ -/* BEGIN - DIF BPF register values from 51_quant.dat*/ -{5100000, DIF_BPF_COEFF01, 0x0000fffd}, -{5100000, DIF_BPF_COEFF23, 0xfff8fff4}, -{5100000, DIF_BPF_COEFF45, 0xfffd001e}, -{5100000, DIF_BPF_COEFF67, 0x0051007b}, -{5100000, DIF_BPF_COEFF89, 0x006e0006}, -{5100000, DIF_BPF_COEFF1011, 0xff48fe7c}, -{5100000, DIF_BPF_COEFF1213, 0xfe1bfe9a}, -{5100000, DIF_BPF_COEFF1415, 0x001d023e}, -{5100000, DIF_BPF_COEFF1617, 0x04130488}, -{5100000, DIF_BPF_COEFF1819, 0x02e6ff5b}, -{5100000, DIF_BPF_COEFF2021, 0xfb1ef812}, -{5100000, DIF_BPF_COEFF2223, 0xf7f7fb7f}, -{5100000, DIF_BPF_COEFF2425, 0x01bc084e}, -{5100000, DIF_BPF_COEFF2627, 0x0c430b72}, -{5100000, DIF_BPF_COEFF2829, 0x059afcba}, -{5100000, DIF_BPF_COEFF3031, 0xf467f046}, -{5100000, DIF_BPF_COEFF3233, 0xf26cfa4a}, -{5100000, DIF_BPF_COEFF3435, 0x04cd0da0}, -{5100000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 51_quant.dat*/ - - -/*case 5200000:*/ -/* BEGIN - DIF BPF register values from 52_quant.dat*/ -{5200000, DIF_BPF_COEFF01, 0x0000fffe}, -{5200000, DIF_BPF_COEFF23, 0xfff8ffef}, -{5200000, DIF_BPF_COEFF45, 0xfff00009}, -{5200000, DIF_BPF_COEFF67, 0x003f007f}, -{5200000, DIF_BPF_COEFF89, 0x00980056}, -{5200000, DIF_BPF_COEFF1011, 0xffa5feb6}, -{5200000, DIF_BPF_COEFF1213, 0xfe00fe15}, -{5200000, DIF_BPF_COEFF1415, 0xff4b0170}, -{5200000, DIF_BPF_COEFF1617, 0x03b004d7}, -{5200000, DIF_BPF_COEFF1819, 0x03e800b9}, -{5200000, DIF_BPF_COEFF2021, 0xfc48f87f}, -{5200000, DIF_BPF_COEFF2223, 0xf768fa23}, -{5200000, DIF_BPF_COEFF2425, 0x0022071f}, -{5200000, DIF_BPF_COEFF2627, 0x0bf90c1b}, -{5200000, DIF_BPF_COEFF2829, 0x06dafdfd}, -{5200000, DIF_BPF_COEFF3031, 0xf52df05e}, -{5200000, DIF_BPF_COEFF3233, 0xf1fef9b5}, -{5200000, DIF_BPF_COEFF3435, 0x04640d7f}, -{5200000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 52_quant.dat*/ - - -/*case 5300000:*/ -/* BEGIN - DIF BPF register values from 53_quant.dat*/ -{5300000, DIF_BPF_COEFF01, 0x0000ffff}, -{5300000, DIF_BPF_COEFF23, 0xfff9ffee}, -{5300000, DIF_BPF_COEFF45, 0xffe6fff3}, -{5300000, DIF_BPF_COEFF67, 0x00250072}, -{5300000, DIF_BPF_COEFF89, 0x00af009c}, -{5300000, DIF_BPF_COEFF1011, 0x000cff10}, -{5300000, DIF_BPF_COEFF1213, 0xfe13fdb8}, -{5300000, DIF_BPF_COEFF1415, 0xfe870089}, -{5300000, DIF_BPF_COEFF1617, 0x031104e1}, -{5300000, DIF_BPF_COEFF1819, 0x04b8020f}, -{5300000, DIF_BPF_COEFF2021, 0xfd98f92f}, -{5300000, DIF_BPF_COEFF2223, 0xf71df8f0}, -{5300000, DIF_BPF_COEFF2425, 0xfe8805ce}, -{5300000, DIF_BPF_COEFF2627, 0x0b7e0c9c}, -{5300000, DIF_BPF_COEFF2829, 0x0808ff44}, -{5300000, DIF_BPF_COEFF3031, 0xf603f086}, -{5300000, DIF_BPF_COEFF3233, 0xf19af922}, -{5300000, DIF_BPF_COEFF3435, 0x03fb0d5e}, -{5300000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 53_quant.dat*/ - - -/*case 5400000:*/ -/* BEGIN - DIF BPF register values from 54_quant.dat*/ -{5400000, DIF_BPF_COEFF01, 0x00000001}, -{5400000, DIF_BPF_COEFF23, 0xfffcffef}, -{5400000, DIF_BPF_COEFF45, 0xffe0ffe0}, -{5400000, DIF_BPF_COEFF67, 0x00050056}, -{5400000, DIF_BPF_COEFF89, 0x00b000d1}, -{5400000, DIF_BPF_COEFF1011, 0x0071ff82}, -{5400000, DIF_BPF_COEFF1213, 0xfe53fd8c}, -{5400000, DIF_BPF_COEFF1415, 0xfddfff99}, -{5400000, DIF_BPF_COEFF1617, 0x024104a3}, -{5400000, DIF_BPF_COEFF1819, 0x054a034d}, -{5400000, DIF_BPF_COEFF2021, 0xff01fa1e}, -{5400000, DIF_BPF_COEFF2223, 0xf717f7ed}, -{5400000, DIF_BPF_COEFF2425, 0xfcf50461}, -{5400000, DIF_BPF_COEFF2627, 0x0ad50cf4}, -{5400000, DIF_BPF_COEFF2829, 0x0921008d}, -{5400000, DIF_BPF_COEFF3031, 0xf6e7f0bd}, -{5400000, DIF_BPF_COEFF3233, 0xf13ff891}, -{5400000, DIF_BPF_COEFF3435, 0x03920d3b}, -{5400000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 54_quant.dat*/ - - -/*case 5500000:*/ -/* BEGIN - DIF BPF register values from 55_quant.dat*/ -{5500000, DIF_BPF_COEFF01, 0x00010002}, -{5500000, DIF_BPF_COEFF23, 0xfffffff3}, -{5500000, DIF_BPF_COEFF45, 0xffdeffd1}, -{5500000, DIF_BPF_COEFF67, 0xffe5002f}, -{5500000, DIF_BPF_COEFF89, 0x009c00ed}, -{5500000, DIF_BPF_COEFF1011, 0x00cb0000}, -{5500000, DIF_BPF_COEFF1213, 0xfebafd94}, -{5500000, DIF_BPF_COEFF1415, 0xfd61feb0}, -{5500000, DIF_BPF_COEFF1617, 0x014d0422}, -{5500000, DIF_BPF_COEFF1819, 0x05970464}, -{5500000, DIF_BPF_COEFF2021, 0x0074fb41}, -{5500000, DIF_BPF_COEFF2223, 0xf759f721}, -{5500000, DIF_BPF_COEFF2425, 0xfb7502de}, -{5500000, DIF_BPF_COEFF2627, 0x0a000d21}, -{5500000, DIF_BPF_COEFF2829, 0x0a2201d4}, -{5500000, DIF_BPF_COEFF3031, 0xf7d9f104}, -{5500000, DIF_BPF_COEFF3233, 0xf0edf804}, -{5500000, DIF_BPF_COEFF3435, 0x03280d19}, -{5500000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 55_quant.dat*/ - - -/*case 5600000:*/ -/* BEGIN - DIF BPF register values from 56_quant.dat*/ -{5600000, DIF_BPF_COEFF01, 0x00010003}, -{5600000, DIF_BPF_COEFF23, 0x0003fffa}, -{5600000, DIF_BPF_COEFF45, 0xffe3ffc9}, -{5600000, DIF_BPF_COEFF67, 0xffc90002}, -{5600000, DIF_BPF_COEFF89, 0x007500ef}, -{5600000, DIF_BPF_COEFF1011, 0x010e007e}, -{5600000, DIF_BPF_COEFF1213, 0xff3dfdcf}, -{5600000, DIF_BPF_COEFF1415, 0xfd16fddd}, -{5600000, DIF_BPF_COEFF1617, 0x00440365}, -{5600000, DIF_BPF_COEFF1819, 0x059b0548}, -{5600000, DIF_BPF_COEFF2021, 0x01e3fc90}, -{5600000, DIF_BPF_COEFF2223, 0xf7dff691}, -{5600000, DIF_BPF_COEFF2425, 0xfa0f014d}, -{5600000, DIF_BPF_COEFF2627, 0x09020d23}, -{5600000, DIF_BPF_COEFF2829, 0x0b0a0318}, -{5600000, DIF_BPF_COEFF3031, 0xf8d7f15a}, -{5600000, DIF_BPF_COEFF3233, 0xf0a5f779}, -{5600000, DIF_BPF_COEFF3435, 0x02bd0cf6}, -{5600000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 56_quant.dat*/ - - -/*case 5700000:*/ -/* BEGIN - DIF BPF register values from 57_quant.dat*/ -{5700000, DIF_BPF_COEFF01, 0x00010003}, -{5700000, DIF_BPF_COEFF23, 0x00060001}, -{5700000, DIF_BPF_COEFF45, 0xffecffc9}, -{5700000, DIF_BPF_COEFF67, 0xffb4ffd4}, -{5700000, DIF_BPF_COEFF89, 0x004000d5}, -{5700000, DIF_BPF_COEFF1011, 0x013600f0}, -{5700000, DIF_BPF_COEFF1213, 0xffd3fe39}, -{5700000, DIF_BPF_COEFF1415, 0xfd04fd31}, -{5700000, DIF_BPF_COEFF1617, 0xff360277}, -{5700000, DIF_BPF_COEFF1819, 0x055605ef}, -{5700000, DIF_BPF_COEFF2021, 0x033efdfe}, -{5700000, DIF_BPF_COEFF2223, 0xf8a5f642}, -{5700000, DIF_BPF_COEFF2425, 0xf8cbffb6}, -{5700000, DIF_BPF_COEFF2627, 0x07e10cfb}, -{5700000, DIF_BPF_COEFF2829, 0x0bd50456}, -{5700000, DIF_BPF_COEFF3031, 0xf9dff1be}, -{5700000, DIF_BPF_COEFF3233, 0xf067f6f2}, -{5700000, DIF_BPF_COEFF3435, 0x02520cd2}, -{5700000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 57_quant.dat*/ - - -/*case 5800000:*/ -/* BEGIN - DIF BPF register values from 58_quant.dat*/ -{5800000, DIF_BPF_COEFF01, 0x00000003}, -{5800000, DIF_BPF_COEFF23, 0x00080009}, -{5800000, DIF_BPF_COEFF45, 0xfff8ffd2}, -{5800000, DIF_BPF_COEFF67, 0xffaaffac}, -{5800000, DIF_BPF_COEFF89, 0x000200a3}, -{5800000, DIF_BPF_COEFF1011, 0x013c014a}, -{5800000, DIF_BPF_COEFF1213, 0x006dfec9}, -{5800000, DIF_BPF_COEFF1415, 0xfd2bfcb7}, -{5800000, DIF_BPF_COEFF1617, 0xfe350165}, -{5800000, DIF_BPF_COEFF1819, 0x04cb0651}, -{5800000, DIF_BPF_COEFF2021, 0x0477ff7e}, -{5800000, DIF_BPF_COEFF2223, 0xf9a5f635}, -{5800000, DIF_BPF_COEFF2425, 0xf7b1fe20}, -{5800000, DIF_BPF_COEFF2627, 0x069f0ca8}, -{5800000, DIF_BPF_COEFF2829, 0x0c81058b}, -{5800000, DIF_BPF_COEFF3031, 0xfaf0f231}, -{5800000, DIF_BPF_COEFF3233, 0xf033f66d}, -{5800000, DIF_BPF_COEFF3435, 0x01e60cae}, -{5800000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 58_quant.dat*/ - - -/*case 5900000:*/ -/* BEGIN - DIF BPF register values from 59_quant.dat*/ -{5900000, DIF_BPF_COEFF01, 0x00000002}, -{5900000, DIF_BPF_COEFF23, 0x0009000e}, -{5900000, DIF_BPF_COEFF45, 0x0005ffe1}, -{5900000, DIF_BPF_COEFF67, 0xffacff90}, -{5900000, DIF_BPF_COEFF89, 0xffc5005f}, -{5900000, DIF_BPF_COEFF1011, 0x01210184}, -{5900000, DIF_BPF_COEFF1213, 0x00fcff72}, -{5900000, DIF_BPF_COEFF1415, 0xfd8afc77}, -{5900000, DIF_BPF_COEFF1617, 0xfd51003f}, -{5900000, DIF_BPF_COEFF1819, 0x04020669}, -{5900000, DIF_BPF_COEFF2021, 0x05830103}, -{5900000, DIF_BPF_COEFF2223, 0xfad7f66b}, -{5900000, DIF_BPF_COEFF2425, 0xf6c8fc93}, -{5900000, DIF_BPF_COEFF2627, 0x05430c2b}, -{5900000, DIF_BPF_COEFF2829, 0x0d0d06b5}, -{5900000, DIF_BPF_COEFF3031, 0xfc08f2b2}, -{5900000, DIF_BPF_COEFF3233, 0xf00af5ec}, -{5900000, DIF_BPF_COEFF3435, 0x017b0c89}, -{5900000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 59_quant.dat*/ - - -/*case 6000000:*/ -/* BEGIN - DIF BPF register values from 60_quant.dat*/ -{6000000, DIF_BPF_COEFF01, 0x00000001}, -{6000000, DIF_BPF_COEFF23, 0x00070012}, -{6000000, DIF_BPF_COEFF45, 0x0012fff5}, -{6000000, DIF_BPF_COEFF67, 0xffbaff82}, -{6000000, DIF_BPF_COEFF89, 0xff8e000f}, -{6000000, DIF_BPF_COEFF1011, 0x00e80198}, -{6000000, DIF_BPF_COEFF1213, 0x01750028}, -{6000000, DIF_BPF_COEFF1415, 0xfe18fc75}, -{6000000, DIF_BPF_COEFF1617, 0xfc99ff15}, -{6000000, DIF_BPF_COEFF1819, 0x03050636}, -{6000000, DIF_BPF_COEFF2021, 0x0656027f}, -{6000000, DIF_BPF_COEFF2223, 0xfc32f6e2}, -{6000000, DIF_BPF_COEFF2425, 0xf614fb17}, -{6000000, DIF_BPF_COEFF2627, 0x03d20b87}, -{6000000, DIF_BPF_COEFF2829, 0x0d7707d2}, -{6000000, DIF_BPF_COEFF3031, 0xfd26f341}, -{6000000, DIF_BPF_COEFF3233, 0xefeaf56f}, -{6000000, DIF_BPF_COEFF3435, 0x010f0c64}, -{6000000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 60_quant.dat*/ - - -/*case 6100000:*/ -/* BEGIN - DIF BPF register values from 61_quant.dat*/ -{6100000, DIF_BPF_COEFF01, 0xffff0000}, -{6100000, DIF_BPF_COEFF23, 0x00050012}, -{6100000, DIF_BPF_COEFF45, 0x001c000b}, -{6100000, DIF_BPF_COEFF67, 0xffd1ff84}, -{6100000, DIF_BPF_COEFF89, 0xff66ffbe}, -{6100000, DIF_BPF_COEFF1011, 0x00960184}, -{6100000, DIF_BPF_COEFF1213, 0x01cd00da}, -{6100000, DIF_BPF_COEFF1415, 0xfeccfcb2}, -{6100000, DIF_BPF_COEFF1617, 0xfc17fdf9}, -{6100000, DIF_BPF_COEFF1819, 0x01e005bc}, -{6100000, DIF_BPF_COEFF2021, 0x06e703e4}, -{6100000, DIF_BPF_COEFF2223, 0xfdabf798}, -{6100000, DIF_BPF_COEFF2425, 0xf599f9b3}, -{6100000, DIF_BPF_COEFF2627, 0x02510abd}, -{6100000, DIF_BPF_COEFF2829, 0x0dbf08df}, -{6100000, DIF_BPF_COEFF3031, 0xfe48f3dc}, -{6100000, DIF_BPF_COEFF3233, 0xefd5f4f6}, -{6100000, DIF_BPF_COEFF3435, 0x00a20c3e}, -{6100000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 61_quant.dat*/ - - -/*case 6200000:*/ -/* BEGIN - DIF BPF register values from 62_quant.dat*/ -{6200000, DIF_BPF_COEFF01, 0xfffffffe}, -{6200000, DIF_BPF_COEFF23, 0x0002000f}, -{6200000, DIF_BPF_COEFF45, 0x0021001f}, -{6200000, DIF_BPF_COEFF67, 0xfff0ff97}, -{6200000, DIF_BPF_COEFF89, 0xff50ff74}, -{6200000, DIF_BPF_COEFF1011, 0x0034014a}, -{6200000, DIF_BPF_COEFF1213, 0x01fa0179}, -{6200000, DIF_BPF_COEFF1415, 0xff97fd2a}, -{6200000, DIF_BPF_COEFF1617, 0xfbd3fcfa}, -{6200000, DIF_BPF_COEFF1819, 0x00a304fe}, -{6200000, DIF_BPF_COEFF2021, 0x07310525}, -{6200000, DIF_BPF_COEFF2223, 0xff37f886}, -{6200000, DIF_BPF_COEFF2425, 0xf55cf86e}, -{6200000, DIF_BPF_COEFF2627, 0x00c709d0}, -{6200000, DIF_BPF_COEFF2829, 0x0de209db}, -{6200000, DIF_BPF_COEFF3031, 0xff6df484}, -{6200000, DIF_BPF_COEFF3233, 0xefcbf481}, -{6200000, DIF_BPF_COEFF3435, 0x00360c18}, -{6200000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 62_quant.dat*/ - - -/*case 6300000:*/ -/* BEGIN - DIF BPF register values from 63_quant.dat*/ -{6300000, DIF_BPF_COEFF01, 0xfffffffd}, -{6300000, DIF_BPF_COEFF23, 0xfffe000a}, -{6300000, DIF_BPF_COEFF45, 0x0021002f}, -{6300000, DIF_BPF_COEFF67, 0x0010ffb8}, -{6300000, DIF_BPF_COEFF89, 0xff50ff3b}, -{6300000, DIF_BPF_COEFF1011, 0xffcc00f0}, -{6300000, DIF_BPF_COEFF1213, 0x01fa01fa}, -{6300000, DIF_BPF_COEFF1415, 0x0069fdd4}, -{6300000, DIF_BPF_COEFF1617, 0xfbd3fc26}, -{6300000, DIF_BPF_COEFF1819, 0xff5d0407}, -{6300000, DIF_BPF_COEFF2021, 0x07310638}, -{6300000, DIF_BPF_COEFF2223, 0x00c9f9a8}, -{6300000, DIF_BPF_COEFF2425, 0xf55cf74e}, -{6300000, DIF_BPF_COEFF2627, 0xff3908c3}, -{6300000, DIF_BPF_COEFF2829, 0x0de20ac3}, -{6300000, DIF_BPF_COEFF3031, 0x0093f537}, -{6300000, DIF_BPF_COEFF3233, 0xefcbf410}, -{6300000, DIF_BPF_COEFF3435, 0xffca0bf2}, -{6300000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 63_quant.dat*/ - - -/*case 6400000:*/ -/* BEGIN - DIF BPF register values from 64_quant.dat*/ -{6400000, DIF_BPF_COEFF01, 0xfffffffd}, -{6400000, DIF_BPF_COEFF23, 0xfffb0003}, -{6400000, DIF_BPF_COEFF45, 0x001c0037}, -{6400000, DIF_BPF_COEFF67, 0x002fffe2}, -{6400000, DIF_BPF_COEFF89, 0xff66ff17}, -{6400000, DIF_BPF_COEFF1011, 0xff6a007e}, -{6400000, DIF_BPF_COEFF1213, 0x01cd0251}, -{6400000, DIF_BPF_COEFF1415, 0x0134fea5}, -{6400000, DIF_BPF_COEFF1617, 0xfc17fb8b}, -{6400000, DIF_BPF_COEFF1819, 0xfe2002e0}, -{6400000, DIF_BPF_COEFF2021, 0x06e70713}, -{6400000, DIF_BPF_COEFF2223, 0x0255faf5}, -{6400000, DIF_BPF_COEFF2425, 0xf599f658}, -{6400000, DIF_BPF_COEFF2627, 0xfdaf0799}, -{6400000, DIF_BPF_COEFF2829, 0x0dbf0b96}, -{6400000, DIF_BPF_COEFF3031, 0x01b8f5f5}, -{6400000, DIF_BPF_COEFF3233, 0xefd5f3a3}, -{6400000, DIF_BPF_COEFF3435, 0xff5e0bca}, -{6400000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 64_quant.dat*/ - - -/*case 6500000:*/ -/* BEGIN - DIF BPF register values from 65_quant.dat*/ -{6500000, DIF_BPF_COEFF01, 0x0000fffd}, -{6500000, DIF_BPF_COEFF23, 0xfff9fffb}, -{6500000, DIF_BPF_COEFF45, 0x00120037}, -{6500000, DIF_BPF_COEFF67, 0x00460010}, -{6500000, DIF_BPF_COEFF89, 0xff8eff0f}, -{6500000, DIF_BPF_COEFF1011, 0xff180000}, -{6500000, DIF_BPF_COEFF1213, 0x01750276}, -{6500000, DIF_BPF_COEFF1415, 0x01e8ff8d}, -{6500000, DIF_BPF_COEFF1617, 0xfc99fb31}, -{6500000, DIF_BPF_COEFF1819, 0xfcfb0198}, -{6500000, DIF_BPF_COEFF2021, 0x065607ad}, -{6500000, DIF_BPF_COEFF2223, 0x03cefc64}, -{6500000, DIF_BPF_COEFF2425, 0xf614f592}, -{6500000, DIF_BPF_COEFF2627, 0xfc2e0656}, -{6500000, DIF_BPF_COEFF2829, 0x0d770c52}, -{6500000, DIF_BPF_COEFF3031, 0x02daf6bd}, -{6500000, DIF_BPF_COEFF3233, 0xefeaf33b}, -{6500000, DIF_BPF_COEFF3435, 0xfef10ba3}, -{6500000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 65_quant.dat*/ - - -/*case 6600000:*/ -/* BEGIN - DIF BPF register values from 66_quant.dat*/ -{6600000, DIF_BPF_COEFF01, 0x0000fffe}, -{6600000, DIF_BPF_COEFF23, 0xfff7fff5}, -{6600000, DIF_BPF_COEFF45, 0x0005002f}, -{6600000, DIF_BPF_COEFF67, 0x0054003c}, -{6600000, DIF_BPF_COEFF89, 0xffc5ff22}, -{6600000, DIF_BPF_COEFF1011, 0xfedfff82}, -{6600000, DIF_BPF_COEFF1213, 0x00fc0267}, -{6600000, DIF_BPF_COEFF1415, 0x0276007e}, -{6600000, DIF_BPF_COEFF1617, 0xfd51fb1c}, -{6600000, DIF_BPF_COEFF1819, 0xfbfe003e}, -{6600000, DIF_BPF_COEFF2021, 0x05830802}, -{6600000, DIF_BPF_COEFF2223, 0x0529fdec}, -{6600000, DIF_BPF_COEFF2425, 0xf6c8f4fe}, -{6600000, DIF_BPF_COEFF2627, 0xfabd04ff}, -{6600000, DIF_BPF_COEFF2829, 0x0d0d0cf6}, -{6600000, DIF_BPF_COEFF3031, 0x03f8f78f}, -{6600000, DIF_BPF_COEFF3233, 0xf00af2d7}, -{6600000, DIF_BPF_COEFF3435, 0xfe850b7b}, -{6600000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 66_quant.dat*/ - - -/*case 6700000:*/ -/* BEGIN - DIF BPF register values from 67_quant.dat*/ -{6700000, DIF_BPF_COEFF01, 0x0000ffff}, -{6700000, DIF_BPF_COEFF23, 0xfff8fff0}, -{6700000, DIF_BPF_COEFF45, 0xfff80020}, -{6700000, DIF_BPF_COEFF67, 0x00560060}, -{6700000, DIF_BPF_COEFF89, 0x0002ff4e}, -{6700000, DIF_BPF_COEFF1011, 0xfec4ff10}, -{6700000, DIF_BPF_COEFF1213, 0x006d0225}, -{6700000, DIF_BPF_COEFF1415, 0x02d50166}, -{6700000, DIF_BPF_COEFF1617, 0xfe35fb4e}, -{6700000, DIF_BPF_COEFF1819, 0xfb35fee1}, -{6700000, DIF_BPF_COEFF2021, 0x0477080e}, -{6700000, DIF_BPF_COEFF2223, 0x065bff82}, -{6700000, DIF_BPF_COEFF2425, 0xf7b1f4a0}, -{6700000, DIF_BPF_COEFF2627, 0xf9610397}, -{6700000, DIF_BPF_COEFF2829, 0x0c810d80}, -{6700000, DIF_BPF_COEFF3031, 0x0510f869}, -{6700000, DIF_BPF_COEFF3233, 0xf033f278}, -{6700000, DIF_BPF_COEFF3435, 0xfe1a0b52}, -{6700000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 67_quant.dat*/ - - -/*case 6800000:*/ -/* BEGIN - DIF BPF register values from 68_quant.dat*/ -{6800000, DIF_BPF_COEFF01, 0x00010000}, -{6800000, DIF_BPF_COEFF23, 0xfffaffee}, -{6800000, DIF_BPF_COEFF45, 0xffec000c}, -{6800000, DIF_BPF_COEFF67, 0x004c0078}, -{6800000, DIF_BPF_COEFF89, 0x0040ff8e}, -{6800000, DIF_BPF_COEFF1011, 0xfecafeb6}, -{6800000, DIF_BPF_COEFF1213, 0xffd301b6}, -{6800000, DIF_BPF_COEFF1415, 0x02fc0235}, -{6800000, DIF_BPF_COEFF1617, 0xff36fbc5}, -{6800000, DIF_BPF_COEFF1819, 0xfaaafd90}, -{6800000, DIF_BPF_COEFF2021, 0x033e07d2}, -{6800000, DIF_BPF_COEFF2223, 0x075b011b}, -{6800000, DIF_BPF_COEFF2425, 0xf8cbf47a}, -{6800000, DIF_BPF_COEFF2627, 0xf81f0224}, -{6800000, DIF_BPF_COEFF2829, 0x0bd50def}, -{6800000, DIF_BPF_COEFF3031, 0x0621f94b}, -{6800000, DIF_BPF_COEFF3233, 0xf067f21e}, -{6800000, DIF_BPF_COEFF3435, 0xfdae0b29}, -{6800000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 68_quant.dat*/ - - -/*case 6900000:*/ -/* BEGIN - DIF BPF register values from 69_quant.dat*/ -{6900000, DIF_BPF_COEFF01, 0x00010001}, -{6900000, DIF_BPF_COEFF23, 0xfffdffef}, -{6900000, DIF_BPF_COEFF45, 0xffe3fff6}, -{6900000, DIF_BPF_COEFF67, 0x0037007f}, -{6900000, DIF_BPF_COEFF89, 0x0075ffdc}, -{6900000, DIF_BPF_COEFF1011, 0xfef2fe7c}, -{6900000, DIF_BPF_COEFF1213, 0xff3d0122}, -{6900000, DIF_BPF_COEFF1415, 0x02ea02dd}, -{6900000, DIF_BPF_COEFF1617, 0x0044fc79}, -{6900000, DIF_BPF_COEFF1819, 0xfa65fc5d}, -{6900000, DIF_BPF_COEFF2021, 0x01e3074e}, -{6900000, DIF_BPF_COEFF2223, 0x082102ad}, -{6900000, DIF_BPF_COEFF2425, 0xfa0ff48c}, -{6900000, DIF_BPF_COEFF2627, 0xf6fe00a9}, -{6900000, DIF_BPF_COEFF2829, 0x0b0a0e43}, -{6900000, DIF_BPF_COEFF3031, 0x0729fa33}, -{6900000, DIF_BPF_COEFF3233, 0xf0a5f1c9}, -{6900000, DIF_BPF_COEFF3435, 0xfd430b00}, -{6900000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 69_quant.dat*/ - - -/*case 7000000:*/ -/* BEGIN - DIF BPF register values from 70_quant.dat*/ -{7000000, DIF_BPF_COEFF01, 0x00010002}, -{7000000, DIF_BPF_COEFF23, 0x0001fff3}, -{7000000, DIF_BPF_COEFF45, 0xffdeffe2}, -{7000000, DIF_BPF_COEFF67, 0x001b0076}, -{7000000, DIF_BPF_COEFF89, 0x009c002d}, -{7000000, DIF_BPF_COEFF1011, 0xff35fe68}, -{7000000, DIF_BPF_COEFF1213, 0xfeba0076}, -{7000000, DIF_BPF_COEFF1415, 0x029f0352}, -{7000000, DIF_BPF_COEFF1617, 0x014dfd60}, -{7000000, DIF_BPF_COEFF1819, 0xfa69fb53}, -{7000000, DIF_BPF_COEFF2021, 0x00740688}, -{7000000, DIF_BPF_COEFF2223, 0x08a7042d}, -{7000000, DIF_BPF_COEFF2425, 0xfb75f4d6}, -{7000000, DIF_BPF_COEFF2627, 0xf600ff2d}, -{7000000, DIF_BPF_COEFF2829, 0x0a220e7a}, -{7000000, DIF_BPF_COEFF3031, 0x0827fb22}, -{7000000, DIF_BPF_COEFF3233, 0xf0edf17a}, -{7000000, DIF_BPF_COEFF3435, 0xfcd80ad6}, -{7000000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 70_quant.dat*/ - - -/*case 7100000:*/ -/* BEGIN - DIF BPF register values from 71_quant.dat*/ -{7100000, DIF_BPF_COEFF01, 0x00000003}, -{7100000, DIF_BPF_COEFF23, 0x0004fff9}, -{7100000, DIF_BPF_COEFF45, 0xffe0ffd2}, -{7100000, DIF_BPF_COEFF67, 0xfffb005e}, -{7100000, DIF_BPF_COEFF89, 0x00b0007a}, -{7100000, DIF_BPF_COEFF1011, 0xff8ffe7c}, -{7100000, DIF_BPF_COEFF1213, 0xfe53ffc1}, -{7100000, DIF_BPF_COEFF1415, 0x0221038c}, -{7100000, DIF_BPF_COEFF1617, 0x0241fe6e}, -{7100000, DIF_BPF_COEFF1819, 0xfab6fa80}, -{7100000, DIF_BPF_COEFF2021, 0xff010587}, -{7100000, DIF_BPF_COEFF2223, 0x08e90590}, -{7100000, DIF_BPF_COEFF2425, 0xfcf5f556}, -{7100000, DIF_BPF_COEFF2627, 0xf52bfdb3}, -{7100000, DIF_BPF_COEFF2829, 0x09210e95}, -{7100000, DIF_BPF_COEFF3031, 0x0919fc15}, -{7100000, DIF_BPF_COEFF3233, 0xf13ff12f}, -{7100000, DIF_BPF_COEFF3435, 0xfc6e0aab}, -{7100000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 71_quant.dat*/ - - -/*case 7200000:*/ -/* BEGIN - DIF BPF register values from 72_quant.dat*/ -{7200000, DIF_BPF_COEFF01, 0x00000003}, -{7200000, DIF_BPF_COEFF23, 0x00070000}, -{7200000, DIF_BPF_COEFF45, 0xffe6ffc9}, -{7200000, DIF_BPF_COEFF67, 0xffdb0039}, -{7200000, DIF_BPF_COEFF89, 0x00af00b8}, -{7200000, DIF_BPF_COEFF1011, 0xfff4feb6}, -{7200000, DIF_BPF_COEFF1213, 0xfe13ff10}, -{7200000, DIF_BPF_COEFF1415, 0x01790388}, -{7200000, DIF_BPF_COEFF1617, 0x0311ff92}, -{7200000, DIF_BPF_COEFF1819, 0xfb48f9ed}, -{7200000, DIF_BPF_COEFF2021, 0xfd980453}, -{7200000, DIF_BPF_COEFF2223, 0x08e306cd}, -{7200000, DIF_BPF_COEFF2425, 0xfe88f60a}, -{7200000, DIF_BPF_COEFF2627, 0xf482fc40}, -{7200000, DIF_BPF_COEFF2829, 0x08080e93}, -{7200000, DIF_BPF_COEFF3031, 0x09fdfd0c}, -{7200000, DIF_BPF_COEFF3233, 0xf19af0ea}, -{7200000, DIF_BPF_COEFF3435, 0xfc050a81}, -{7200000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 72_quant.dat*/ - - -/*case 7300000:*/ -/* BEGIN - DIF BPF register values from 73_quant.dat*/ -{7300000, DIF_BPF_COEFF01, 0x00000002}, -{7300000, DIF_BPF_COEFF23, 0x00080008}, -{7300000, DIF_BPF_COEFF45, 0xfff0ffc9}, -{7300000, DIF_BPF_COEFF67, 0xffc1000d}, -{7300000, DIF_BPF_COEFF89, 0x009800e2}, -{7300000, DIF_BPF_COEFF1011, 0x005bff10}, -{7300000, DIF_BPF_COEFF1213, 0xfe00fe74}, -{7300000, DIF_BPF_COEFF1415, 0x00b50345}, -{7300000, DIF_BPF_COEFF1617, 0x03b000bc}, -{7300000, DIF_BPF_COEFF1819, 0xfc18f9a1}, -{7300000, DIF_BPF_COEFF2021, 0xfc4802f9}, -{7300000, DIF_BPF_COEFF2223, 0x089807dc}, -{7300000, DIF_BPF_COEFF2425, 0x0022f6f0}, -{7300000, DIF_BPF_COEFF2627, 0xf407fada}, -{7300000, DIF_BPF_COEFF2829, 0x06da0e74}, -{7300000, DIF_BPF_COEFF3031, 0x0ad3fe06}, -{7300000, DIF_BPF_COEFF3233, 0xf1fef0ab}, -{7300000, DIF_BPF_COEFF3435, 0xfb9c0a55}, -{7300000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 73_quant.dat*/ - - -/*case 7400000:*/ -/* BEGIN - DIF BPF register values from 74_quant.dat*/ -{7400000, DIF_BPF_COEFF01, 0x00000001}, -{7400000, DIF_BPF_COEFF23, 0x0008000e}, -{7400000, DIF_BPF_COEFF45, 0xfffdffd0}, -{7400000, DIF_BPF_COEFF67, 0xffafffdf}, -{7400000, DIF_BPF_COEFF89, 0x006e00f2}, -{7400000, DIF_BPF_COEFF1011, 0x00b8ff82}, -{7400000, DIF_BPF_COEFF1213, 0xfe1bfdf8}, -{7400000, DIF_BPF_COEFF1415, 0xffe302c8}, -{7400000, DIF_BPF_COEFF1617, 0x041301dc}, -{7400000, DIF_BPF_COEFF1819, 0xfd1af99e}, -{7400000, DIF_BPF_COEFF2021, 0xfb1e0183}, -{7400000, DIF_BPF_COEFF2223, 0x080908b5}, -{7400000, DIF_BPF_COEFF2425, 0x01bcf801}, -{7400000, DIF_BPF_COEFF2627, 0xf3bdf985}, -{7400000, DIF_BPF_COEFF2829, 0x059a0e38}, -{7400000, DIF_BPF_COEFF3031, 0x0b99ff03}, -{7400000, DIF_BPF_COEFF3233, 0xf26cf071}, -{7400000, DIF_BPF_COEFF3435, 0xfb330a2a}, -{7400000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 74_quant.dat*/ - - -/*case 7500000:*/ -/* BEGIN - DIF BPF register values from 75_quant.dat*/ -{7500000, DIF_BPF_COEFF01, 0xffff0000}, -{7500000, DIF_BPF_COEFF23, 0x00070011}, -{7500000, DIF_BPF_COEFF45, 0x000affdf}, -{7500000, DIF_BPF_COEFF67, 0xffa9ffb5}, -{7500000, DIF_BPF_COEFF89, 0x003700e6}, -{7500000, DIF_BPF_COEFF1011, 0x01010000}, -{7500000, DIF_BPF_COEFF1213, 0xfe62fda8}, -{7500000, DIF_BPF_COEFF1415, 0xff140219}, -{7500000, DIF_BPF_COEFF1617, 0x043502e1}, -{7500000, DIF_BPF_COEFF1819, 0xfe42f9e6}, -{7500000, DIF_BPF_COEFF2021, 0xfa270000}, -{7500000, DIF_BPF_COEFF2223, 0x073a0953}, -{7500000, DIF_BPF_COEFF2425, 0x034cf939}, -{7500000, DIF_BPF_COEFF2627, 0xf3a4f845}, -{7500000, DIF_BPF_COEFF2829, 0x044c0de1}, -{7500000, DIF_BPF_COEFF3031, 0x0c4f0000}, -{7500000, DIF_BPF_COEFF3233, 0xf2e2f03c}, -{7500000, DIF_BPF_COEFF3435, 0xfacc09fe}, -{7500000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 75_quant.dat*/ - - -/*case 7600000:*/ -/* BEGIN - DIF BPF register values from 76_quant.dat*/ -{7600000, DIF_BPF_COEFF01, 0xffffffff}, -{7600000, DIF_BPF_COEFF23, 0x00040012}, -{7600000, DIF_BPF_COEFF45, 0x0016fff3}, -{7600000, DIF_BPF_COEFF67, 0xffafff95}, -{7600000, DIF_BPF_COEFF89, 0xfff900c0}, -{7600000, DIF_BPF_COEFF1011, 0x0130007e}, -{7600000, DIF_BPF_COEFF1213, 0xfecefd89}, -{7600000, DIF_BPF_COEFF1415, 0xfe560146}, -{7600000, DIF_BPF_COEFF1617, 0x041303bc}, -{7600000, DIF_BPF_COEFF1819, 0xff81fa76}, -{7600000, DIF_BPF_COEFF2021, 0xf96cfe7d}, -{7600000, DIF_BPF_COEFF2223, 0x063209b1}, -{7600000, DIF_BPF_COEFF2425, 0x04c9fa93}, -{7600000, DIF_BPF_COEFF2627, 0xf3bdf71e}, -{7600000, DIF_BPF_COEFF2829, 0x02f30d6e}, -{7600000, DIF_BPF_COEFF3031, 0x0cf200fd}, -{7600000, DIF_BPF_COEFF3233, 0xf361f00e}, -{7600000, DIF_BPF_COEFF3435, 0xfa6509d1}, -{7600000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 76_quant.dat*/ - - -/*case 7700000:*/ -/* BEGIN - DIF BPF register values from 77_quant.dat*/ -{7700000, DIF_BPF_COEFF01, 0xfffffffe}, -{7700000, DIF_BPF_COEFF23, 0x00010010}, -{7700000, DIF_BPF_COEFF45, 0x001e0008}, -{7700000, DIF_BPF_COEFF67, 0xffc1ff84}, -{7700000, DIF_BPF_COEFF89, 0xffbc0084}, -{7700000, DIF_BPF_COEFF1011, 0x013e00f0}, -{7700000, DIF_BPF_COEFF1213, 0xff56fd9f}, -{7700000, DIF_BPF_COEFF1415, 0xfdb8005c}, -{7700000, DIF_BPF_COEFF1617, 0x03b00460}, -{7700000, DIF_BPF_COEFF1819, 0x00c7fb45}, -{7700000, DIF_BPF_COEFF2021, 0xf8f4fd07}, -{7700000, DIF_BPF_COEFF2223, 0x04fa09ce}, -{7700000, DIF_BPF_COEFF2425, 0x062afc07}, -{7700000, DIF_BPF_COEFF2627, 0xf407f614}, -{7700000, DIF_BPF_COEFF2829, 0x01920ce0}, -{7700000, DIF_BPF_COEFF3031, 0x0d8301fa}, -{7700000, DIF_BPF_COEFF3233, 0xf3e8efe5}, -{7700000, DIF_BPF_COEFF3435, 0xfa0009a4}, -{7700000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 77_quant.dat*/ - - -/*case 7800000:*/ -/* BEGIN - DIF BPF register values from 78_quant.dat*/ -{7800000, DIF_BPF_COEFF01, 0x0000fffd}, -{7800000, DIF_BPF_COEFF23, 0xfffd000b}, -{7800000, DIF_BPF_COEFF45, 0x0022001d}, -{7800000, DIF_BPF_COEFF67, 0xffdbff82}, -{7800000, DIF_BPF_COEFF89, 0xff870039}, -{7800000, DIF_BPF_COEFF1011, 0x012a014a}, -{7800000, DIF_BPF_COEFF1213, 0xffedfde7}, -{7800000, DIF_BPF_COEFF1415, 0xfd47ff6b}, -{7800000, DIF_BPF_COEFF1617, 0x031104c6}, -{7800000, DIF_BPF_COEFF1819, 0x0202fc4c}, -{7800000, DIF_BPF_COEFF2021, 0xf8c6fbad}, -{7800000, DIF_BPF_COEFF2223, 0x039909a7}, -{7800000, DIF_BPF_COEFF2425, 0x0767fd8e}, -{7800000, DIF_BPF_COEFF2627, 0xf482f52b}, -{7800000, DIF_BPF_COEFF2829, 0x002d0c39}, -{7800000, DIF_BPF_COEFF3031, 0x0e0002f4}, -{7800000, DIF_BPF_COEFF3233, 0xf477efc2}, -{7800000, DIF_BPF_COEFF3435, 0xf99b0977}, -{7800000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 78_quant.dat*/ - - -/*case 7900000:*/ -/* BEGIN - DIF BPF register values from 79_quant.dat*/ -{7900000, DIF_BPF_COEFF01, 0x0000fffd}, -{7900000, DIF_BPF_COEFF23, 0xfffa0004}, -{7900000, DIF_BPF_COEFF45, 0x0020002d}, -{7900000, DIF_BPF_COEFF67, 0xfffbff91}, -{7900000, DIF_BPF_COEFF89, 0xff61ffe8}, -{7900000, DIF_BPF_COEFF1011, 0x00f70184}, -{7900000, DIF_BPF_COEFF1213, 0x0086fe5c}, -{7900000, DIF_BPF_COEFF1415, 0xfd0bfe85}, -{7900000, DIF_BPF_COEFF1617, 0x024104e5}, -{7900000, DIF_BPF_COEFF1819, 0x0323fd7d}, -{7900000, DIF_BPF_COEFF2021, 0xf8e2fa79}, -{7900000, DIF_BPF_COEFF2223, 0x021d093f}, -{7900000, DIF_BPF_COEFF2425, 0x0879ff22}, -{7900000, DIF_BPF_COEFF2627, 0xf52bf465}, -{7900000, DIF_BPF_COEFF2829, 0xfec70b79}, -{7900000, DIF_BPF_COEFF3031, 0x0e6803eb}, -{7900000, DIF_BPF_COEFF3233, 0xf50defa5}, -{7900000, DIF_BPF_COEFF3435, 0xf937094a}, -{7900000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 79_quant.dat*/ - - -/*case 8000000:*/ -/* BEGIN - DIF BPF register values from 80_quant.dat*/ -{8000000, DIF_BPF_COEFF01, 0x0000fffe}, -{8000000, DIF_BPF_COEFF23, 0xfff8fffd}, -{8000000, DIF_BPF_COEFF45, 0x00190036}, -{8000000, DIF_BPF_COEFF67, 0x001bffaf}, -{8000000, DIF_BPF_COEFF89, 0xff4fff99}, -{8000000, DIF_BPF_COEFF1011, 0x00aa0198}, -{8000000, DIF_BPF_COEFF1213, 0x0112fef3}, -{8000000, DIF_BPF_COEFF1415, 0xfd09fdb9}, -{8000000, DIF_BPF_COEFF1617, 0x014d04be}, -{8000000, DIF_BPF_COEFF1819, 0x041bfecc}, -{8000000, DIF_BPF_COEFF2021, 0xf947f978}, -{8000000, DIF_BPF_COEFF2223, 0x00900897}, -{8000000, DIF_BPF_COEFF2425, 0x095a00b9}, -{8000000, DIF_BPF_COEFF2627, 0xf600f3c5}, -{8000000, DIF_BPF_COEFF2829, 0xfd650aa3}, -{8000000, DIF_BPF_COEFF3031, 0x0ebc04de}, -{8000000, DIF_BPF_COEFF3233, 0xf5aaef8e}, -{8000000, DIF_BPF_COEFF3435, 0xf8d5091c}, -{8000000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 80_quant.dat*/ - - -/*case 8100000:*/ -/* BEGIN - DIF BPF register values from 81_quant.dat*/ -{8100000, DIF_BPF_COEFF01, 0x0000ffff}, -{8100000, DIF_BPF_COEFF23, 0xfff7fff6}, -{8100000, DIF_BPF_COEFF45, 0x000e0038}, -{8100000, DIF_BPF_COEFF67, 0x0037ffd7}, -{8100000, DIF_BPF_COEFF89, 0xff52ff56}, -{8100000, DIF_BPF_COEFF1011, 0x004b0184}, -{8100000, DIF_BPF_COEFF1213, 0x0186ffa1}, -{8100000, DIF_BPF_COEFF1415, 0xfd40fd16}, -{8100000, DIF_BPF_COEFF1617, 0x00440452}, -{8100000, DIF_BPF_COEFF1819, 0x04de0029}, -{8100000, DIF_BPF_COEFF2021, 0xf9f2f8b2}, -{8100000, DIF_BPF_COEFF2223, 0xfefe07b5}, -{8100000, DIF_BPF_COEFF2425, 0x0a05024d}, -{8100000, DIF_BPF_COEFF2627, 0xf6fef34d}, -{8100000, DIF_BPF_COEFF2829, 0xfc0a09b8}, -{8100000, DIF_BPF_COEFF3031, 0x0efa05cd}, -{8100000, DIF_BPF_COEFF3233, 0xf64eef7d}, -{8100000, DIF_BPF_COEFF3435, 0xf87308ed}, -{8100000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 81_quant.dat*/ - - -/*case 8200000:*/ -/* BEGIN - DIF BPF register values from 82_quant.dat*/ -{8200000, DIF_BPF_COEFF01, 0x00010000}, -{8200000, DIF_BPF_COEFF23, 0xfff8fff0}, -{8200000, DIF_BPF_COEFF45, 0x00000031}, -{8200000, DIF_BPF_COEFF67, 0x004c0005}, -{8200000, DIF_BPF_COEFF89, 0xff6aff27}, -{8200000, DIF_BPF_COEFF1011, 0xffe4014a}, -{8200000, DIF_BPF_COEFF1213, 0x01d70057}, -{8200000, DIF_BPF_COEFF1415, 0xfdacfca6}, -{8200000, DIF_BPF_COEFF1617, 0xff3603a7}, -{8200000, DIF_BPF_COEFF1819, 0x05610184}, -{8200000, DIF_BPF_COEFF2021, 0xfadbf82e}, -{8200000, DIF_BPF_COEFF2223, 0xfd74069f}, -{8200000, DIF_BPF_COEFF2425, 0x0a7503d6}, -{8200000, DIF_BPF_COEFF2627, 0xf81ff2ff}, -{8200000, DIF_BPF_COEFF2829, 0xfab808b9}, -{8200000, DIF_BPF_COEFF3031, 0x0f2306b5}, -{8200000, DIF_BPF_COEFF3233, 0xf6f9ef72}, -{8200000, DIF_BPF_COEFF3435, 0xf81308bf}, -{8200000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 82_quant.dat*/ - - -/*case 8300000:*/ -/* BEGIN - DIF BPF register values from 83_quant.dat*/ -{8300000, DIF_BPF_COEFF01, 0x00010001}, -{8300000, DIF_BPF_COEFF23, 0xfffbffee}, -{8300000, DIF_BPF_COEFF45, 0xfff30022}, -{8300000, DIF_BPF_COEFF67, 0x00560032}, -{8300000, DIF_BPF_COEFF89, 0xff95ff10}, -{8300000, DIF_BPF_COEFF1011, 0xff8000f0}, -{8300000, DIF_BPF_COEFF1213, 0x01fe0106}, -{8300000, DIF_BPF_COEFF1415, 0xfe46fc71}, -{8300000, DIF_BPF_COEFF1617, 0xfe3502c7}, -{8300000, DIF_BPF_COEFF1819, 0x059e02ce}, -{8300000, DIF_BPF_COEFF2021, 0xfbf9f7f2}, -{8300000, DIF_BPF_COEFF2223, 0xfbff055b}, -{8300000, DIF_BPF_COEFF2425, 0x0aa9054c}, -{8300000, DIF_BPF_COEFF2627, 0xf961f2db}, -{8300000, DIF_BPF_COEFF2829, 0xf97507aa}, -{8300000, DIF_BPF_COEFF3031, 0x0f350797}, -{8300000, DIF_BPF_COEFF3233, 0xf7a9ef6d}, -{8300000, DIF_BPF_COEFF3435, 0xf7b40890}, -{8300000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 83_quant.dat*/ - - -/*case 8400000:*/ -/* BEGIN - DIF BPF register values from 84_quant.dat*/ -{8400000, DIF_BPF_COEFF01, 0x00010002}, -{8400000, DIF_BPF_COEFF23, 0xfffeffee}, -{8400000, DIF_BPF_COEFF45, 0xffe8000f}, -{8400000, DIF_BPF_COEFF67, 0x00540058}, -{8400000, DIF_BPF_COEFF89, 0xffcdff14}, -{8400000, DIF_BPF_COEFF1011, 0xff29007e}, -{8400000, DIF_BPF_COEFF1213, 0x01f6019e}, -{8400000, DIF_BPF_COEFF1415, 0xff01fc7c}, -{8400000, DIF_BPF_COEFF1617, 0xfd5101bf}, -{8400000, DIF_BPF_COEFF1819, 0x059203f6}, -{8400000, DIF_BPF_COEFF2021, 0xfd41f7fe}, -{8400000, DIF_BPF_COEFF2223, 0xfaa903f3}, -{8400000, DIF_BPF_COEFF2425, 0x0a9e06a9}, -{8400000, DIF_BPF_COEFF2627, 0xfabdf2e2}, -{8400000, DIF_BPF_COEFF2829, 0xf842068b}, -{8400000, DIF_BPF_COEFF3031, 0x0f320871}, -{8400000, DIF_BPF_COEFF3233, 0xf85eef6e}, -{8400000, DIF_BPF_COEFF3435, 0xf7560860}, -{8400000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 84_quant.dat*/ - - -/*case 8500000:*/ -/* BEGIN - DIF BPF register values from 85_quant.dat*/ -{8500000, DIF_BPF_COEFF01, 0x00000003}, -{8500000, DIF_BPF_COEFF23, 0x0002fff2}, -{8500000, DIF_BPF_COEFF45, 0xffe1fff9}, -{8500000, DIF_BPF_COEFF67, 0x00460073}, -{8500000, DIF_BPF_COEFF89, 0x000bff34}, -{8500000, DIF_BPF_COEFF1011, 0xfee90000}, -{8500000, DIF_BPF_COEFF1213, 0x01c10215}, -{8500000, DIF_BPF_COEFF1415, 0xffd0fcc5}, -{8500000, DIF_BPF_COEFF1617, 0xfc99009d}, -{8500000, DIF_BPF_COEFF1819, 0x053d04f1}, -{8500000, DIF_BPF_COEFF2021, 0xfea5f853}, -{8500000, DIF_BPF_COEFF2223, 0xf97d0270}, -{8500000, DIF_BPF_COEFF2425, 0x0a5607e4}, -{8500000, DIF_BPF_COEFF2627, 0xfc2ef314}, -{8500000, DIF_BPF_COEFF2829, 0xf723055f}, -{8500000, DIF_BPF_COEFF3031, 0x0f180943}, -{8500000, DIF_BPF_COEFF3233, 0xf919ef75}, -{8500000, DIF_BPF_COEFF3435, 0xf6fa0830}, -{8500000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 85_quant.dat*/ - - -/*case 8600000:*/ -/* BEGIN - DIF BPF register values from 86_quant.dat*/ -{8600000, DIF_BPF_COEFF01, 0x00000003}, -{8600000, DIF_BPF_COEFF23, 0x0005fff8}, -{8600000, DIF_BPF_COEFF45, 0xffdeffe4}, -{8600000, DIF_BPF_COEFF67, 0x002f007f}, -{8600000, DIF_BPF_COEFF89, 0x0048ff6b}, -{8600000, DIF_BPF_COEFF1011, 0xfec7ff82}, -{8600000, DIF_BPF_COEFF1213, 0x0163025f}, -{8600000, DIF_BPF_COEFF1415, 0x00a2fd47}, -{8600000, DIF_BPF_COEFF1617, 0xfc17ff73}, -{8600000, DIF_BPF_COEFF1819, 0x04a405b2}, -{8600000, DIF_BPF_COEFF2021, 0x0017f8ed}, -{8600000, DIF_BPF_COEFF2223, 0xf88500dc}, -{8600000, DIF_BPF_COEFF2425, 0x09d208f9}, -{8600000, DIF_BPF_COEFF2627, 0xfdaff370}, -{8600000, DIF_BPF_COEFF2829, 0xf61c0429}, -{8600000, DIF_BPF_COEFF3031, 0x0ee80a0b}, -{8600000, DIF_BPF_COEFF3233, 0xf9d8ef82}, -{8600000, DIF_BPF_COEFF3435, 0xf6a00800}, -{8600000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 86_quant.dat*/ - - -/*case 8700000:*/ -/* BEGIN - DIF BPF register values from 87_quant.dat*/ -{8700000, DIF_BPF_COEFF01, 0x00000003}, -{8700000, DIF_BPF_COEFF23, 0x0007ffff}, -{8700000, DIF_BPF_COEFF45, 0xffe1ffd4}, -{8700000, DIF_BPF_COEFF67, 0x0010007a}, -{8700000, DIF_BPF_COEFF89, 0x007cffb2}, -{8700000, DIF_BPF_COEFF1011, 0xfec6ff10}, -{8700000, DIF_BPF_COEFF1213, 0x00e60277}, -{8700000, DIF_BPF_COEFF1415, 0x0168fdf9}, -{8700000, DIF_BPF_COEFF1617, 0xfbd3fe50}, -{8700000, DIF_BPF_COEFF1819, 0x03ce0631}, -{8700000, DIF_BPF_COEFF2021, 0x0188f9c8}, -{8700000, DIF_BPF_COEFF2223, 0xf7c7ff43}, -{8700000, DIF_BPF_COEFF2425, 0x091509e3}, -{8700000, DIF_BPF_COEFF2627, 0xff39f3f6}, -{8700000, DIF_BPF_COEFF2829, 0xf52d02ea}, -{8700000, DIF_BPF_COEFF3031, 0x0ea30ac9}, -{8700000, DIF_BPF_COEFF3233, 0xfa9bef95}, -{8700000, DIF_BPF_COEFF3435, 0xf64607d0}, -{8700000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 87_quant.dat*/ - - -/*case 8800000:*/ -/* BEGIN - DIF BPF register values from 88_quant.dat*/ -{8800000, DIF_BPF_COEFF01, 0x00000002}, -{8800000, DIF_BPF_COEFF23, 0x00090007}, -{8800000, DIF_BPF_COEFF45, 0xffe9ffca}, -{8800000, DIF_BPF_COEFF67, 0xfff00065}, -{8800000, DIF_BPF_COEFF89, 0x00a10003}, -{8800000, DIF_BPF_COEFF1011, 0xfee6feb6}, -{8800000, DIF_BPF_COEFF1213, 0x0053025b}, -{8800000, DIF_BPF_COEFF1415, 0x0213fed0}, -{8800000, DIF_BPF_COEFF1617, 0xfbd3fd46}, -{8800000, DIF_BPF_COEFF1819, 0x02c70668}, -{8800000, DIF_BPF_COEFF2021, 0x02eafadb}, -{8800000, DIF_BPF_COEFF2223, 0xf74bfdae}, -{8800000, DIF_BPF_COEFF2425, 0x08230a9c}, -{8800000, DIF_BPF_COEFF2627, 0x00c7f4a3}, -{8800000, DIF_BPF_COEFF2829, 0xf45b01a6}, -{8800000, DIF_BPF_COEFF3031, 0x0e480b7c}, -{8800000, DIF_BPF_COEFF3233, 0xfb61efae}, -{8800000, DIF_BPF_COEFF3435, 0xf5ef079f}, -{8800000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 88_quant.dat*/ - - -/*case 8900000:*/ -/* BEGIN - DIF BPF register values from 89_quant.dat*/ -{8900000, DIF_BPF_COEFF01, 0xffff0000}, -{8900000, DIF_BPF_COEFF23, 0x0008000d}, -{8900000, DIF_BPF_COEFF45, 0xfff5ffc8}, -{8900000, DIF_BPF_COEFF67, 0xffd10043}, -{8900000, DIF_BPF_COEFF89, 0x00b20053}, -{8900000, DIF_BPF_COEFF1011, 0xff24fe7c}, -{8900000, DIF_BPF_COEFF1213, 0xffb9020c}, -{8900000, DIF_BPF_COEFF1415, 0x0295ffbb}, -{8900000, DIF_BPF_COEFF1617, 0xfc17fc64}, -{8900000, DIF_BPF_COEFF1819, 0x019b0654}, -{8900000, DIF_BPF_COEFF2021, 0x042dfc1c}, -{8900000, DIF_BPF_COEFF2223, 0xf714fc2a}, -{8900000, DIF_BPF_COEFF2425, 0x07020b21}, -{8900000, DIF_BPF_COEFF2627, 0x0251f575}, -{8900000, DIF_BPF_COEFF2829, 0xf3a7005e}, -{8900000, DIF_BPF_COEFF3031, 0x0dd80c24}, -{8900000, DIF_BPF_COEFF3233, 0xfc2aefcd}, -{8900000, DIF_BPF_COEFF3435, 0xf599076e}, -{8900000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 89_quant.dat*/ - - -/*case 9000000:*/ -/* BEGIN - DIF BPF register values from 90_quant.dat*/ -{9000000, DIF_BPF_COEFF01, 0xffffffff}, -{9000000, DIF_BPF_COEFF23, 0x00060011}, -{9000000, DIF_BPF_COEFF45, 0x0002ffcf}, -{9000000, DIF_BPF_COEFF67, 0xffba0018}, -{9000000, DIF_BPF_COEFF89, 0x00ad009a}, -{9000000, DIF_BPF_COEFF1011, 0xff79fe68}, -{9000000, DIF_BPF_COEFF1213, 0xff260192}, -{9000000, DIF_BPF_COEFF1415, 0x02e500ab}, -{9000000, DIF_BPF_COEFF1617, 0xfc99fbb6}, -{9000000, DIF_BPF_COEFF1819, 0x005b05f7}, -{9000000, DIF_BPF_COEFF2021, 0x0545fd81}, -{9000000, DIF_BPF_COEFF2223, 0xf723fabf}, -{9000000, DIF_BPF_COEFF2425, 0x05b80b70}, -{9000000, DIF_BPF_COEFF2627, 0x03d2f669}, -{9000000, DIF_BPF_COEFF2829, 0xf313ff15}, -{9000000, DIF_BPF_COEFF3031, 0x0d550cbf}, -{9000000, DIF_BPF_COEFF3233, 0xfcf6eff2}, -{9000000, DIF_BPF_COEFF3435, 0xf544073d}, -{9000000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 90_quant.dat*/ - - -/*case 9100000:*/ -/* BEGIN - DIF BPF register values from 91_quant.dat*/ -{9100000, DIF_BPF_COEFF01, 0xfffffffe}, -{9100000, DIF_BPF_COEFF23, 0x00030012}, -{9100000, DIF_BPF_COEFF45, 0x000fffdd}, -{9100000, DIF_BPF_COEFF67, 0xffacffea}, -{9100000, DIF_BPF_COEFF89, 0x009300cf}, -{9100000, DIF_BPF_COEFF1011, 0xffdcfe7c}, -{9100000, DIF_BPF_COEFF1213, 0xfea600f7}, -{9100000, DIF_BPF_COEFF1415, 0x02fd0190}, -{9100000, DIF_BPF_COEFF1617, 0xfd51fb46}, -{9100000, DIF_BPF_COEFF1819, 0xff150554}, -{9100000, DIF_BPF_COEFF2021, 0x0627fefd}, -{9100000, DIF_BPF_COEFF2223, 0xf778f978}, -{9100000, DIF_BPF_COEFF2425, 0x044d0b87}, -{9100000, DIF_BPF_COEFF2627, 0x0543f77d}, -{9100000, DIF_BPF_COEFF2829, 0xf2a0fdcf}, -{9100000, DIF_BPF_COEFF3031, 0x0cbe0d4e}, -{9100000, DIF_BPF_COEFF3233, 0xfdc4f01d}, -{9100000, DIF_BPF_COEFF3435, 0xf4f2070b}, -{9100000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 91_quant.dat*/ - - -/*case 9200000:*/ -/* BEGIN - DIF BPF register values from 92_quant.dat*/ -{9200000, DIF_BPF_COEFF01, 0x0000fffd}, -{9200000, DIF_BPF_COEFF23, 0x00000010}, -{9200000, DIF_BPF_COEFF45, 0x001afff0}, -{9200000, DIF_BPF_COEFF67, 0xffaaffbf}, -{9200000, DIF_BPF_COEFF89, 0x006700ed}, -{9200000, DIF_BPF_COEFF1011, 0x0043feb6}, -{9200000, DIF_BPF_COEFF1213, 0xfe460047}, -{9200000, DIF_BPF_COEFF1415, 0x02db0258}, -{9200000, DIF_BPF_COEFF1617, 0xfe35fb1b}, -{9200000, DIF_BPF_COEFF1819, 0xfddc0473}, -{9200000, DIF_BPF_COEFF2021, 0x06c90082}, -{9200000, DIF_BPF_COEFF2223, 0xf811f85e}, -{9200000, DIF_BPF_COEFF2425, 0x02c90b66}, -{9200000, DIF_BPF_COEFF2627, 0x069ff8ad}, -{9200000, DIF_BPF_COEFF2829, 0xf250fc8d}, -{9200000, DIF_BPF_COEFF3031, 0x0c140dcf}, -{9200000, DIF_BPF_COEFF3233, 0xfe93f04d}, -{9200000, DIF_BPF_COEFF3435, 0xf4a106d9}, -{9200000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 92_quant.dat*/ - - -/*case 9300000:*/ -/* BEGIN - DIF BPF register values from 93_quant.dat*/ -{9300000, DIF_BPF_COEFF01, 0x0000fffd}, -{9300000, DIF_BPF_COEFF23, 0xfffc000c}, -{9300000, DIF_BPF_COEFF45, 0x00200006}, -{9300000, DIF_BPF_COEFF67, 0xffb4ff9c}, -{9300000, DIF_BPF_COEFF89, 0x002f00ef}, -{9300000, DIF_BPF_COEFF1011, 0x00a4ff10}, -{9300000, DIF_BPF_COEFF1213, 0xfe0dff92}, -{9300000, DIF_BPF_COEFF1415, 0x028102f7}, -{9300000, DIF_BPF_COEFF1617, 0xff36fb37}, -{9300000, DIF_BPF_COEFF1819, 0xfcbf035e}, -{9300000, DIF_BPF_COEFF2021, 0x07260202}, -{9300000, DIF_BPF_COEFF2223, 0xf8e8f778}, -{9300000, DIF_BPF_COEFF2425, 0x01340b0d}, -{9300000, DIF_BPF_COEFF2627, 0x07e1f9f4}, -{9300000, DIF_BPF_COEFF2829, 0xf223fb51}, -{9300000, DIF_BPF_COEFF3031, 0x0b590e42}, -{9300000, DIF_BPF_COEFF3233, 0xff64f083}, -{9300000, DIF_BPF_COEFF3435, 0xf45206a7}, -{9300000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 93_quant.dat*/ - - -/*case 9400000:*/ -/* BEGIN - DIF BPF register values from 94_quant.dat*/ -{9400000, DIF_BPF_COEFF01, 0x0000fffd}, -{9400000, DIF_BPF_COEFF23, 0xfff90005}, -{9400000, DIF_BPF_COEFF45, 0x0022001a}, -{9400000, DIF_BPF_COEFF67, 0xffc9ff86}, -{9400000, DIF_BPF_COEFF89, 0xfff000d7}, -{9400000, DIF_BPF_COEFF1011, 0x00f2ff82}, -{9400000, DIF_BPF_COEFF1213, 0xfe01fee5}, -{9400000, DIF_BPF_COEFF1415, 0x01f60362}, -{9400000, DIF_BPF_COEFF1617, 0x0044fb99}, -{9400000, DIF_BPF_COEFF1819, 0xfbcc0222}, -{9400000, DIF_BPF_COEFF2021, 0x07380370}, -{9400000, DIF_BPF_COEFF2223, 0xf9f7f6cc}, -{9400000, DIF_BPF_COEFF2425, 0xff990a7e}, -{9400000, DIF_BPF_COEFF2627, 0x0902fb50}, -{9400000, DIF_BPF_COEFF2829, 0xf21afa1f}, -{9400000, DIF_BPF_COEFF3031, 0x0a8d0ea6}, -{9400000, DIF_BPF_COEFF3233, 0x0034f0bf}, -{9400000, DIF_BPF_COEFF3435, 0xf4050675}, -{9400000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 94_quant.dat*/ - - -/*case 9500000:*/ -/* BEGIN - DIF BPF register values from 95_quant.dat*/ -{9500000, DIF_BPF_COEFF01, 0x0000fffe}, -{9500000, DIF_BPF_COEFF23, 0xfff8fffe}, -{9500000, DIF_BPF_COEFF45, 0x001e002b}, -{9500000, DIF_BPF_COEFF67, 0xffe5ff81}, -{9500000, DIF_BPF_COEFF89, 0xffb400a5}, -{9500000, DIF_BPF_COEFF1011, 0x01280000}, -{9500000, DIF_BPF_COEFF1213, 0xfe24fe50}, -{9500000, DIF_BPF_COEFF1415, 0x01460390}, -{9500000, DIF_BPF_COEFF1617, 0x014dfc3a}, -{9500000, DIF_BPF_COEFF1819, 0xfb1000ce}, -{9500000, DIF_BPF_COEFF2021, 0x070104bf}, -{9500000, DIF_BPF_COEFF2223, 0xfb37f65f}, -{9500000, DIF_BPF_COEFF2425, 0xfe0009bc}, -{9500000, DIF_BPF_COEFF2627, 0x0a00fcbb}, -{9500000, DIF_BPF_COEFF2829, 0xf235f8f8}, -{9500000, DIF_BPF_COEFF3031, 0x09b20efc}, -{9500000, DIF_BPF_COEFF3233, 0x0105f101}, -{9500000, DIF_BPF_COEFF3435, 0xf3ba0642}, -{9500000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 95_quant.dat*/ - - -/*case 9600000:*/ -/* BEGIN - DIF BPF register values from 96_quant.dat*/ -{9600000, DIF_BPF_COEFF01, 0x0001ffff}, -{9600000, DIF_BPF_COEFF23, 0xfff8fff7}, -{9600000, DIF_BPF_COEFF45, 0x00150036}, -{9600000, DIF_BPF_COEFF67, 0x0005ff8c}, -{9600000, DIF_BPF_COEFF89, 0xff810061}, -{9600000, DIF_BPF_COEFF1011, 0x013d007e}, -{9600000, DIF_BPF_COEFF1213, 0xfe71fddf}, -{9600000, DIF_BPF_COEFF1415, 0x007c0380}, -{9600000, DIF_BPF_COEFF1617, 0x0241fd13}, -{9600000, DIF_BPF_COEFF1819, 0xfa94ff70}, -{9600000, DIF_BPF_COEFF2021, 0x068005e2}, -{9600000, DIF_BPF_COEFF2223, 0xfc9bf633}, -{9600000, DIF_BPF_COEFF2425, 0xfc7308ca}, -{9600000, DIF_BPF_COEFF2627, 0x0ad5fe30}, -{9600000, DIF_BPF_COEFF2829, 0xf274f7e0}, -{9600000, DIF_BPF_COEFF3031, 0x08c90f43}, -{9600000, DIF_BPF_COEFF3233, 0x01d4f147}, -{9600000, DIF_BPF_COEFF3435, 0xf371060f}, -{9600000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 96_quant.dat*/ - - -/*case 9700000:*/ -/* BEGIN - DIF BPF register values from 97_quant.dat*/ -{9700000, DIF_BPF_COEFF01, 0x00010001}, -{9700000, DIF_BPF_COEFF23, 0xfff9fff1}, -{9700000, DIF_BPF_COEFF45, 0x00090038}, -{9700000, DIF_BPF_COEFF67, 0x0025ffa7}, -{9700000, DIF_BPF_COEFF89, 0xff5e0012}, -{9700000, DIF_BPF_COEFF1011, 0x013200f0}, -{9700000, DIF_BPF_COEFF1213, 0xfee3fd9b}, -{9700000, DIF_BPF_COEFF1415, 0xffaa0331}, -{9700000, DIF_BPF_COEFF1617, 0x0311fe15}, -{9700000, DIF_BPF_COEFF1819, 0xfa60fe18}, -{9700000, DIF_BPF_COEFF2021, 0x05bd06d1}, -{9700000, DIF_BPF_COEFF2223, 0xfe1bf64a}, -{9700000, DIF_BPF_COEFF2425, 0xfafa07ae}, -{9700000, DIF_BPF_COEFF2627, 0x0b7effab}, -{9700000, DIF_BPF_COEFF2829, 0xf2d5f6d7}, -{9700000, DIF_BPF_COEFF3031, 0x07d30f7a}, -{9700000, DIF_BPF_COEFF3233, 0x02a3f194}, -{9700000, DIF_BPF_COEFF3435, 0xf32905dc}, -{9700000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 97_quant.dat*/ - - -/*case 9800000:*/ -/* BEGIN - DIF BPF register values from 98_quant.dat*/ -{9800000, DIF_BPF_COEFF01, 0x00010002}, -{9800000, DIF_BPF_COEFF23, 0xfffcffee}, -{9800000, DIF_BPF_COEFF45, 0xfffb0032}, -{9800000, DIF_BPF_COEFF67, 0x003fffcd}, -{9800000, DIF_BPF_COEFF89, 0xff4effc1}, -{9800000, DIF_BPF_COEFF1011, 0x0106014a}, -{9800000, DIF_BPF_COEFF1213, 0xff6efd8a}, -{9800000, DIF_BPF_COEFF1415, 0xfedd02aa}, -{9800000, DIF_BPF_COEFF1617, 0x03b0ff34}, -{9800000, DIF_BPF_COEFF1819, 0xfa74fcd7}, -{9800000, DIF_BPF_COEFF2021, 0x04bf0781}, -{9800000, DIF_BPF_COEFF2223, 0xffaaf6a3}, -{9800000, DIF_BPF_COEFF2425, 0xf99e066b}, -{9800000, DIF_BPF_COEFF2627, 0x0bf90128}, -{9800000, DIF_BPF_COEFF2829, 0xf359f5e1}, -{9800000, DIF_BPF_COEFF3031, 0x06d20fa2}, -{9800000, DIF_BPF_COEFF3233, 0x0370f1e5}, -{9800000, DIF_BPF_COEFF3435, 0xf2e405a8}, -{9800000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 98_quant.dat*/ - - -/*case 9900000:*/ -/* BEGIN - DIF BPF register values from 99_quant.dat*/ -{9900000, DIF_BPF_COEFF01, 0x00000003}, -{9900000, DIF_BPF_COEFF23, 0xffffffee}, -{9900000, DIF_BPF_COEFF45, 0xffef0024}, -{9900000, DIF_BPF_COEFF67, 0x0051fffa}, -{9900000, DIF_BPF_COEFF89, 0xff54ff77}, -{9900000, DIF_BPF_COEFF1011, 0x00be0184}, -{9900000, DIF_BPF_COEFF1213, 0x0006fdad}, -{9900000, DIF_BPF_COEFF1415, 0xfe2701f3}, -{9900000, DIF_BPF_COEFF1617, 0x0413005e}, -{9900000, DIF_BPF_COEFF1819, 0xfad1fbba}, -{9900000, DIF_BPF_COEFF2021, 0x039007ee}, -{9900000, DIF_BPF_COEFF2223, 0x013bf73d}, -{9900000, DIF_BPF_COEFF2425, 0xf868050a}, -{9900000, DIF_BPF_COEFF2627, 0x0c4302a1}, -{9900000, DIF_BPF_COEFF2829, 0xf3fdf4fe}, -{9900000, DIF_BPF_COEFF3031, 0x05c70fba}, -{9900000, DIF_BPF_COEFF3233, 0x043bf23c}, -{9900000, DIF_BPF_COEFF3435, 0xf2a10575}, -{9900000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 99_quant.dat*/ - - -/*case 10000000:*/ -/* BEGIN - DIF BPF register values from 100_quant.dat*/ -{10000000, DIF_BPF_COEFF01, 0x00000003}, -{10000000, DIF_BPF_COEFF23, 0x0003fff1}, -{10000000, DIF_BPF_COEFF45, 0xffe50011}, -{10000000, DIF_BPF_COEFF67, 0x00570027}, -{10000000, DIF_BPF_COEFF89, 0xff70ff3c}, -{10000000, DIF_BPF_COEFF1011, 0x00620198}, -{10000000, DIF_BPF_COEFF1213, 0x009efe01}, -{10000000, DIF_BPF_COEFF1415, 0xfd95011a}, -{10000000, DIF_BPF_COEFF1617, 0x04350183}, -{10000000, DIF_BPF_COEFF1819, 0xfb71fad0}, -{10000000, DIF_BPF_COEFF2021, 0x023c0812}, -{10000000, DIF_BPF_COEFF2223, 0x02c3f811}, -{10000000, DIF_BPF_COEFF2425, 0xf75e0390}, -{10000000, DIF_BPF_COEFF2627, 0x0c5c0411}, -{10000000, DIF_BPF_COEFF2829, 0xf4c1f432}, -{10000000, DIF_BPF_COEFF3031, 0x04b30fc1}, -{10000000, DIF_BPF_COEFF3233, 0x0503f297}, -{10000000, DIF_BPF_COEFF3435, 0xf2610541}, -{10000000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 100_quant.dat*/ - - -/*case 10100000:*/ -/* BEGIN - DIF BPF register values from 101_quant.dat*/ -{10100000, DIF_BPF_COEFF01, 0x00000003}, -{10100000, DIF_BPF_COEFF23, 0x0006fff7}, -{10100000, DIF_BPF_COEFF45, 0xffdffffc}, -{10100000, DIF_BPF_COEFF67, 0x00510050}, -{10100000, DIF_BPF_COEFF89, 0xff9dff18}, -{10100000, DIF_BPF_COEFF1011, 0xfffc0184}, -{10100000, DIF_BPF_COEFF1213, 0x0128fe80}, -{10100000, DIF_BPF_COEFF1415, 0xfd32002e}, -{10100000, DIF_BPF_COEFF1617, 0x04130292}, -{10100000, DIF_BPF_COEFF1819, 0xfc4dfa21}, -{10100000, DIF_BPF_COEFF2021, 0x00d107ee}, -{10100000, DIF_BPF_COEFF2223, 0x0435f91c}, -{10100000, DIF_BPF_COEFF2425, 0xf6850205}, -{10100000, DIF_BPF_COEFF2627, 0x0c430573}, -{10100000, DIF_BPF_COEFF2829, 0xf5a1f37d}, -{10100000, DIF_BPF_COEFF3031, 0x03990fba}, -{10100000, DIF_BPF_COEFF3233, 0x05c7f2f8}, -{10100000, DIF_BPF_COEFF3435, 0xf222050d}, -{10100000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 101_quant.dat*/ - - -/*case 10200000:*/ -/* BEGIN - DIF BPF register values from 102_quant.dat*/ -{10200000, DIF_BPF_COEFF01, 0x00000002}, -{10200000, DIF_BPF_COEFF23, 0x0008fffe}, -{10200000, DIF_BPF_COEFF45, 0xffdfffe7}, -{10200000, DIF_BPF_COEFF67, 0x003f006e}, -{10200000, DIF_BPF_COEFF89, 0xffd6ff0f}, -{10200000, DIF_BPF_COEFF1011, 0xff96014a}, -{10200000, DIF_BPF_COEFF1213, 0x0197ff1f}, -{10200000, DIF_BPF_COEFF1415, 0xfd05ff3e}, -{10200000, DIF_BPF_COEFF1617, 0x03b0037c}, -{10200000, DIF_BPF_COEFF1819, 0xfd59f9b7}, -{10200000, DIF_BPF_COEFF2021, 0xff5d0781}, -{10200000, DIF_BPF_COEFF2223, 0x0585fa56}, -{10200000, DIF_BPF_COEFF2425, 0xf5e4006f}, -{10200000, DIF_BPF_COEFF2627, 0x0bf906c4}, -{10200000, DIF_BPF_COEFF2829, 0xf69df2e0}, -{10200000, DIF_BPF_COEFF3031, 0x02790fa2}, -{10200000, DIF_BPF_COEFF3233, 0x0688f35d}, -{10200000, DIF_BPF_COEFF3435, 0xf1e604d8}, -{10200000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 102_quant.dat*/ - - -/*case 10300000:*/ -/* BEGIN - DIF BPF register values from 103_quant.dat*/ -{10300000, DIF_BPF_COEFF01, 0xffff0001}, -{10300000, DIF_BPF_COEFF23, 0x00090005}, -{10300000, DIF_BPF_COEFF45, 0xffe4ffd6}, -{10300000, DIF_BPF_COEFF67, 0x0025007e}, -{10300000, DIF_BPF_COEFF89, 0x0014ff20}, -{10300000, DIF_BPF_COEFF1011, 0xff3c00f0}, -{10300000, DIF_BPF_COEFF1213, 0x01e1ffd0}, -{10300000, DIF_BPF_COEFF1415, 0xfd12fe5c}, -{10300000, DIF_BPF_COEFF1617, 0x03110433}, -{10300000, DIF_BPF_COEFF1819, 0xfe88f996}, -{10300000, DIF_BPF_COEFF2021, 0xfdf106d1}, -{10300000, DIF_BPF_COEFF2223, 0x06aafbb7}, -{10300000, DIF_BPF_COEFF2425, 0xf57efed8}, -{10300000, DIF_BPF_COEFF2627, 0x0b7e07ff}, -{10300000, DIF_BPF_COEFF2829, 0xf7b0f25e}, -{10300000, DIF_BPF_COEFF3031, 0x01560f7a}, -{10300000, DIF_BPF_COEFF3233, 0x0745f3c7}, -{10300000, DIF_BPF_COEFF3435, 0xf1ac04a4}, -{10300000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 103_quant.dat*/ - - -/*case 10400000:*/ -/* BEGIN - DIF BPF register values from 104_quant.dat*/ -{10400000, DIF_BPF_COEFF01, 0xffffffff}, -{10400000, DIF_BPF_COEFF23, 0x0008000c}, -{10400000, DIF_BPF_COEFF45, 0xffedffcb}, -{10400000, DIF_BPF_COEFF67, 0x0005007d}, -{10400000, DIF_BPF_COEFF89, 0x0050ff4c}, -{10400000, DIF_BPF_COEFF1011, 0xfef6007e}, -{10400000, DIF_BPF_COEFF1213, 0x01ff0086}, -{10400000, DIF_BPF_COEFF1415, 0xfd58fd97}, -{10400000, DIF_BPF_COEFF1617, 0x024104ad}, -{10400000, DIF_BPF_COEFF1819, 0xffcaf9c0}, -{10400000, DIF_BPF_COEFF2021, 0xfc9905e2}, -{10400000, DIF_BPF_COEFF2223, 0x079afd35}, -{10400000, DIF_BPF_COEFF2425, 0xf555fd46}, -{10400000, DIF_BPF_COEFF2627, 0x0ad50920}, -{10400000, DIF_BPF_COEFF2829, 0xf8d9f1f6}, -{10400000, DIF_BPF_COEFF3031, 0x00310f43}, -{10400000, DIF_BPF_COEFF3233, 0x07fdf435}, -{10400000, DIF_BPF_COEFF3435, 0xf174046f}, -{10400000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 104_quant.dat*/ - - -/*case 10500000:*/ -/* BEGIN - DIF BPF register values from 105_quant.dat*/ -{10500000, DIF_BPF_COEFF01, 0xfffffffe}, -{10500000, DIF_BPF_COEFF23, 0x00050011}, -{10500000, DIF_BPF_COEFF45, 0xfffaffc8}, -{10500000, DIF_BPF_COEFF67, 0xffe5006b}, -{10500000, DIF_BPF_COEFF89, 0x0082ff8c}, -{10500000, DIF_BPF_COEFF1011, 0xfecc0000}, -{10500000, DIF_BPF_COEFF1213, 0x01f00130}, -{10500000, DIF_BPF_COEFF1415, 0xfdd2fcfc}, -{10500000, DIF_BPF_COEFF1617, 0x014d04e3}, -{10500000, DIF_BPF_COEFF1819, 0x010efa32}, -{10500000, DIF_BPF_COEFF2021, 0xfb6404bf}, -{10500000, DIF_BPF_COEFF2223, 0x084efec5}, -{10500000, DIF_BPF_COEFF2425, 0xf569fbc2}, -{10500000, DIF_BPF_COEFF2627, 0x0a000a23}, -{10500000, DIF_BPF_COEFF2829, 0xfa15f1ab}, -{10500000, DIF_BPF_COEFF3031, 0xff0b0efc}, -{10500000, DIF_BPF_COEFF3233, 0x08b0f4a7}, -{10500000, DIF_BPF_COEFF3435, 0xf13f043a}, -{10500000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 105_quant.dat*/ - - -/*case 10600000:*/ -/* BEGIN - DIF BPF register values from 106_quant.dat*/ -{10600000, DIF_BPF_COEFF01, 0x0000fffd}, -{10600000, DIF_BPF_COEFF23, 0x00020012}, -{10600000, DIF_BPF_COEFF45, 0x0007ffcd}, -{10600000, DIF_BPF_COEFF67, 0xffc9004c}, -{10600000, DIF_BPF_COEFF89, 0x00a4ffd9}, -{10600000, DIF_BPF_COEFF1011, 0xfec3ff82}, -{10600000, DIF_BPF_COEFF1213, 0x01b401c1}, -{10600000, DIF_BPF_COEFF1415, 0xfe76fc97}, -{10600000, DIF_BPF_COEFF1617, 0x004404d2}, -{10600000, DIF_BPF_COEFF1819, 0x0245fae8}, -{10600000, DIF_BPF_COEFF2021, 0xfa5f0370}, -{10600000, DIF_BPF_COEFF2223, 0x08c1005f}, -{10600000, DIF_BPF_COEFF2425, 0xf5bcfa52}, -{10600000, DIF_BPF_COEFF2627, 0x09020b04}, -{10600000, DIF_BPF_COEFF2829, 0xfb60f17b}, -{10600000, DIF_BPF_COEFF3031, 0xfde70ea6}, -{10600000, DIF_BPF_COEFF3233, 0x095df51e}, -{10600000, DIF_BPF_COEFF3435, 0xf10c0405}, -{10600000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 106_quant.dat*/ - - -/*case 10700000:*/ -/* BEGIN - DIF BPF register values from 107_quant.dat*/ -{10700000, DIF_BPF_COEFF01, 0x0000fffd}, -{10700000, DIF_BPF_COEFF23, 0xffff0011}, -{10700000, DIF_BPF_COEFF45, 0x0014ffdb}, -{10700000, DIF_BPF_COEFF67, 0xffb40023}, -{10700000, DIF_BPF_COEFF89, 0x00b2002a}, -{10700000, DIF_BPF_COEFF1011, 0xfedbff10}, -{10700000, DIF_BPF_COEFF1213, 0x0150022d}, -{10700000, DIF_BPF_COEFF1415, 0xff38fc6f}, -{10700000, DIF_BPF_COEFF1617, 0xff36047b}, -{10700000, DIF_BPF_COEFF1819, 0x035efbda}, -{10700000, DIF_BPF_COEFF2021, 0xf9940202}, -{10700000, DIF_BPF_COEFF2223, 0x08ee01f5}, -{10700000, DIF_BPF_COEFF2425, 0xf649f8fe}, -{10700000, DIF_BPF_COEFF2627, 0x07e10bc2}, -{10700000, DIF_BPF_COEFF2829, 0xfcb6f169}, -{10700000, DIF_BPF_COEFF3031, 0xfcc60e42}, -{10700000, DIF_BPF_COEFF3233, 0x0a04f599}, -{10700000, DIF_BPF_COEFF3435, 0xf0db03d0}, -{10700000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 107_quant.dat*/ - - -/*case 10800000:*/ -/* BEGIN - DIF BPF register values from 108_quant.dat*/ -{10800000, DIF_BPF_COEFF01, 0x0000fffd}, -{10800000, DIF_BPF_COEFF23, 0xfffb000d}, -{10800000, DIF_BPF_COEFF45, 0x001dffed}, -{10800000, DIF_BPF_COEFF67, 0xffaafff5}, -{10800000, DIF_BPF_COEFF89, 0x00aa0077}, -{10800000, DIF_BPF_COEFF1011, 0xff13feb6}, -{10800000, DIF_BPF_COEFF1213, 0x00ce026b}, -{10800000, DIF_BPF_COEFF1415, 0x000afc85}, -{10800000, DIF_BPF_COEFF1617, 0xfe3503e3}, -{10800000, DIF_BPF_COEFF1819, 0x044cfcfb}, -{10800000, DIF_BPF_COEFF2021, 0xf90c0082}, -{10800000, DIF_BPF_COEFF2223, 0x08d5037f}, -{10800000, DIF_BPF_COEFF2425, 0xf710f7cc}, -{10800000, DIF_BPF_COEFF2627, 0x069f0c59}, -{10800000, DIF_BPF_COEFF2829, 0xfe16f173}, -{10800000, DIF_BPF_COEFF3031, 0xfbaa0dcf}, -{10800000, DIF_BPF_COEFF3233, 0x0aa5f617}, -{10800000, DIF_BPF_COEFF3435, 0xf0ad039b}, -{10800000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 108_quant.dat*/ - - -/*case 10900000:*/ -/* BEGIN - DIF BPF register values from 109_quant.dat*/ -{10900000, DIF_BPF_COEFF01, 0x0000fffe}, -{10900000, DIF_BPF_COEFF23, 0xfff90006}, -{10900000, DIF_BPF_COEFF45, 0x00210003}, -{10900000, DIF_BPF_COEFF67, 0xffacffc8}, -{10900000, DIF_BPF_COEFF89, 0x008e00b6}, -{10900000, DIF_BPF_COEFF1011, 0xff63fe7c}, -{10900000, DIF_BPF_COEFF1213, 0x003a0275}, -{10900000, DIF_BPF_COEFF1415, 0x00dafcda}, -{10900000, DIF_BPF_COEFF1617, 0xfd510313}, -{10900000, DIF_BPF_COEFF1819, 0x0501fe40}, -{10900000, DIF_BPF_COEFF2021, 0xf8cbfefd}, -{10900000, DIF_BPF_COEFF2223, 0x087604f0}, -{10900000, DIF_BPF_COEFF2425, 0xf80af6c2}, -{10900000, DIF_BPF_COEFF2627, 0x05430cc8}, -{10900000, DIF_BPF_COEFF2829, 0xff7af19a}, -{10900000, DIF_BPF_COEFF3031, 0xfa940d4e}, -{10900000, DIF_BPF_COEFF3233, 0x0b3ff699}, -{10900000, DIF_BPF_COEFF3435, 0xf0810365}, -{10900000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 109_quant.dat*/ - - -/*case 11000000:*/ -/* BEGIN - DIF BPF register values from 110_quant.dat*/ -{11000000, DIF_BPF_COEFF01, 0x0001ffff}, -{11000000, DIF_BPF_COEFF23, 0xfff8ffff}, -{11000000, DIF_BPF_COEFF45, 0x00210018}, -{11000000, DIF_BPF_COEFF67, 0xffbaffa3}, -{11000000, DIF_BPF_COEFF89, 0x006000e1}, -{11000000, DIF_BPF_COEFF1011, 0xffc4fe68}, -{11000000, DIF_BPF_COEFF1213, 0xffa0024b}, -{11000000, DIF_BPF_COEFF1415, 0x019afd66}, -{11000000, DIF_BPF_COEFF1617, 0xfc990216}, -{11000000, DIF_BPF_COEFF1819, 0x0575ff99}, -{11000000, DIF_BPF_COEFF2021, 0xf8d4fd81}, -{11000000, DIF_BPF_COEFF2223, 0x07d40640}, -{11000000, DIF_BPF_COEFF2425, 0xf932f5e6}, -{11000000, DIF_BPF_COEFF2627, 0x03d20d0d}, -{11000000, DIF_BPF_COEFF2829, 0x00dff1de}, -{11000000, DIF_BPF_COEFF3031, 0xf9860cbf}, -{11000000, DIF_BPF_COEFF3233, 0x0bd1f71e}, -{11000000, DIF_BPF_COEFF3435, 0xf058032f}, -{11000000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 110_quant.dat*/ - - -/*case 11100000:*/ -/* BEGIN - DIF BPF register values from 111_quant.dat*/ -{11100000, DIF_BPF_COEFF01, 0x00010000}, -{11100000, DIF_BPF_COEFF23, 0xfff8fff8}, -{11100000, DIF_BPF_COEFF45, 0x001b0029}, -{11100000, DIF_BPF_COEFF67, 0xffd1ff8a}, -{11100000, DIF_BPF_COEFF89, 0x002600f2}, -{11100000, DIF_BPF_COEFF1011, 0x002cfe7c}, -{11100000, DIF_BPF_COEFF1213, 0xff0f01f0}, -{11100000, DIF_BPF_COEFF1415, 0x023bfe20}, -{11100000, DIF_BPF_COEFF1617, 0xfc1700fa}, -{11100000, DIF_BPF_COEFF1819, 0x05a200f7}, -{11100000, DIF_BPF_COEFF2021, 0xf927fc1c}, -{11100000, DIF_BPF_COEFF2223, 0x06f40765}, -{11100000, DIF_BPF_COEFF2425, 0xfa82f53b}, -{11100000, DIF_BPF_COEFF2627, 0x02510d27}, -{11100000, DIF_BPF_COEFF2829, 0x0243f23d}, -{11100000, DIF_BPF_COEFF3031, 0xf8810c24}, -{11100000, DIF_BPF_COEFF3233, 0x0c5cf7a7}, -{11100000, DIF_BPF_COEFF3435, 0xf03102fa}, -{11100000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 111_quant.dat*/ - - -/*case 11200000:*/ -/* BEGIN - DIF BPF register values from 112_quant.dat*/ -{11200000, DIF_BPF_COEFF01, 0x00010002}, -{11200000, DIF_BPF_COEFF23, 0xfffafff2}, -{11200000, DIF_BPF_COEFF45, 0x00110035}, -{11200000, DIF_BPF_COEFF67, 0xfff0ff81}, -{11200000, DIF_BPF_COEFF89, 0xffe700e7}, -{11200000, DIF_BPF_COEFF1011, 0x008ffeb6}, -{11200000, DIF_BPF_COEFF1213, 0xfe94016d}, -{11200000, DIF_BPF_COEFF1415, 0x02b0fefb}, -{11200000, DIF_BPF_COEFF1617, 0xfbd3ffd1}, -{11200000, DIF_BPF_COEFF1819, 0x05850249}, -{11200000, DIF_BPF_COEFF2021, 0xf9c1fadb}, -{11200000, DIF_BPF_COEFF2223, 0x05de0858}, -{11200000, DIF_BPF_COEFF2425, 0xfbf2f4c4}, -{11200000, DIF_BPF_COEFF2627, 0x00c70d17}, -{11200000, DIF_BPF_COEFF2829, 0x03a0f2b8}, -{11200000, DIF_BPF_COEFF3031, 0xf7870b7c}, -{11200000, DIF_BPF_COEFF3233, 0x0cdff833}, -{11200000, DIF_BPF_COEFF3435, 0xf00d02c4}, -{11200000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 112_quant.dat*/ - - -/*case 11300000:*/ -/* BEGIN - DIF BPF register values from 113_quant.dat*/ -{11300000, DIF_BPF_COEFF01, 0x00000003}, -{11300000, DIF_BPF_COEFF23, 0xfffdffee}, -{11300000, DIF_BPF_COEFF45, 0x00040038}, -{11300000, DIF_BPF_COEFF67, 0x0010ff88}, -{11300000, DIF_BPF_COEFF89, 0xffac00c2}, -{11300000, DIF_BPF_COEFF1011, 0x00e2ff10}, -{11300000, DIF_BPF_COEFF1213, 0xfe3900cb}, -{11300000, DIF_BPF_COEFF1415, 0x02f1ffe9}, -{11300000, DIF_BPF_COEFF1617, 0xfbd3feaa}, -{11300000, DIF_BPF_COEFF1819, 0x05210381}, -{11300000, DIF_BPF_COEFF2021, 0xfa9cf9c8}, -{11300000, DIF_BPF_COEFF2223, 0x04990912}, -{11300000, DIF_BPF_COEFF2425, 0xfd7af484}, -{11300000, DIF_BPF_COEFF2627, 0xff390cdb}, -{11300000, DIF_BPF_COEFF2829, 0x04f4f34d}, -{11300000, DIF_BPF_COEFF3031, 0xf69a0ac9}, -{11300000, DIF_BPF_COEFF3233, 0x0d5af8c1}, -{11300000, DIF_BPF_COEFF3435, 0xefec028e}, -{11300000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 113_quant.dat*/ - - -/*case 11400000:*/ -/* BEGIN - DIF BPF register values from 114_quant.dat*/ -{11400000, DIF_BPF_COEFF01, 0x00000003}, -{11400000, DIF_BPF_COEFF23, 0x0000ffee}, -{11400000, DIF_BPF_COEFF45, 0xfff60033}, -{11400000, DIF_BPF_COEFF67, 0x002fff9f}, -{11400000, DIF_BPF_COEFF89, 0xff7b0087}, -{11400000, DIF_BPF_COEFF1011, 0x011eff82}, -{11400000, DIF_BPF_COEFF1213, 0xfe080018}, -{11400000, DIF_BPF_COEFF1415, 0x02f900d8}, -{11400000, DIF_BPF_COEFF1617, 0xfc17fd96}, -{11400000, DIF_BPF_COEFF1819, 0x04790490}, -{11400000, DIF_BPF_COEFF2021, 0xfbadf8ed}, -{11400000, DIF_BPF_COEFF2223, 0x032f098e}, -{11400000, DIF_BPF_COEFF2425, 0xff10f47d}, -{11400000, DIF_BPF_COEFF2627, 0xfdaf0c75}, -{11400000, DIF_BPF_COEFF2829, 0x063cf3fc}, -{11400000, DIF_BPF_COEFF3031, 0xf5ba0a0b}, -{11400000, DIF_BPF_COEFF3233, 0x0dccf952}, -{11400000, DIF_BPF_COEFF3435, 0xefcd0258}, -{11400000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 114_quant.dat*/ - - -/*case 11500000:*/ -/* BEGIN - DIF BPF register values from 115_quant.dat*/ -{11500000, DIF_BPF_COEFF01, 0x00000003}, -{11500000, DIF_BPF_COEFF23, 0x0004fff1}, -{11500000, DIF_BPF_COEFF45, 0xffea0026}, -{11500000, DIF_BPF_COEFF67, 0x0046ffc3}, -{11500000, DIF_BPF_COEFF89, 0xff5a003c}, -{11500000, DIF_BPF_COEFF1011, 0x013b0000}, -{11500000, DIF_BPF_COEFF1213, 0xfe04ff63}, -{11500000, DIF_BPF_COEFF1415, 0x02c801b8}, -{11500000, DIF_BPF_COEFF1617, 0xfc99fca6}, -{11500000, DIF_BPF_COEFF1819, 0x0397056a}, -{11500000, DIF_BPF_COEFF2021, 0xfcecf853}, -{11500000, DIF_BPF_COEFF2223, 0x01ad09c9}, -{11500000, DIF_BPF_COEFF2425, 0x00acf4ad}, -{11500000, DIF_BPF_COEFF2627, 0xfc2e0be7}, -{11500000, DIF_BPF_COEFF2829, 0x0773f4c2}, -{11500000, DIF_BPF_COEFF3031, 0xf4e90943}, -{11500000, DIF_BPF_COEFF3233, 0x0e35f9e6}, -{11500000, DIF_BPF_COEFF3435, 0xefb10221}, -{11500000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 115_quant.dat*/ - - -/*case 11600000:*/ -/* BEGIN - DIF BPF register values from 116_quant.dat*/ -{11600000, DIF_BPF_COEFF01, 0x00000002}, -{11600000, DIF_BPF_COEFF23, 0x0007fff6}, -{11600000, DIF_BPF_COEFF45, 0xffe20014}, -{11600000, DIF_BPF_COEFF67, 0x0054ffee}, -{11600000, DIF_BPF_COEFF89, 0xff4effeb}, -{11600000, DIF_BPF_COEFF1011, 0x0137007e}, -{11600000, DIF_BPF_COEFF1213, 0xfe2efebb}, -{11600000, DIF_BPF_COEFF1415, 0x0260027a}, -{11600000, DIF_BPF_COEFF1617, 0xfd51fbe6}, -{11600000, DIF_BPF_COEFF1819, 0x02870605}, -{11600000, DIF_BPF_COEFF2021, 0xfe4af7fe}, -{11600000, DIF_BPF_COEFF2223, 0x001d09c1}, -{11600000, DIF_BPF_COEFF2425, 0x0243f515}, -{11600000, DIF_BPF_COEFF2627, 0xfabd0b32}, -{11600000, DIF_BPF_COEFF2829, 0x0897f59e}, -{11600000, DIF_BPF_COEFF3031, 0xf4280871}, -{11600000, DIF_BPF_COEFF3233, 0x0e95fa7c}, -{11600000, DIF_BPF_COEFF3435, 0xef9701eb}, -{11600000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 116_quant.dat*/ - - -/*case 11700000:*/ -/* BEGIN - DIF BPF register values from 117_quant.dat*/ -{11700000, DIF_BPF_COEFF01, 0xffff0001}, -{11700000, DIF_BPF_COEFF23, 0x0008fffd}, -{11700000, DIF_BPF_COEFF45, 0xffdeffff}, -{11700000, DIF_BPF_COEFF67, 0x0056001d}, -{11700000, DIF_BPF_COEFF89, 0xff57ff9c}, -{11700000, DIF_BPF_COEFF1011, 0x011300f0}, -{11700000, DIF_BPF_COEFF1213, 0xfe82fe2e}, -{11700000, DIF_BPF_COEFF1415, 0x01ca0310}, -{11700000, DIF_BPF_COEFF1617, 0xfe35fb62}, -{11700000, DIF_BPF_COEFF1819, 0x0155065a}, -{11700000, DIF_BPF_COEFF2021, 0xffbaf7f2}, -{11700000, DIF_BPF_COEFF2223, 0xfe8c0977}, -{11700000, DIF_BPF_COEFF2425, 0x03cef5b2}, -{11700000, DIF_BPF_COEFF2627, 0xf9610a58}, -{11700000, DIF_BPF_COEFF2829, 0x09a5f68f}, -{11700000, DIF_BPF_COEFF3031, 0xf3790797}, -{11700000, DIF_BPF_COEFF3233, 0x0eebfb14}, -{11700000, DIF_BPF_COEFF3435, 0xef8001b5}, -{11700000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 117_quant.dat*/ - - -/*case 11800000:*/ -/* BEGIN - DIF BPF register values from 118_quant.dat*/ -{11800000, DIF_BPF_COEFF01, 0xffff0000}, -{11800000, DIF_BPF_COEFF23, 0x00080004}, -{11800000, DIF_BPF_COEFF45, 0xffe0ffe9}, -{11800000, DIF_BPF_COEFF67, 0x004c0047}, -{11800000, DIF_BPF_COEFF89, 0xff75ff58}, -{11800000, DIF_BPF_COEFF1011, 0x00d1014a}, -{11800000, DIF_BPF_COEFF1213, 0xfef9fdc8}, -{11800000, DIF_BPF_COEFF1415, 0x0111036f}, -{11800000, DIF_BPF_COEFF1617, 0xff36fb21}, -{11800000, DIF_BPF_COEFF1819, 0x00120665}, -{11800000, DIF_BPF_COEFF2021, 0x012df82e}, -{11800000, DIF_BPF_COEFF2223, 0xfd0708ec}, -{11800000, DIF_BPF_COEFF2425, 0x0542f682}, -{11800000, DIF_BPF_COEFF2627, 0xf81f095c}, -{11800000, DIF_BPF_COEFF2829, 0x0a9af792}, -{11800000, DIF_BPF_COEFF3031, 0xf2db06b5}, -{11800000, DIF_BPF_COEFF3233, 0x0f38fbad}, -{11800000, DIF_BPF_COEFF3435, 0xef6c017e}, -{11800000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 118_quant.dat*/ - - -/*case 11900000:*/ -/* BEGIN - DIF BPF register values from 119_quant.dat*/ -{11900000, DIF_BPF_COEFF01, 0xffffffff}, -{11900000, DIF_BPF_COEFF23, 0x0007000b}, -{11900000, DIF_BPF_COEFF45, 0xffe7ffd8}, -{11900000, DIF_BPF_COEFF67, 0x00370068}, -{11900000, DIF_BPF_COEFF89, 0xffa4ff28}, -{11900000, DIF_BPF_COEFF1011, 0x00790184}, -{11900000, DIF_BPF_COEFF1213, 0xff87fd91}, -{11900000, DIF_BPF_COEFF1415, 0x00430392}, -{11900000, DIF_BPF_COEFF1617, 0x0044fb26}, -{11900000, DIF_BPF_COEFF1819, 0xfece0626}, -{11900000, DIF_BPF_COEFF2021, 0x0294f8b2}, -{11900000, DIF_BPF_COEFF2223, 0xfb990825}, -{11900000, DIF_BPF_COEFF2425, 0x0698f77f}, -{11900000, DIF_BPF_COEFF2627, 0xf6fe0842}, -{11900000, DIF_BPF_COEFF2829, 0x0b73f8a7}, -{11900000, DIF_BPF_COEFF3031, 0xf25105cd}, -{11900000, DIF_BPF_COEFF3233, 0x0f7bfc48}, -{11900000, DIF_BPF_COEFF3435, 0xef5a0148}, -{11900000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 119_quant.dat*/ - - -/*case 12000000:*/ -/* BEGIN - DIF BPF register values from 120_quant.dat*/ -{12000000, DIF_BPF_COEFF01, 0x0000fffe}, -{12000000, DIF_BPF_COEFF23, 0x00050010}, -{12000000, DIF_BPF_COEFF45, 0xfff2ffcc}, -{12000000, DIF_BPF_COEFF67, 0x001b007b}, -{12000000, DIF_BPF_COEFF89, 0xffdfff10}, -{12000000, DIF_BPF_COEFF1011, 0x00140198}, -{12000000, DIF_BPF_COEFF1213, 0x0020fd8e}, -{12000000, DIF_BPF_COEFF1415, 0xff710375}, -{12000000, DIF_BPF_COEFF1617, 0x014dfb73}, -{12000000, DIF_BPF_COEFF1819, 0xfd9a059f}, -{12000000, DIF_BPF_COEFF2021, 0x03e0f978}, -{12000000, DIF_BPF_COEFF2223, 0xfa4e0726}, -{12000000, DIF_BPF_COEFF2425, 0x07c8f8a7}, -{12000000, DIF_BPF_COEFF2627, 0xf600070c}, -{12000000, DIF_BPF_COEFF2829, 0x0c2ff9c9}, -{12000000, DIF_BPF_COEFF3031, 0xf1db04de}, -{12000000, DIF_BPF_COEFF3233, 0x0fb4fce5}, -{12000000, DIF_BPF_COEFF3435, 0xef4b0111}, -{12000000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 120_quant.dat*/ - - -/*case 12100000:*/ -/* BEGIN - DIF BPF register values from 121_quant.dat*/ -{12100000, DIF_BPF_COEFF01, 0x0000fffd}, -{12100000, DIF_BPF_COEFF23, 0x00010012}, -{12100000, DIF_BPF_COEFF45, 0xffffffc8}, -{12100000, DIF_BPF_COEFF67, 0xfffb007e}, -{12100000, DIF_BPF_COEFF89, 0x001dff14}, -{12100000, DIF_BPF_COEFF1011, 0xffad0184}, -{12100000, DIF_BPF_COEFF1213, 0x00b7fdbe}, -{12100000, DIF_BPF_COEFF1415, 0xfea9031b}, -{12100000, DIF_BPF_COEFF1617, 0x0241fc01}, -{12100000, DIF_BPF_COEFF1819, 0xfc8504d6}, -{12100000, DIF_BPF_COEFF2021, 0x0504fa79}, -{12100000, DIF_BPF_COEFF2223, 0xf93005f6}, -{12100000, DIF_BPF_COEFF2425, 0x08caf9f2}, -{12100000, DIF_BPF_COEFF2627, 0xf52b05c0}, -{12100000, DIF_BPF_COEFF2829, 0x0ccbfaf9}, -{12100000, DIF_BPF_COEFF3031, 0xf17903eb}, -{12100000, DIF_BPF_COEFF3233, 0x0fe3fd83}, -{12100000, DIF_BPF_COEFF3435, 0xef3f00db}, -{12100000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 121_quant.dat*/ - - -/*case 12200000:*/ -/* BEGIN - DIF BPF register values from 122_quant.dat*/ -{12200000, DIF_BPF_COEFF01, 0x0000fffd}, -{12200000, DIF_BPF_COEFF23, 0xfffe0011}, -{12200000, DIF_BPF_COEFF45, 0x000cffcc}, -{12200000, DIF_BPF_COEFF67, 0xffdb0071}, -{12200000, DIF_BPF_COEFF89, 0x0058ff32}, -{12200000, DIF_BPF_COEFF1011, 0xff4f014a}, -{12200000, DIF_BPF_COEFF1213, 0x013cfe1f}, -{12200000, DIF_BPF_COEFF1415, 0xfdfb028a}, -{12200000, DIF_BPF_COEFF1617, 0x0311fcc9}, -{12200000, DIF_BPF_COEFF1819, 0xfb9d03d6}, -{12200000, DIF_BPF_COEFF2021, 0x05f4fbad}, -{12200000, DIF_BPF_COEFF2223, 0xf848049d}, -{12200000, DIF_BPF_COEFF2425, 0x0999fb5b}, -{12200000, DIF_BPF_COEFF2627, 0xf4820461}, -{12200000, DIF_BPF_COEFF2829, 0x0d46fc32}, -{12200000, DIF_BPF_COEFF3031, 0xf12d02f4}, -{12200000, DIF_BPF_COEFF3233, 0x1007fe21}, -{12200000, DIF_BPF_COEFF3435, 0xef3600a4}, -{12200000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 122_quant.dat*/ - - -/*case 12300000:*/ -/* BEGIN - DIF BPF register values from 123_quant.dat*/ -{12300000, DIF_BPF_COEFF01, 0x0000fffe}, -{12300000, DIF_BPF_COEFF23, 0xfffa000e}, -{12300000, DIF_BPF_COEFF45, 0x0017ffd9}, -{12300000, DIF_BPF_COEFF67, 0xffc10055}, -{12300000, DIF_BPF_COEFF89, 0x0088ff68}, -{12300000, DIF_BPF_COEFF1011, 0xff0400f0}, -{12300000, DIF_BPF_COEFF1213, 0x01a6fea7}, -{12300000, DIF_BPF_COEFF1415, 0xfd7501cc}, -{12300000, DIF_BPF_COEFF1617, 0x03b0fdc0}, -{12300000, DIF_BPF_COEFF1819, 0xfaef02a8}, -{12300000, DIF_BPF_COEFF2021, 0x06a7fd07}, -{12300000, DIF_BPF_COEFF2223, 0xf79d0326}, -{12300000, DIF_BPF_COEFF2425, 0x0a31fcda}, -{12300000, DIF_BPF_COEFF2627, 0xf40702f3}, -{12300000, DIF_BPF_COEFF2829, 0x0d9ffd72}, -{12300000, DIF_BPF_COEFF3031, 0xf0f601fa}, -{12300000, DIF_BPF_COEFF3233, 0x1021fec0}, -{12300000, DIF_BPF_COEFF3435, 0xef2f006d}, -{12300000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 123_quant.dat*/ - - -/*case 12400000:*/ -/* BEGIN - DIF BPF register values from 124_quant.dat*/ -{12400000, DIF_BPF_COEFF01, 0x0001ffff}, -{12400000, DIF_BPF_COEFF23, 0xfff80007}, -{12400000, DIF_BPF_COEFF45, 0x001fffeb}, -{12400000, DIF_BPF_COEFF67, 0xffaf002d}, -{12400000, DIF_BPF_COEFF89, 0x00a8ffb0}, -{12400000, DIF_BPF_COEFF1011, 0xfed3007e}, -{12400000, DIF_BPF_COEFF1213, 0x01e9ff4c}, -{12400000, DIF_BPF_COEFF1415, 0xfd2000ee}, -{12400000, DIF_BPF_COEFF1617, 0x0413fed8}, -{12400000, DIF_BPF_COEFF1819, 0xfa82015c}, -{12400000, DIF_BPF_COEFF2021, 0x0715fe7d}, -{12400000, DIF_BPF_COEFF2223, 0xf7340198}, -{12400000, DIF_BPF_COEFF2425, 0x0a8dfe69}, -{12400000, DIF_BPF_COEFF2627, 0xf3bd017c}, -{12400000, DIF_BPF_COEFF2829, 0x0dd5feb8}, -{12400000, DIF_BPF_COEFF3031, 0xf0d500fd}, -{12400000, DIF_BPF_COEFF3233, 0x1031ff60}, -{12400000, DIF_BPF_COEFF3435, 0xef2b0037}, -{12400000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 124_quant.dat*/ - - -/*case 12500000:*/ -/* BEGIN - DIF BPF register values from 125_quant.dat*/ -{12500000, DIF_BPF_COEFF01, 0x00010000}, -{12500000, DIF_BPF_COEFF23, 0xfff70000}, -{12500000, DIF_BPF_COEFF45, 0x00220000}, -{12500000, DIF_BPF_COEFF67, 0xffa90000}, -{12500000, DIF_BPF_COEFF89, 0x00b30000}, -{12500000, DIF_BPF_COEFF1011, 0xfec20000}, -{12500000, DIF_BPF_COEFF1213, 0x02000000}, -{12500000, DIF_BPF_COEFF1415, 0xfd030000}, -{12500000, DIF_BPF_COEFF1617, 0x04350000}, -{12500000, DIF_BPF_COEFF1819, 0xfa5e0000}, -{12500000, DIF_BPF_COEFF2021, 0x073b0000}, -{12500000, DIF_BPF_COEFF2223, 0xf7110000}, -{12500000, DIF_BPF_COEFF2425, 0x0aac0000}, -{12500000, DIF_BPF_COEFF2627, 0xf3a40000}, -{12500000, DIF_BPF_COEFF2829, 0x0de70000}, -{12500000, DIF_BPF_COEFF3031, 0xf0c90000}, -{12500000, DIF_BPF_COEFF3233, 0x10360000}, -{12500000, DIF_BPF_COEFF3435, 0xef290000}, -{12500000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 125_quant.dat*/ - - -/*case 12600000:*/ -/* BEGIN - DIF BPF register values from 126_quant.dat*/ -{12600000, DIF_BPF_COEFF01, 0x00010001}, -{12600000, DIF_BPF_COEFF23, 0xfff8fff9}, -{12600000, DIF_BPF_COEFF45, 0x001f0015}, -{12600000, DIF_BPF_COEFF67, 0xffafffd3}, -{12600000, DIF_BPF_COEFF89, 0x00a80050}, -{12600000, DIF_BPF_COEFF1011, 0xfed3ff82}, -{12600000, DIF_BPF_COEFF1213, 0x01e900b4}, -{12600000, DIF_BPF_COEFF1415, 0xfd20ff12}, -{12600000, DIF_BPF_COEFF1617, 0x04130128}, -{12600000, DIF_BPF_COEFF1819, 0xfa82fea4}, -{12600000, DIF_BPF_COEFF2021, 0x07150183}, -{12600000, DIF_BPF_COEFF2223, 0xf734fe68}, -{12600000, DIF_BPF_COEFF2425, 0x0a8d0197}, -{12600000, DIF_BPF_COEFF2627, 0xf3bdfe84}, -{12600000, DIF_BPF_COEFF2829, 0x0dd50148}, -{12600000, DIF_BPF_COEFF3031, 0xf0d5ff03}, -{12600000, DIF_BPF_COEFF3233, 0x103100a0}, -{12600000, DIF_BPF_COEFF3435, 0xef2bffc9}, -{12600000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 126_quant.dat*/ - - -/*case 12700000:*/ -/* BEGIN - DIF BPF register values from 127_quant.dat*/ -{12700000, DIF_BPF_COEFF01, 0x00000002}, -{12700000, DIF_BPF_COEFF23, 0xfffafff2}, -{12700000, DIF_BPF_COEFF45, 0x00170027}, -{12700000, DIF_BPF_COEFF67, 0xffc1ffab}, -{12700000, DIF_BPF_COEFF89, 0x00880098}, -{12700000, DIF_BPF_COEFF1011, 0xff04ff10}, -{12700000, DIF_BPF_COEFF1213, 0x01a60159}, -{12700000, DIF_BPF_COEFF1415, 0xfd75fe34}, -{12700000, DIF_BPF_COEFF1617, 0x03b00240}, -{12700000, DIF_BPF_COEFF1819, 0xfaeffd58}, -{12700000, DIF_BPF_COEFF2021, 0x06a702f9}, -{12700000, DIF_BPF_COEFF2223, 0xf79dfcda}, -{12700000, DIF_BPF_COEFF2425, 0x0a310326}, -{12700000, DIF_BPF_COEFF2627, 0xf407fd0d}, -{12700000, DIF_BPF_COEFF2829, 0x0d9f028e}, -{12700000, DIF_BPF_COEFF3031, 0xf0f6fe06}, -{12700000, DIF_BPF_COEFF3233, 0x10210140}, -{12700000, DIF_BPF_COEFF3435, 0xef2fff93}, -{12700000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 127_quant.dat*/ - - -/*case 12800000:*/ -/* BEGIN - DIF BPF register values from 128_quant.dat*/ -{12800000, DIF_BPF_COEFF01, 0x00000003}, -{12800000, DIF_BPF_COEFF23, 0xfffeffef}, -{12800000, DIF_BPF_COEFF45, 0x000c0034}, -{12800000, DIF_BPF_COEFF67, 0xffdbff8f}, -{12800000, DIF_BPF_COEFF89, 0x005800ce}, -{12800000, DIF_BPF_COEFF1011, 0xff4ffeb6}, -{12800000, DIF_BPF_COEFF1213, 0x013c01e1}, -{12800000, DIF_BPF_COEFF1415, 0xfdfbfd76}, -{12800000, DIF_BPF_COEFF1617, 0x03110337}, -{12800000, DIF_BPF_COEFF1819, 0xfb9dfc2a}, -{12800000, DIF_BPF_COEFF2021, 0x05f40453}, -{12800000, DIF_BPF_COEFF2223, 0xf848fb63}, -{12800000, DIF_BPF_COEFF2425, 0x099904a5}, -{12800000, DIF_BPF_COEFF2627, 0xf482fb9f}, -{12800000, DIF_BPF_COEFF2829, 0x0d4603ce}, -{12800000, DIF_BPF_COEFF3031, 0xf12dfd0c}, -{12800000, DIF_BPF_COEFF3233, 0x100701df}, -{12800000, DIF_BPF_COEFF3435, 0xef36ff5c}, -{12800000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 128_quant.dat*/ - - -/*case 12900000:*/ -/* BEGIN - DIF BPF register values from 129_quant.dat*/ -{12900000, DIF_BPF_COEFF01, 0x00000003}, -{12900000, DIF_BPF_COEFF23, 0x0001ffee}, -{12900000, DIF_BPF_COEFF45, 0xffff0038}, -{12900000, DIF_BPF_COEFF67, 0xfffbff82}, -{12900000, DIF_BPF_COEFF89, 0x001d00ec}, -{12900000, DIF_BPF_COEFF1011, 0xffadfe7c}, -{12900000, DIF_BPF_COEFF1213, 0x00b70242}, -{12900000, DIF_BPF_COEFF1415, 0xfea9fce5}, -{12900000, DIF_BPF_COEFF1617, 0x024103ff}, -{12900000, DIF_BPF_COEFF1819, 0xfc85fb2a}, -{12900000, DIF_BPF_COEFF2021, 0x05040587}, -{12900000, DIF_BPF_COEFF2223, 0xf930fa0a}, -{12900000, DIF_BPF_COEFF2425, 0x08ca060e}, -{12900000, DIF_BPF_COEFF2627, 0xf52bfa40}, -{12900000, DIF_BPF_COEFF2829, 0x0ccb0507}, -{12900000, DIF_BPF_COEFF3031, 0xf179fc15}, -{12900000, DIF_BPF_COEFF3233, 0x0fe3027d}, -{12900000, DIF_BPF_COEFF3435, 0xef3fff25}, -{12900000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 129_quant.dat*/ - - -/*case 113000000:*/ -/* BEGIN - DIF BPF register values from 130_quant.dat*/ -{13000000, DIF_BPF_COEFF01, 0x00000002}, -{13000000, DIF_BPF_COEFF23, 0x0005fff0}, -{13000000, DIF_BPF_COEFF45, 0xfff20034}, -{13000000, DIF_BPF_COEFF67, 0x001bff85}, -{13000000, DIF_BPF_COEFF89, 0xffdf00f0}, -{13000000, DIF_BPF_COEFF1011, 0x0014fe68}, -{13000000, DIF_BPF_COEFF1213, 0x00200272}, -{13000000, DIF_BPF_COEFF1415, 0xff71fc8b}, -{13000000, DIF_BPF_COEFF1617, 0x014d048d}, -{13000000, DIF_BPF_COEFF1819, 0xfd9afa61}, -{13000000, DIF_BPF_COEFF2021, 0x03e00688}, -{13000000, DIF_BPF_COEFF2223, 0xfa4ef8da}, -{13000000, DIF_BPF_COEFF2425, 0x07c80759}, -{13000000, DIF_BPF_COEFF2627, 0xf600f8f4}, -{13000000, DIF_BPF_COEFF2829, 0x0c2f0637}, -{13000000, DIF_BPF_COEFF3031, 0xf1dbfb22}, -{13000000, DIF_BPF_COEFF3233, 0x0fb4031b}, -{13000000, DIF_BPF_COEFF3435, 0xef4bfeef}, -{13000000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 130_quant.dat*/ - - -/*case 13100000:*/ -/* BEGIN - DIF BPF register values from 131_quant.dat*/ -{13100000, DIF_BPF_COEFF01, 0xffff0001}, -{13100000, DIF_BPF_COEFF23, 0x0007fff5}, -{13100000, DIF_BPF_COEFF45, 0xffe70028}, -{13100000, DIF_BPF_COEFF67, 0x0037ff98}, -{13100000, DIF_BPF_COEFF89, 0xffa400d8}, -{13100000, DIF_BPF_COEFF1011, 0x0079fe7c}, -{13100000, DIF_BPF_COEFF1213, 0xff87026f}, -{13100000, DIF_BPF_COEFF1415, 0x0043fc6e}, -{13100000, DIF_BPF_COEFF1617, 0x004404da}, -{13100000, DIF_BPF_COEFF1819, 0xfecef9da}, -{13100000, DIF_BPF_COEFF2021, 0x0294074e}, -{13100000, DIF_BPF_COEFF2223, 0xfb99f7db}, -{13100000, DIF_BPF_COEFF2425, 0x06980881}, -{13100000, DIF_BPF_COEFF2627, 0xf6fef7be}, -{13100000, DIF_BPF_COEFF2829, 0x0b730759}, -{13100000, DIF_BPF_COEFF3031, 0xf251fa33}, -{13100000, DIF_BPF_COEFF3233, 0x0f7b03b8}, -{13100000, DIF_BPF_COEFF3435, 0xef5afeb8}, -{13100000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 131_quant.dat*/ - - -/*case 13200000:*/ -/* BEGIN - DIF BPF register values from 132_quant.dat*/ -{13200000, DIF_BPF_COEFF01, 0xffff0000}, -{13200000, DIF_BPF_COEFF23, 0x0008fffc}, -{13200000, DIF_BPF_COEFF45, 0xffe00017}, -{13200000, DIF_BPF_COEFF67, 0x004cffb9}, -{13200000, DIF_BPF_COEFF89, 0xff7500a8}, -{13200000, DIF_BPF_COEFF1011, 0x00d1feb6}, -{13200000, DIF_BPF_COEFF1213, 0xfef90238}, -{13200000, DIF_BPF_COEFF1415, 0x0111fc91}, -{13200000, DIF_BPF_COEFF1617, 0xff3604df}, -{13200000, DIF_BPF_COEFF1819, 0x0012f99b}, -{13200000, DIF_BPF_COEFF2021, 0x012d07d2}, -{13200000, DIF_BPF_COEFF2223, 0xfd07f714}, -{13200000, DIF_BPF_COEFF2425, 0x0542097e}, -{13200000, DIF_BPF_COEFF2627, 0xf81ff6a4}, -{13200000, DIF_BPF_COEFF2829, 0x0a9a086e}, -{13200000, DIF_BPF_COEFF3031, 0xf2dbf94b}, -{13200000, DIF_BPF_COEFF3233, 0x0f380453}, -{13200000, DIF_BPF_COEFF3435, 0xef6cfe82}, -{13200000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 132_quant.dat*/ - - -/*case 13300000:*/ -/* BEGIN - DIF BPF register values from 133_quant.dat*/ -{13300000, DIF_BPF_COEFF01, 0xffffffff}, -{13300000, DIF_BPF_COEFF23, 0x00080003}, -{13300000, DIF_BPF_COEFF45, 0xffde0001}, -{13300000, DIF_BPF_COEFF67, 0x0056ffe3}, -{13300000, DIF_BPF_COEFF89, 0xff570064}, -{13300000, DIF_BPF_COEFF1011, 0x0113ff10}, -{13300000, DIF_BPF_COEFF1213, 0xfe8201d2}, -{13300000, DIF_BPF_COEFF1415, 0x01cafcf0}, -{13300000, DIF_BPF_COEFF1617, 0xfe35049e}, -{13300000, DIF_BPF_COEFF1819, 0x0155f9a6}, -{13300000, DIF_BPF_COEFF2021, 0xffba080e}, -{13300000, DIF_BPF_COEFF2223, 0xfe8cf689}, -{13300000, DIF_BPF_COEFF2425, 0x03ce0a4e}, -{13300000, DIF_BPF_COEFF2627, 0xf961f5a8}, -{13300000, DIF_BPF_COEFF2829, 0x09a50971}, -{13300000, DIF_BPF_COEFF3031, 0xf379f869}, -{13300000, DIF_BPF_COEFF3233, 0x0eeb04ec}, -{13300000, DIF_BPF_COEFF3435, 0xef80fe4b}, -{13300000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 133_quant.dat*/ - - -/*case 13400000:*/ -/* BEGIN - DIF BPF register values from 134_quant.dat*/ -{13400000, DIF_BPF_COEFF01, 0x0000fffe}, -{13400000, DIF_BPF_COEFF23, 0x0007000a}, -{13400000, DIF_BPF_COEFF45, 0xffe2ffec}, -{13400000, DIF_BPF_COEFF67, 0x00540012}, -{13400000, DIF_BPF_COEFF89, 0xff4e0015}, -{13400000, DIF_BPF_COEFF1011, 0x0137ff82}, -{13400000, DIF_BPF_COEFF1213, 0xfe2e0145}, -{13400000, DIF_BPF_COEFF1415, 0x0260fd86}, -{13400000, DIF_BPF_COEFF1617, 0xfd51041a}, -{13400000, DIF_BPF_COEFF1819, 0x0287f9fb}, -{13400000, DIF_BPF_COEFF2021, 0xfe4a0802}, -{13400000, DIF_BPF_COEFF2223, 0x001df63f}, -{13400000, DIF_BPF_COEFF2425, 0x02430aeb}, -{13400000, DIF_BPF_COEFF2627, 0xfabdf4ce}, -{13400000, DIF_BPF_COEFF2829, 0x08970a62}, -{13400000, DIF_BPF_COEFF3031, 0xf428f78f}, -{13400000, DIF_BPF_COEFF3233, 0x0e950584}, -{13400000, DIF_BPF_COEFF3435, 0xef97fe15}, -{13400000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 134_quant.dat*/ - - -/*case 13500000:*/ -/* BEGIN - DIF BPF register values from 135_quant.dat*/ -{13500000, DIF_BPF_COEFF01, 0x0000fffd}, -{13500000, DIF_BPF_COEFF23, 0x0004000f}, -{13500000, DIF_BPF_COEFF45, 0xffeaffda}, -{13500000, DIF_BPF_COEFF67, 0x0046003d}, -{13500000, DIF_BPF_COEFF89, 0xff5affc4}, -{13500000, DIF_BPF_COEFF1011, 0x013b0000}, -{13500000, DIF_BPF_COEFF1213, 0xfe04009d}, -{13500000, DIF_BPF_COEFF1415, 0x02c8fe48}, -{13500000, DIF_BPF_COEFF1617, 0xfc99035a}, -{13500000, DIF_BPF_COEFF1819, 0x0397fa96}, -{13500000, DIF_BPF_COEFF2021, 0xfcec07ad}, -{13500000, DIF_BPF_COEFF2223, 0x01adf637}, -{13500000, DIF_BPF_COEFF2425, 0x00ac0b53}, -{13500000, DIF_BPF_COEFF2627, 0xfc2ef419}, -{13500000, DIF_BPF_COEFF2829, 0x07730b3e}, -{13500000, DIF_BPF_COEFF3031, 0xf4e9f6bd}, -{13500000, DIF_BPF_COEFF3233, 0x0e35061a}, -{13500000, DIF_BPF_COEFF3435, 0xefb1fddf}, -{13500000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 135_quant.dat*/ - - -/*case 13600000:*/ -/* BEGIN - DIF BPF register values from 136_quant.dat*/ -{13600000, DIF_BPF_COEFF01, 0x0000fffd}, -{13600000, DIF_BPF_COEFF23, 0x00000012}, -{13600000, DIF_BPF_COEFF45, 0xfff6ffcd}, -{13600000, DIF_BPF_COEFF67, 0x002f0061}, -{13600000, DIF_BPF_COEFF89, 0xff7bff79}, -{13600000, DIF_BPF_COEFF1011, 0x011e007e}, -{13600000, DIF_BPF_COEFF1213, 0xfe08ffe8}, -{13600000, DIF_BPF_COEFF1415, 0x02f9ff28}, -{13600000, DIF_BPF_COEFF1617, 0xfc17026a}, -{13600000, DIF_BPF_COEFF1819, 0x0479fb70}, -{13600000, DIF_BPF_COEFF2021, 0xfbad0713}, -{13600000, DIF_BPF_COEFF2223, 0x032ff672}, -{13600000, DIF_BPF_COEFF2425, 0xff100b83}, -{13600000, DIF_BPF_COEFF2627, 0xfdaff38b}, -{13600000, DIF_BPF_COEFF2829, 0x063c0c04}, -{13600000, DIF_BPF_COEFF3031, 0xf5baf5f5}, -{13600000, DIF_BPF_COEFF3233, 0x0dcc06ae}, -{13600000, DIF_BPF_COEFF3435, 0xefcdfda8}, -{13600000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 136_quant.dat*/ - - -/*case 13700000:*/ -/* BEGIN - DIF BPF register values from 137_quant.dat*/ -{13700000, DIF_BPF_COEFF01, 0x0000fffd}, -{13700000, DIF_BPF_COEFF23, 0xfffd0012}, -{13700000, DIF_BPF_COEFF45, 0x0004ffc8}, -{13700000, DIF_BPF_COEFF67, 0x00100078}, -{13700000, DIF_BPF_COEFF89, 0xffacff3e}, -{13700000, DIF_BPF_COEFF1011, 0x00e200f0}, -{13700000, DIF_BPF_COEFF1213, 0xfe39ff35}, -{13700000, DIF_BPF_COEFF1415, 0x02f10017}, -{13700000, DIF_BPF_COEFF1617, 0xfbd30156}, -{13700000, DIF_BPF_COEFF1819, 0x0521fc7f}, -{13700000, DIF_BPF_COEFF2021, 0xfa9c0638}, -{13700000, DIF_BPF_COEFF2223, 0x0499f6ee}, -{13700000, DIF_BPF_COEFF2425, 0xfd7a0b7c}, -{13700000, DIF_BPF_COEFF2627, 0xff39f325}, -{13700000, DIF_BPF_COEFF2829, 0x04f40cb3}, -{13700000, DIF_BPF_COEFF3031, 0xf69af537}, -{13700000, DIF_BPF_COEFF3233, 0x0d5a073f}, -{13700000, DIF_BPF_COEFF3435, 0xefecfd72}, -{13700000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 137_quant.dat*/ - - -/*case 13800000:*/ -/* BEGIN - DIF BPF register values from 138_quant.dat*/ -{13800000, DIF_BPF_COEFF01, 0x0001fffe}, -{13800000, DIF_BPF_COEFF23, 0xfffa000e}, -{13800000, DIF_BPF_COEFF45, 0x0011ffcb}, -{13800000, DIF_BPF_COEFF67, 0xfff0007f}, -{13800000, DIF_BPF_COEFF89, 0xffe7ff19}, -{13800000, DIF_BPF_COEFF1011, 0x008f014a}, -{13800000, DIF_BPF_COEFF1213, 0xfe94fe93}, -{13800000, DIF_BPF_COEFF1415, 0x02b00105}, -{13800000, DIF_BPF_COEFF1617, 0xfbd3002f}, -{13800000, DIF_BPF_COEFF1819, 0x0585fdb7}, -{13800000, DIF_BPF_COEFF2021, 0xf9c10525}, -{13800000, DIF_BPF_COEFF2223, 0x05def7a8}, -{13800000, DIF_BPF_COEFF2425, 0xfbf20b3c}, -{13800000, DIF_BPF_COEFF2627, 0x00c7f2e9}, -{13800000, DIF_BPF_COEFF2829, 0x03a00d48}, -{13800000, DIF_BPF_COEFF3031, 0xf787f484}, -{13800000, DIF_BPF_COEFF3233, 0x0cdf07cd}, -{13800000, DIF_BPF_COEFF3435, 0xf00dfd3c}, -{13800000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 138_quant.dat*/ - - -/*case 13900000:*/ -/* BEGIN - DIF BPF register values from 139_quant.dat*/ -{13900000, DIF_BPF_COEFF01, 0x00010000}, -{13900000, DIF_BPF_COEFF23, 0xfff80008}, -{13900000, DIF_BPF_COEFF45, 0x001bffd7}, -{13900000, DIF_BPF_COEFF67, 0xffd10076}, -{13900000, DIF_BPF_COEFF89, 0x0026ff0e}, -{13900000, DIF_BPF_COEFF1011, 0x002c0184}, -{13900000, DIF_BPF_COEFF1213, 0xff0ffe10}, -{13900000, DIF_BPF_COEFF1415, 0x023b01e0}, -{13900000, DIF_BPF_COEFF1617, 0xfc17ff06}, -{13900000, DIF_BPF_COEFF1819, 0x05a2ff09}, -{13900000, DIF_BPF_COEFF2021, 0xf92703e4}, -{13900000, DIF_BPF_COEFF2223, 0x06f4f89b}, -{13900000, DIF_BPF_COEFF2425, 0xfa820ac5}, -{13900000, DIF_BPF_COEFF2627, 0x0251f2d9}, -{13900000, DIF_BPF_COEFF2829, 0x02430dc3}, -{13900000, DIF_BPF_COEFF3031, 0xf881f3dc}, -{13900000, DIF_BPF_COEFF3233, 0x0c5c0859}, -{13900000, DIF_BPF_COEFF3435, 0xf031fd06}, -{13900000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 139_quant.dat*/ - - -/*case 14000000:*/ -/* BEGIN - DIF BPF register values from 140_quant.dat*/ -{14000000, DIF_BPF_COEFF01, 0x00010001}, -{14000000, DIF_BPF_COEFF23, 0xfff80001}, -{14000000, DIF_BPF_COEFF45, 0x0021ffe8}, -{14000000, DIF_BPF_COEFF67, 0xffba005d}, -{14000000, DIF_BPF_COEFF89, 0x0060ff1f}, -{14000000, DIF_BPF_COEFF1011, 0xffc40198}, -{14000000, DIF_BPF_COEFF1213, 0xffa0fdb5}, -{14000000, DIF_BPF_COEFF1415, 0x019a029a}, -{14000000, DIF_BPF_COEFF1617, 0xfc99fdea}, -{14000000, DIF_BPF_COEFF1819, 0x05750067}, -{14000000, DIF_BPF_COEFF2021, 0xf8d4027f}, -{14000000, DIF_BPF_COEFF2223, 0x07d4f9c0}, -{14000000, DIF_BPF_COEFF2425, 0xf9320a1a}, -{14000000, DIF_BPF_COEFF2627, 0x03d2f2f3}, -{14000000, DIF_BPF_COEFF2829, 0x00df0e22}, -{14000000, DIF_BPF_COEFF3031, 0xf986f341}, -{14000000, DIF_BPF_COEFF3233, 0x0bd108e2}, -{14000000, DIF_BPF_COEFF3435, 0xf058fcd1}, -{14000000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 140_quant.dat*/ - - -/*case 14100000:*/ -/* BEGIN - DIF BPF register values from 141_quant.dat*/ -{14100000, DIF_BPF_COEFF01, 0x00000002}, -{14100000, DIF_BPF_COEFF23, 0xfff9fffa}, -{14100000, DIF_BPF_COEFF45, 0x0021fffd}, -{14100000, DIF_BPF_COEFF67, 0xffac0038}, -{14100000, DIF_BPF_COEFF89, 0x008eff4a}, -{14100000, DIF_BPF_COEFF1011, 0xff630184}, -{14100000, DIF_BPF_COEFF1213, 0x003afd8b}, -{14100000, DIF_BPF_COEFF1415, 0x00da0326}, -{14100000, DIF_BPF_COEFF1617, 0xfd51fced}, -{14100000, DIF_BPF_COEFF1819, 0x050101c0}, -{14100000, DIF_BPF_COEFF2021, 0xf8cb0103}, -{14100000, DIF_BPF_COEFF2223, 0x0876fb10}, -{14100000, DIF_BPF_COEFF2425, 0xf80a093e}, -{14100000, DIF_BPF_COEFF2627, 0x0543f338}, -{14100000, DIF_BPF_COEFF2829, 0xff7a0e66}, -{14100000, DIF_BPF_COEFF3031, 0xfa94f2b2}, -{14100000, DIF_BPF_COEFF3233, 0x0b3f0967}, -{14100000, DIF_BPF_COEFF3435, 0xf081fc9b}, -{14100000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 141_quant.dat*/ - - -/*case 14200000:*/ -/* BEGIN - DIF BPF register values from 142_quant.dat*/ -{14200000, DIF_BPF_COEFF01, 0x00000003}, -{14200000, DIF_BPF_COEFF23, 0xfffbfff3}, -{14200000, DIF_BPF_COEFF45, 0x001d0013}, -{14200000, DIF_BPF_COEFF67, 0xffaa000b}, -{14200000, DIF_BPF_COEFF89, 0x00aaff89}, -{14200000, DIF_BPF_COEFF1011, 0xff13014a}, -{14200000, DIF_BPF_COEFF1213, 0x00cefd95}, -{14200000, DIF_BPF_COEFF1415, 0x000a037b}, -{14200000, DIF_BPF_COEFF1617, 0xfe35fc1d}, -{14200000, DIF_BPF_COEFF1819, 0x044c0305}, -{14200000, DIF_BPF_COEFF2021, 0xf90cff7e}, -{14200000, DIF_BPF_COEFF2223, 0x08d5fc81}, -{14200000, DIF_BPF_COEFF2425, 0xf7100834}, -{14200000, DIF_BPF_COEFF2627, 0x069ff3a7}, -{14200000, DIF_BPF_COEFF2829, 0xfe160e8d}, -{14200000, DIF_BPF_COEFF3031, 0xfbaaf231}, -{14200000, DIF_BPF_COEFF3233, 0x0aa509e9}, -{14200000, DIF_BPF_COEFF3435, 0xf0adfc65}, -{14200000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 142_quant.dat*/ - - -/*case 14300000:*/ -/* BEGIN - DIF BPF register values from 143_quant.dat*/ -{14300000, DIF_BPF_COEFF01, 0x00000003}, -{14300000, DIF_BPF_COEFF23, 0xffffffef}, -{14300000, DIF_BPF_COEFF45, 0x00140025}, -{14300000, DIF_BPF_COEFF67, 0xffb4ffdd}, -{14300000, DIF_BPF_COEFF89, 0x00b2ffd6}, -{14300000, DIF_BPF_COEFF1011, 0xfedb00f0}, -{14300000, DIF_BPF_COEFF1213, 0x0150fdd3}, -{14300000, DIF_BPF_COEFF1415, 0xff380391}, -{14300000, DIF_BPF_COEFF1617, 0xff36fb85}, -{14300000, DIF_BPF_COEFF1819, 0x035e0426}, -{14300000, DIF_BPF_COEFF2021, 0xf994fdfe}, -{14300000, DIF_BPF_COEFF2223, 0x08eefe0b}, -{14300000, DIF_BPF_COEFF2425, 0xf6490702}, -{14300000, DIF_BPF_COEFF2627, 0x07e1f43e}, -{14300000, DIF_BPF_COEFF2829, 0xfcb60e97}, -{14300000, DIF_BPF_COEFF3031, 0xfcc6f1be}, -{14300000, DIF_BPF_COEFF3233, 0x0a040a67}, -{14300000, DIF_BPF_COEFF3435, 0xf0dbfc30}, -{14300000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 143_quant.dat*/ - - -/*case 14400000:*/ -/* BEGIN - DIF BPF register values from 144_quant.dat*/ -{14400000, DIF_BPF_COEFF01, 0x00000003}, -{14400000, DIF_BPF_COEFF23, 0x0002ffee}, -{14400000, DIF_BPF_COEFF45, 0x00070033}, -{14400000, DIF_BPF_COEFF67, 0xffc9ffb4}, -{14400000, DIF_BPF_COEFF89, 0x00a40027}, -{14400000, DIF_BPF_COEFF1011, 0xfec3007e}, -{14400000, DIF_BPF_COEFF1213, 0x01b4fe3f}, -{14400000, DIF_BPF_COEFF1415, 0xfe760369}, -{14400000, DIF_BPF_COEFF1617, 0x0044fb2e}, -{14400000, DIF_BPF_COEFF1819, 0x02450518}, -{14400000, DIF_BPF_COEFF2021, 0xfa5ffc90}, -{14400000, DIF_BPF_COEFF2223, 0x08c1ffa1}, -{14400000, DIF_BPF_COEFF2425, 0xf5bc05ae}, -{14400000, DIF_BPF_COEFF2627, 0x0902f4fc}, -{14400000, DIF_BPF_COEFF2829, 0xfb600e85}, -{14400000, DIF_BPF_COEFF3031, 0xfde7f15a}, -{14400000, DIF_BPF_COEFF3233, 0x095d0ae2}, -{14400000, DIF_BPF_COEFF3435, 0xf10cfbfb}, -{14400000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 144_quant.dat*/ - - -/*case 14500000:*/ -/* BEGIN - DIF BPF register values from 145_quant.dat*/ -{14500000, DIF_BPF_COEFF01, 0xffff0002}, -{14500000, DIF_BPF_COEFF23, 0x0005ffef}, -{14500000, DIF_BPF_COEFF45, 0xfffa0038}, -{14500000, DIF_BPF_COEFF67, 0xffe5ff95}, -{14500000, DIF_BPF_COEFF89, 0x00820074}, -{14500000, DIF_BPF_COEFF1011, 0xfecc0000}, -{14500000, DIF_BPF_COEFF1213, 0x01f0fed0}, -{14500000, DIF_BPF_COEFF1415, 0xfdd20304}, -{14500000, DIF_BPF_COEFF1617, 0x014dfb1d}, -{14500000, DIF_BPF_COEFF1819, 0x010e05ce}, -{14500000, DIF_BPF_COEFF2021, 0xfb64fb41}, -{14500000, DIF_BPF_COEFF2223, 0x084e013b}, -{14500000, DIF_BPF_COEFF2425, 0xf569043e}, -{14500000, DIF_BPF_COEFF2627, 0x0a00f5dd}, -{14500000, DIF_BPF_COEFF2829, 0xfa150e55}, -{14500000, DIF_BPF_COEFF3031, 0xff0bf104}, -{14500000, DIF_BPF_COEFF3233, 0x08b00b59}, -{14500000, DIF_BPF_COEFF3435, 0xf13ffbc6}, -{14500000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 145_quant.dat*/ - - -/*case 14600000:*/ -/* BEGIN - DIF BPF register values from 146_quant.dat*/ -{14600000, DIF_BPF_COEFF01, 0xffff0001}, -{14600000, DIF_BPF_COEFF23, 0x0008fff4}, -{14600000, DIF_BPF_COEFF45, 0xffed0035}, -{14600000, DIF_BPF_COEFF67, 0x0005ff83}, -{14600000, DIF_BPF_COEFF89, 0x005000b4}, -{14600000, DIF_BPF_COEFF1011, 0xfef6ff82}, -{14600000, DIF_BPF_COEFF1213, 0x01ffff7a}, -{14600000, DIF_BPF_COEFF1415, 0xfd580269}, -{14600000, DIF_BPF_COEFF1617, 0x0241fb53}, -{14600000, DIF_BPF_COEFF1819, 0xffca0640}, -{14600000, DIF_BPF_COEFF2021, 0xfc99fa1e}, -{14600000, DIF_BPF_COEFF2223, 0x079a02cb}, -{14600000, DIF_BPF_COEFF2425, 0xf55502ba}, -{14600000, DIF_BPF_COEFF2627, 0x0ad5f6e0}, -{14600000, DIF_BPF_COEFF2829, 0xf8d90e0a}, -{14600000, DIF_BPF_COEFF3031, 0x0031f0bd}, -{14600000, DIF_BPF_COEFF3233, 0x07fd0bcb}, -{14600000, DIF_BPF_COEFF3435, 0xf174fb91}, -{14600000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 146_quant.dat*/ - - -/*case 14700000:*/ -/* BEGIN - DIF BPF register values from 147_quant.dat*/ -{14700000, DIF_BPF_COEFF01, 0xffffffff}, -{14700000, DIF_BPF_COEFF23, 0x0009fffb}, -{14700000, DIF_BPF_COEFF45, 0xffe4002a}, -{14700000, DIF_BPF_COEFF67, 0x0025ff82}, -{14700000, DIF_BPF_COEFF89, 0x001400e0}, -{14700000, DIF_BPF_COEFF1011, 0xff3cff10}, -{14700000, DIF_BPF_COEFF1213, 0x01e10030}, -{14700000, DIF_BPF_COEFF1415, 0xfd1201a4}, -{14700000, DIF_BPF_COEFF1617, 0x0311fbcd}, -{14700000, DIF_BPF_COEFF1819, 0xfe88066a}, -{14700000, DIF_BPF_COEFF2021, 0xfdf1f92f}, -{14700000, DIF_BPF_COEFF2223, 0x06aa0449}, -{14700000, DIF_BPF_COEFF2425, 0xf57e0128}, -{14700000, DIF_BPF_COEFF2627, 0x0b7ef801}, -{14700000, DIF_BPF_COEFF2829, 0xf7b00da2}, -{14700000, DIF_BPF_COEFF3031, 0x0156f086}, -{14700000, DIF_BPF_COEFF3233, 0x07450c39}, -{14700000, DIF_BPF_COEFF3435, 0xf1acfb5c}, -{14700000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 147_quant.dat*/ - - -/*case 14800000:*/ -/* BEGIN - DIF BPF register values from 148_quant.dat*/ -{14800000, DIF_BPF_COEFF01, 0x0000fffe}, -{14800000, DIF_BPF_COEFF23, 0x00080002}, -{14800000, DIF_BPF_COEFF45, 0xffdf0019}, -{14800000, DIF_BPF_COEFF67, 0x003fff92}, -{14800000, DIF_BPF_COEFF89, 0xffd600f1}, -{14800000, DIF_BPF_COEFF1011, 0xff96feb6}, -{14800000, DIF_BPF_COEFF1213, 0x019700e1}, -{14800000, DIF_BPF_COEFF1415, 0xfd0500c2}, -{14800000, DIF_BPF_COEFF1617, 0x03b0fc84}, -{14800000, DIF_BPF_COEFF1819, 0xfd590649}, -{14800000, DIF_BPF_COEFF2021, 0xff5df87f}, -{14800000, DIF_BPF_COEFF2223, 0x058505aa}, -{14800000, DIF_BPF_COEFF2425, 0xf5e4ff91}, -{14800000, DIF_BPF_COEFF2627, 0x0bf9f93c}, -{14800000, DIF_BPF_COEFF2829, 0xf69d0d20}, -{14800000, DIF_BPF_COEFF3031, 0x0279f05e}, -{14800000, DIF_BPF_COEFF3233, 0x06880ca3}, -{14800000, DIF_BPF_COEFF3435, 0xf1e6fb28}, -{14800000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 148_quant.dat*/ - - -/*case 14900000:*/ -/* BEGIN - DIF BPF register values from 149_quant.dat*/ -{14900000, DIF_BPF_COEFF01, 0x0000fffd}, -{14900000, DIF_BPF_COEFF23, 0x00060009}, -{14900000, DIF_BPF_COEFF45, 0xffdf0004}, -{14900000, DIF_BPF_COEFF67, 0x0051ffb0}, -{14900000, DIF_BPF_COEFF89, 0xff9d00e8}, -{14900000, DIF_BPF_COEFF1011, 0xfffcfe7c}, -{14900000, DIF_BPF_COEFF1213, 0x01280180}, -{14900000, DIF_BPF_COEFF1415, 0xfd32ffd2}, -{14900000, DIF_BPF_COEFF1617, 0x0413fd6e}, -{14900000, DIF_BPF_COEFF1819, 0xfc4d05df}, -{14900000, DIF_BPF_COEFF2021, 0x00d1f812}, -{14900000, DIF_BPF_COEFF2223, 0x043506e4}, -{14900000, DIF_BPF_COEFF2425, 0xf685fdfb}, -{14900000, DIF_BPF_COEFF2627, 0x0c43fa8d}, -{14900000, DIF_BPF_COEFF2829, 0xf5a10c83}, -{14900000, DIF_BPF_COEFF3031, 0x0399f046}, -{14900000, DIF_BPF_COEFF3233, 0x05c70d08}, -{14900000, DIF_BPF_COEFF3435, 0xf222faf3}, -{14900000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 149_quant.dat*/ - - -/*case 15000000:*/ -/* BEGIN - DIF BPF register values from 150_quant.dat*/ -{15000000, DIF_BPF_COEFF01, 0x0000fffd}, -{15000000, DIF_BPF_COEFF23, 0x0003000f}, -{15000000, DIF_BPF_COEFF45, 0xffe5ffef}, -{15000000, DIF_BPF_COEFF67, 0x0057ffd9}, -{15000000, DIF_BPF_COEFF89, 0xff7000c4}, -{15000000, DIF_BPF_COEFF1011, 0x0062fe68}, -{15000000, DIF_BPF_COEFF1213, 0x009e01ff}, -{15000000, DIF_BPF_COEFF1415, 0xfd95fee6}, -{15000000, DIF_BPF_COEFF1617, 0x0435fe7d}, -{15000000, DIF_BPF_COEFF1819, 0xfb710530}, -{15000000, DIF_BPF_COEFF2021, 0x023cf7ee}, -{15000000, DIF_BPF_COEFF2223, 0x02c307ef}, -{15000000, DIF_BPF_COEFF2425, 0xf75efc70}, -{15000000, DIF_BPF_COEFF2627, 0x0c5cfbef}, -{15000000, DIF_BPF_COEFF2829, 0xf4c10bce}, -{15000000, DIF_BPF_COEFF3031, 0x04b3f03f}, -{15000000, DIF_BPF_COEFF3233, 0x05030d69}, -{15000000, DIF_BPF_COEFF3435, 0xf261fabf}, -{15000000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 150_quant.dat*/ - - -/*case 15100000:*/ -/* BEGIN - DIF BPF register values from 151_quant.dat*/ -{15100000, DIF_BPF_COEFF01, 0x0000fffd}, -{15100000, DIF_BPF_COEFF23, 0xffff0012}, -{15100000, DIF_BPF_COEFF45, 0xffefffdc}, -{15100000, DIF_BPF_COEFF67, 0x00510006}, -{15100000, DIF_BPF_COEFF89, 0xff540089}, -{15100000, DIF_BPF_COEFF1011, 0x00befe7c}, -{15100000, DIF_BPF_COEFF1213, 0x00060253}, -{15100000, DIF_BPF_COEFF1415, 0xfe27fe0d}, -{15100000, DIF_BPF_COEFF1617, 0x0413ffa2}, -{15100000, DIF_BPF_COEFF1819, 0xfad10446}, -{15100000, DIF_BPF_COEFF2021, 0x0390f812}, -{15100000, DIF_BPF_COEFF2223, 0x013b08c3}, -{15100000, DIF_BPF_COEFF2425, 0xf868faf6}, -{15100000, DIF_BPF_COEFF2627, 0x0c43fd5f}, -{15100000, DIF_BPF_COEFF2829, 0xf3fd0b02}, -{15100000, DIF_BPF_COEFF3031, 0x05c7f046}, -{15100000, DIF_BPF_COEFF3233, 0x043b0dc4}, -{15100000, DIF_BPF_COEFF3435, 0xf2a1fa8b}, -{15100000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 151_quant.dat*/ - - -/*case 15200000:*/ -/* BEGIN - DIF BPF register values from 152_quant.dat*/ -{15200000, DIF_BPF_COEFF01, 0x0001fffe}, -{15200000, DIF_BPF_COEFF23, 0xfffc0012}, -{15200000, DIF_BPF_COEFF45, 0xfffbffce}, -{15200000, DIF_BPF_COEFF67, 0x003f0033}, -{15200000, DIF_BPF_COEFF89, 0xff4e003f}, -{15200000, DIF_BPF_COEFF1011, 0x0106feb6}, -{15200000, DIF_BPF_COEFF1213, 0xff6e0276}, -{15200000, DIF_BPF_COEFF1415, 0xfeddfd56}, -{15200000, DIF_BPF_COEFF1617, 0x03b000cc}, -{15200000, DIF_BPF_COEFF1819, 0xfa740329}, -{15200000, DIF_BPF_COEFF2021, 0x04bff87f}, -{15200000, DIF_BPF_COEFF2223, 0xffaa095d}, -{15200000, DIF_BPF_COEFF2425, 0xf99ef995}, -{15200000, DIF_BPF_COEFF2627, 0x0bf9fed8}, -{15200000, DIF_BPF_COEFF2829, 0xf3590a1f}, -{15200000, DIF_BPF_COEFF3031, 0x06d2f05e}, -{15200000, DIF_BPF_COEFF3233, 0x03700e1b}, -{15200000, DIF_BPF_COEFF3435, 0xf2e4fa58}, -{15200000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 152_quant.dat*/ - - -/*case 115300000:*/ -/* BEGIN - DIF BPF register values from 153_quant.dat*/ -{15300000, DIF_BPF_COEFF01, 0x0001ffff}, -{15300000, DIF_BPF_COEFF23, 0xfff9000f}, -{15300000, DIF_BPF_COEFF45, 0x0009ffc8}, -{15300000, DIF_BPF_COEFF67, 0x00250059}, -{15300000, DIF_BPF_COEFF89, 0xff5effee}, -{15300000, DIF_BPF_COEFF1011, 0x0132ff10}, -{15300000, DIF_BPF_COEFF1213, 0xfee30265}, -{15300000, DIF_BPF_COEFF1415, 0xffaafccf}, -{15300000, DIF_BPF_COEFF1617, 0x031101eb}, -{15300000, DIF_BPF_COEFF1819, 0xfa6001e8}, -{15300000, DIF_BPF_COEFF2021, 0x05bdf92f}, -{15300000, DIF_BPF_COEFF2223, 0xfe1b09b6}, -{15300000, DIF_BPF_COEFF2425, 0xfafaf852}, -{15300000, DIF_BPF_COEFF2627, 0x0b7e0055}, -{15300000, DIF_BPF_COEFF2829, 0xf2d50929}, -{15300000, DIF_BPF_COEFF3031, 0x07d3f086}, -{15300000, DIF_BPF_COEFF3233, 0x02a30e6c}, -{15300000, DIF_BPF_COEFF3435, 0xf329fa24}, -{15300000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 153_quant.dat*/ - - -/*case 115400000:*/ -/* BEGIN - DIF BPF register values from 154_quant.dat*/ -{15400000, DIF_BPF_COEFF01, 0x00010001}, -{15400000, DIF_BPF_COEFF23, 0xfff80009}, -{15400000, DIF_BPF_COEFF45, 0x0015ffca}, -{15400000, DIF_BPF_COEFF67, 0x00050074}, -{15400000, DIF_BPF_COEFF89, 0xff81ff9f}, -{15400000, DIF_BPF_COEFF1011, 0x013dff82}, -{15400000, DIF_BPF_COEFF1213, 0xfe710221}, -{15400000, DIF_BPF_COEFF1415, 0x007cfc80}, -{15400000, DIF_BPF_COEFF1617, 0x024102ed}, -{15400000, DIF_BPF_COEFF1819, 0xfa940090}, -{15400000, DIF_BPF_COEFF2021, 0x0680fa1e}, -{15400000, DIF_BPF_COEFF2223, 0xfc9b09cd}, -{15400000, DIF_BPF_COEFF2425, 0xfc73f736}, -{15400000, DIF_BPF_COEFF2627, 0x0ad501d0}, -{15400000, DIF_BPF_COEFF2829, 0xf2740820}, -{15400000, DIF_BPF_COEFF3031, 0x08c9f0bd}, -{15400000, DIF_BPF_COEFF3233, 0x01d40eb9}, -{15400000, DIF_BPF_COEFF3435, 0xf371f9f1}, -{15400000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 154_quant.dat*/ - - -/*case 115500000:*/ -/* BEGIN - DIF BPF register values from 155_quant.dat*/ -{15500000, DIF_BPF_COEFF01, 0x00000002}, -{15500000, DIF_BPF_COEFF23, 0xfff80002}, -{15500000, DIF_BPF_COEFF45, 0x001effd5}, -{15500000, DIF_BPF_COEFF67, 0xffe5007f}, -{15500000, DIF_BPF_COEFF89, 0xffb4ff5b}, -{15500000, DIF_BPF_COEFF1011, 0x01280000}, -{15500000, DIF_BPF_COEFF1213, 0xfe2401b0}, -{15500000, DIF_BPF_COEFF1415, 0x0146fc70}, -{15500000, DIF_BPF_COEFF1617, 0x014d03c6}, -{15500000, DIF_BPF_COEFF1819, 0xfb10ff32}, -{15500000, DIF_BPF_COEFF2021, 0x0701fb41}, -{15500000, DIF_BPF_COEFF2223, 0xfb3709a1}, -{15500000, DIF_BPF_COEFF2425, 0xfe00f644}, -{15500000, DIF_BPF_COEFF2627, 0x0a000345}, -{15500000, DIF_BPF_COEFF2829, 0xf2350708}, -{15500000, DIF_BPF_COEFF3031, 0x09b2f104}, -{15500000, DIF_BPF_COEFF3233, 0x01050eff}, -{15500000, DIF_BPF_COEFF3435, 0xf3baf9be}, -{15500000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 155_quant.dat*/ - - -/*case 115600000:*/ -/* BEGIN - DIF BPF register values from 156_quant.dat*/ -{15600000, DIF_BPF_COEFF01, 0x00000003}, -{15600000, DIF_BPF_COEFF23, 0xfff9fffb}, -{15600000, DIF_BPF_COEFF45, 0x0022ffe6}, -{15600000, DIF_BPF_COEFF67, 0xffc9007a}, -{15600000, DIF_BPF_COEFF89, 0xfff0ff29}, -{15600000, DIF_BPF_COEFF1011, 0x00f2007e}, -{15600000, DIF_BPF_COEFF1213, 0xfe01011b}, -{15600000, DIF_BPF_COEFF1415, 0x01f6fc9e}, -{15600000, DIF_BPF_COEFF1617, 0x00440467}, -{15600000, DIF_BPF_COEFF1819, 0xfbccfdde}, -{15600000, DIF_BPF_COEFF2021, 0x0738fc90}, -{15600000, DIF_BPF_COEFF2223, 0xf9f70934}, -{15600000, DIF_BPF_COEFF2425, 0xff99f582}, -{15600000, DIF_BPF_COEFF2627, 0x090204b0}, -{15600000, DIF_BPF_COEFF2829, 0xf21a05e1}, -{15600000, DIF_BPF_COEFF3031, 0x0a8df15a}, -{15600000, DIF_BPF_COEFF3233, 0x00340f41}, -{15600000, DIF_BPF_COEFF3435, 0xf405f98b}, -{15600000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 156_quant.dat*/ - - -/*case 115700000:*/ -/* BEGIN - DIF BPF register values from 157_quant.dat*/ -{15700000, DIF_BPF_COEFF01, 0x00000003}, -{15700000, DIF_BPF_COEFF23, 0xfffcfff4}, -{15700000, DIF_BPF_COEFF45, 0x0020fffa}, -{15700000, DIF_BPF_COEFF67, 0xffb40064}, -{15700000, DIF_BPF_COEFF89, 0x002fff11}, -{15700000, DIF_BPF_COEFF1011, 0x00a400f0}, -{15700000, DIF_BPF_COEFF1213, 0xfe0d006e}, -{15700000, DIF_BPF_COEFF1415, 0x0281fd09}, -{15700000, DIF_BPF_COEFF1617, 0xff3604c9}, -{15700000, DIF_BPF_COEFF1819, 0xfcbffca2}, -{15700000, DIF_BPF_COEFF2021, 0x0726fdfe}, -{15700000, DIF_BPF_COEFF2223, 0xf8e80888}, -{15700000, DIF_BPF_COEFF2425, 0x0134f4f3}, -{15700000, DIF_BPF_COEFF2627, 0x07e1060c}, -{15700000, DIF_BPF_COEFF2829, 0xf22304af}, -{15700000, DIF_BPF_COEFF3031, 0x0b59f1be}, -{15700000, DIF_BPF_COEFF3233, 0xff640f7d}, -{15700000, DIF_BPF_COEFF3435, 0xf452f959}, -{15700000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 157_quant.dat*/ - - -/*case 115800000:*/ -/* BEGIN - DIF BPF register values from 158_quant.dat*/ -{15800000, DIF_BPF_COEFF01, 0x00000003}, -{15800000, DIF_BPF_COEFF23, 0x0000fff0}, -{15800000, DIF_BPF_COEFF45, 0x001a0010}, -{15800000, DIF_BPF_COEFF67, 0xffaa0041}, -{15800000, DIF_BPF_COEFF89, 0x0067ff13}, -{15800000, DIF_BPF_COEFF1011, 0x0043014a}, -{15800000, DIF_BPF_COEFF1213, 0xfe46ffb9}, -{15800000, DIF_BPF_COEFF1415, 0x02dbfda8}, -{15800000, DIF_BPF_COEFF1617, 0xfe3504e5}, -{15800000, DIF_BPF_COEFF1819, 0xfddcfb8d}, -{15800000, DIF_BPF_COEFF2021, 0x06c9ff7e}, -{15800000, DIF_BPF_COEFF2223, 0xf81107a2}, -{15800000, DIF_BPF_COEFF2425, 0x02c9f49a}, -{15800000, DIF_BPF_COEFF2627, 0x069f0753}, -{15800000, DIF_BPF_COEFF2829, 0xf2500373}, -{15800000, DIF_BPF_COEFF3031, 0x0c14f231}, -{15800000, DIF_BPF_COEFF3233, 0xfe930fb3}, -{15800000, DIF_BPF_COEFF3435, 0xf4a1f927}, -{15800000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 158_quant.dat*/ - - -/*case 115900000:*/ -/* BEGIN - DIF BPF register values from 159_quant.dat*/ -{15900000, DIF_BPF_COEFF01, 0xffff0002}, -{15900000, DIF_BPF_COEFF23, 0x0003ffee}, -{15900000, DIF_BPF_COEFF45, 0x000f0023}, -{15900000, DIF_BPF_COEFF67, 0xffac0016}, -{15900000, DIF_BPF_COEFF89, 0x0093ff31}, -{15900000, DIF_BPF_COEFF1011, 0xffdc0184}, -{15900000, DIF_BPF_COEFF1213, 0xfea6ff09}, -{15900000, DIF_BPF_COEFF1415, 0x02fdfe70}, -{15900000, DIF_BPF_COEFF1617, 0xfd5104ba}, -{15900000, DIF_BPF_COEFF1819, 0xff15faac}, -{15900000, DIF_BPF_COEFF2021, 0x06270103}, -{15900000, DIF_BPF_COEFF2223, 0xf7780688}, -{15900000, DIF_BPF_COEFF2425, 0x044df479}, -{15900000, DIF_BPF_COEFF2627, 0x05430883}, -{15900000, DIF_BPF_COEFF2829, 0xf2a00231}, -{15900000, DIF_BPF_COEFF3031, 0x0cbef2b2}, -{15900000, DIF_BPF_COEFF3233, 0xfdc40fe3}, -{15900000, DIF_BPF_COEFF3435, 0xf4f2f8f5}, -{15900000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 159_quant.dat*/ - - -/*case 116000000:*/ -/* BEGIN - DIF BPF register values from 160_quant.dat*/ -{16000000, DIF_BPF_COEFF01, 0xffff0001}, -{16000000, DIF_BPF_COEFF23, 0x0006ffef}, -{16000000, DIF_BPF_COEFF45, 0x00020031}, -{16000000, DIF_BPF_COEFF67, 0xffbaffe8}, -{16000000, DIF_BPF_COEFF89, 0x00adff66}, -{16000000, DIF_BPF_COEFF1011, 0xff790198}, -{16000000, DIF_BPF_COEFF1213, 0xff26fe6e}, -{16000000, DIF_BPF_COEFF1415, 0x02e5ff55}, -{16000000, DIF_BPF_COEFF1617, 0xfc99044a}, -{16000000, DIF_BPF_COEFF1819, 0x005bfa09}, -{16000000, DIF_BPF_COEFF2021, 0x0545027f}, -{16000000, DIF_BPF_COEFF2223, 0xf7230541}, -{16000000, DIF_BPF_COEFF2425, 0x05b8f490}, -{16000000, DIF_BPF_COEFF2627, 0x03d20997}, -{16000000, DIF_BPF_COEFF2829, 0xf31300eb}, -{16000000, DIF_BPF_COEFF3031, 0x0d55f341}, -{16000000, DIF_BPF_COEFF3233, 0xfcf6100e}, -{16000000, DIF_BPF_COEFF3435, 0xf544f8c3}, -{16000000, DIF_BPF_COEFF36, 0x110d0000}, -/* END - DIF BPF register values from 160_quant.dat*/ -}; - -#endif diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/video/cx231xx/cx231xx-dvb.c deleted file mode 100644 index 7c4e360ba9bc..000000000000 --- a/drivers/media/video/cx231xx/cx231xx-dvb.c +++ /dev/null @@ -1,796 +0,0 @@ -/* - DVB device driver for cx231xx - - Copyright (C) 2008 <srinivasa.deevi at conexant dot com> - Based on em28xx driver - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/usb.h> - -#include "cx231xx.h" -#include <media/v4l2-common.h> -#include <media/videobuf-vmalloc.h> - -#include "xc5000.h" -#include "s5h1432.h" -#include "tda18271.h" -#include "s5h1411.h" -#include "lgdt3305.h" -#include "mb86a20s.h" - -MODULE_DESCRIPTION("driver for cx231xx based DVB cards"); -MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>"); -MODULE_LICENSE("GPL"); - -static unsigned int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "enable debug messages [dvb]"); - -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - -#define dprintk(level, fmt, arg...) do { \ -if (debug >= level) \ - printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \ -} while (0) - -#define CX231XX_DVB_NUM_BUFS 5 -#define CX231XX_DVB_MAX_PACKETSIZE 564 -#define CX231XX_DVB_MAX_PACKETS 64 - -struct cx231xx_dvb { - struct dvb_frontend *frontend; - - /* feed count management */ - struct mutex lock; - int nfeeds; - - /* general boilerplate stuff */ - struct dvb_adapter adapter; - struct dvb_demux demux; - struct dmxdev dmxdev; - struct dmx_frontend fe_hw; - struct dmx_frontend fe_mem; - struct dvb_net net; -}; - -static struct s5h1432_config dvico_s5h1432_config = { - .output_mode = S5H1432_SERIAL_OUTPUT, - .gpio = S5H1432_GPIO_ON, - .qam_if = S5H1432_IF_4000, - .vsb_if = S5H1432_IF_4000, - .inversion = S5H1432_INVERSION_OFF, - .status_mode = S5H1432_DEMODLOCKING, - .mpeg_timing = S5H1432_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, -}; - -static struct tda18271_std_map cnxt_rde253s_tda18271_std_map = { - .dvbt_6 = { .if_freq = 4000, .agc_mode = 3, .std = 4, - .if_lvl = 1, .rfagc_top = 0x37, }, - .dvbt_7 = { .if_freq = 4000, .agc_mode = 3, .std = 5, - .if_lvl = 1, .rfagc_top = 0x37, }, - .dvbt_8 = { .if_freq = 4000, .agc_mode = 3, .std = 6, - .if_lvl = 1, .rfagc_top = 0x37, }, -}; - -static struct tda18271_std_map mb86a20s_tda18271_config = { - .dvbt_6 = { .if_freq = 3300, .agc_mode = 3, .std = 4, - .if_lvl = 7, .rfagc_top = 0x37, }, -}; - -static struct tda18271_config cnxt_rde253s_tunerconfig = { - .std_map = &cnxt_rde253s_tda18271_std_map, - .gate = TDA18271_GATE_ANALOG, -}; - -static struct s5h1411_config tda18271_s5h1411_config = { - .output_mode = S5H1411_SERIAL_OUTPUT, - .gpio = S5H1411_GPIO_OFF, - .vsb_if = S5H1411_IF_3250, - .qam_if = S5H1411_IF_4000, - .inversion = S5H1411_INVERSION_ON, - .status_mode = S5H1411_DEMODLOCKING, - .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, -}; -static struct s5h1411_config xc5000_s5h1411_config = { - .output_mode = S5H1411_SERIAL_OUTPUT, - .gpio = S5H1411_GPIO_OFF, - .vsb_if = S5H1411_IF_3250, - .qam_if = S5H1411_IF_3250, - .inversion = S5H1411_INVERSION_OFF, - .status_mode = S5H1411_DEMODLOCKING, - .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, -}; - -static struct lgdt3305_config hcw_lgdt3305_config = { - .i2c_addr = 0x0e, - .mpeg_mode = LGDT3305_MPEG_SERIAL, - .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, - .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, - .deny_i2c_rptr = 1, - .spectral_inversion = 1, - .qam_if_khz = 4000, - .vsb_if_khz = 3250, -}; - -static struct tda18271_std_map hauppauge_tda18271_std_map = { - .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 4, - .if_lvl = 1, .rfagc_top = 0x58, }, - .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 5, - .if_lvl = 1, .rfagc_top = 0x58, }, -}; - -static struct tda18271_config hcw_tda18271_config = { - .std_map = &hauppauge_tda18271_std_map, - .gate = TDA18271_GATE_DIGITAL, -}; - -static const struct mb86a20s_config pv_mb86a20s_config = { - .demod_address = 0x10, - .is_serial = true, -}; - -static struct tda18271_config pv_tda18271_config = { - .std_map = &mb86a20s_tda18271_config, - .gate = TDA18271_GATE_DIGITAL, - .small_i2c = TDA18271_03_BYTE_CHUNK_INIT, -}; - -static inline void print_err_status(struct cx231xx *dev, int packet, int status) -{ - char *errmsg = "Unknown"; - - switch (status) { - case -ENOENT: - errmsg = "unlinked synchronuously"; - break; - case -ECONNRESET: - errmsg = "unlinked asynchronuously"; - break; - case -ENOSR: - errmsg = "Buffer error (overrun)"; - break; - case -EPIPE: - errmsg = "Stalled (device not responding)"; - break; - case -EOVERFLOW: - errmsg = "Babble (bad cable?)"; - break; - case -EPROTO: - errmsg = "Bit-stuff error (bad cable?)"; - break; - case -EILSEQ: - errmsg = "CRC/Timeout (could be anything)"; - break; - case -ETIME: - errmsg = "Device does not respond"; - break; - } - if (packet < 0) { - dprintk(1, "URB status %d [%s].\n", status, errmsg); - } else { - dprintk(1, "URB packet %d, status %d [%s].\n", - packet, status, errmsg); - } -} - -static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb) -{ - int i; - - if (!dev) - return 0; - - if (dev->state & DEV_DISCONNECTED) - return 0; - - if (urb->status < 0) { - print_err_status(dev, -1, urb->status); - if (urb->status == -ENOENT) - return 0; - } - - for (i = 0; i < urb->number_of_packets; i++) { - int status = urb->iso_frame_desc[i].status; - - if (status < 0) { - print_err_status(dev, i, status); - if (urb->iso_frame_desc[i].status != -EPROTO) - continue; - } - - dvb_dmx_swfilter(&dev->dvb->demux, - urb->transfer_buffer + - urb->iso_frame_desc[i].offset, - urb->iso_frame_desc[i].actual_length); - } - - return 0; -} - -static inline int dvb_bulk_copy(struct cx231xx *dev, struct urb *urb) -{ - if (!dev) - return 0; - - if (dev->state & DEV_DISCONNECTED) - return 0; - - if (urb->status < 0) { - print_err_status(dev, -1, urb->status); - if (urb->status == -ENOENT) - return 0; - } - - /* Feed the transport payload into the kernel demux */ - dvb_dmx_swfilter(&dev->dvb->demux, - urb->transfer_buffer, urb->actual_length); - - return 0; -} - -static int start_streaming(struct cx231xx_dvb *dvb) -{ - int rc; - struct cx231xx *dev = dvb->adapter.priv; - - if (dev->USE_ISO) { - cx231xx_info("DVB transfer mode is ISO.\n"); - mutex_lock(&dev->i2c_lock); - cx231xx_enable_i2c_port_3(dev, false); - cx231xx_set_alt_setting(dev, INDEX_TS1, 4); - cx231xx_enable_i2c_port_3(dev, true); - mutex_unlock(&dev->i2c_lock); - rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); - if (rc < 0) - return rc; - dev->mode_tv = 1; - return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS, - CX231XX_DVB_NUM_BUFS, - dev->ts1_mode.max_pkt_size, - dvb_isoc_copy); - } else { - cx231xx_info("DVB transfer mode is BULK.\n"); - cx231xx_set_alt_setting(dev, INDEX_TS1, 0); - rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); - if (rc < 0) - return rc; - dev->mode_tv = 1; - return cx231xx_init_bulk(dev, CX231XX_DVB_MAX_PACKETS, - CX231XX_DVB_NUM_BUFS, - dev->ts1_mode.max_pkt_size, - dvb_bulk_copy); - } - -} - -static int stop_streaming(struct cx231xx_dvb *dvb) -{ - struct cx231xx *dev = dvb->adapter.priv; - - if (dev->USE_ISO) - cx231xx_uninit_isoc(dev); - else - cx231xx_uninit_bulk(dev); - - cx231xx_set_mode(dev, CX231XX_SUSPEND); - - return 0; -} - -static int start_feed(struct dvb_demux_feed *feed) -{ - struct dvb_demux *demux = feed->demux; - struct cx231xx_dvb *dvb = demux->priv; - int rc, ret; - - if (!demux->dmx.frontend) - return -EINVAL; - - mutex_lock(&dvb->lock); - dvb->nfeeds++; - rc = dvb->nfeeds; - - if (dvb->nfeeds == 1) { - ret = start_streaming(dvb); - if (ret < 0) - rc = ret; - } - - mutex_unlock(&dvb->lock); - return rc; -} - -static int stop_feed(struct dvb_demux_feed *feed) -{ - struct dvb_demux *demux = feed->demux; - struct cx231xx_dvb *dvb = demux->priv; - int err = 0; - - mutex_lock(&dvb->lock); - dvb->nfeeds--; - - if (0 == dvb->nfeeds) - err = stop_streaming(dvb); - - mutex_unlock(&dvb->lock); - return err; -} - -/* ------------------------------------------------------------------ */ -static int cx231xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) -{ - struct cx231xx *dev = fe->dvb->priv; - - if (acquire) - return cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); - else - return cx231xx_set_mode(dev, CX231XX_SUSPEND); -} - -/* ------------------------------------------------------------------ */ - -static struct xc5000_config cnxt_rde250_tunerconfig = { - .i2c_address = 0x61, - .if_khz = 4000, -}; -static struct xc5000_config cnxt_rdu250_tunerconfig = { - .i2c_address = 0x61, - .if_khz = 3250, -}; - -/* ------------------------------------------------------------------ */ -#if 0 -static int attach_xc5000(u8 addr, struct cx231xx *dev) -{ - - struct dvb_frontend *fe; - struct xc5000_config cfg; - - memset(&cfg, 0, sizeof(cfg)); - cfg.i2c_adap = &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap; - cfg.i2c_addr = addr; - - if (!dev->dvb->frontend) { - printk(KERN_ERR "%s/2: dvb frontend not attached. " - "Can't attach xc5000\n", dev->name); - return -EINVAL; - } - - fe = dvb_attach(xc5000_attach, dev->dvb->frontend, &cfg); - if (!fe) { - printk(KERN_ERR "%s/2: xc5000 attach failed\n", dev->name); - dvb_frontend_detach(dev->dvb->frontend); - dev->dvb->frontend = NULL; - return -EINVAL; - } - - printk(KERN_INFO "%s/2: xc5000 attached\n", dev->name); - - return 0; -} -#endif - -int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq) -{ - int status = 0; - - if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) { - - struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops; - - if (dops->set_analog_params != NULL) { - struct analog_parameters params; - - params.frequency = freq; - params.std = dev->norm; - params.mode = 0; /* 0- Air; 1 - cable */ - /*params.audmode = ; */ - - /* Set the analog parameters to set the frequency */ - dops->set_analog_params(dev->dvb->frontend, ¶ms); - } - - } - - return status; -} - -int cx231xx_reset_analog_tuner(struct cx231xx *dev) -{ - int status = 0; - - if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) { - - struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops; - - if (dops->init != NULL && !dev->xc_fw_load_done) { - - cx231xx_info("Reloading firmware for XC5000\n"); - status = dops->init(dev->dvb->frontend); - if (status == 0) { - dev->xc_fw_load_done = 1; - cx231xx_info - ("XC5000 firmware download completed\n"); - } else { - dev->xc_fw_load_done = 0; - cx231xx_info - ("XC5000 firmware download failed !!!\n"); - } - } - - } - - return status; -} - -/* ------------------------------------------------------------------ */ - -static int register_dvb(struct cx231xx_dvb *dvb, - struct module *module, - struct cx231xx *dev, struct device *device) -{ - int result; - - mutex_init(&dvb->lock); - - /* register adapter */ - result = dvb_register_adapter(&dvb->adapter, dev->name, module, device, - adapter_nr); - if (result < 0) { - printk(KERN_WARNING - "%s: dvb_register_adapter failed (errno = %d)\n", - dev->name, result); - goto fail_adapter; - } - - /* Ensure all frontends negotiate bus access */ - dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl; - - dvb->adapter.priv = dev; - - /* register frontend */ - result = dvb_register_frontend(&dvb->adapter, dvb->frontend); - if (result < 0) { - printk(KERN_WARNING - "%s: dvb_register_frontend failed (errno = %d)\n", - dev->name, result); - goto fail_frontend; - } - - /* register demux stuff */ - dvb->demux.dmx.capabilities = - DMX_TS_FILTERING | DMX_SECTION_FILTERING | - DMX_MEMORY_BASED_FILTERING; - dvb->demux.priv = dvb; - dvb->demux.filternum = 256; - dvb->demux.feednum = 256; - dvb->demux.start_feed = start_feed; - dvb->demux.stop_feed = stop_feed; - - result = dvb_dmx_init(&dvb->demux); - if (result < 0) { - printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n", - dev->name, result); - goto fail_dmx; - } - - dvb->dmxdev.filternum = 256; - dvb->dmxdev.demux = &dvb->demux.dmx; - dvb->dmxdev.capabilities = 0; - result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); - if (result < 0) { - printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", - dev->name, result); - goto fail_dmxdev; - } - - dvb->fe_hw.source = DMX_FRONTEND_0; - result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); - if (result < 0) { - printk(KERN_WARNING - "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", - dev->name, result); - goto fail_fe_hw; - } - - dvb->fe_mem.source = DMX_MEMORY_FE; - result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); - if (result < 0) { - printk(KERN_WARNING - "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", - dev->name, result); - goto fail_fe_mem; - } - - result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); - if (result < 0) { - printk(KERN_WARNING - "%s: connect_frontend failed (errno = %d)\n", dev->name, - result); - goto fail_fe_conn; - } - - /* register network adapter */ - dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); - return 0; - -fail_fe_conn: - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); -fail_fe_mem: - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); -fail_fe_hw: - dvb_dmxdev_release(&dvb->dmxdev); -fail_dmxdev: - dvb_dmx_release(&dvb->demux); -fail_dmx: - dvb_unregister_frontend(dvb->frontend); -fail_frontend: - dvb_frontend_detach(dvb->frontend); - dvb_unregister_adapter(&dvb->adapter); -fail_adapter: - return result; -} - -static void unregister_dvb(struct cx231xx_dvb *dvb) -{ - dvb_net_release(&dvb->net); - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); - dvb_dmxdev_release(&dvb->dmxdev); - dvb_dmx_release(&dvb->demux); - dvb_unregister_frontend(dvb->frontend); - dvb_frontend_detach(dvb->frontend); - dvb_unregister_adapter(&dvb->adapter); -} - -static int dvb_init(struct cx231xx *dev) -{ - int result = 0; - struct cx231xx_dvb *dvb; - - if (!dev->board.has_dvb) { - /* This device does not support the extension */ - return 0; - } - - dvb = kzalloc(sizeof(struct cx231xx_dvb), GFP_KERNEL); - - if (dvb == NULL) { - printk(KERN_INFO "cx231xx_dvb: memory allocation failed\n"); - return -ENOMEM; - } - dev->dvb = dvb; - dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq; - dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner; - - mutex_lock(&dev->lock); - cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); - cx231xx_demod_reset(dev); - /* init frontend */ - switch (dev->model) { - case CX231XX_BOARD_CNXT_CARRAERA: - case CX231XX_BOARD_CNXT_RDE_250: - - dev->dvb->frontend = dvb_attach(s5h1432_attach, - &dvico_s5h1432_config, - &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap); - - if (dev->dvb->frontend == NULL) { - printk(DRIVER_NAME - ": Failed to attach s5h1432 front end\n"); - result = -EINVAL; - goto out_free; - } - - /* define general-purpose callback pointer */ - dvb->frontend->callback = cx231xx_tuner_callback; - - if (!dvb_attach(xc5000_attach, dev->dvb->frontend, - &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap, - &cnxt_rde250_tunerconfig)) { - result = -EINVAL; - goto out_free; - } - - break; - case CX231XX_BOARD_CNXT_SHELBY: - case CX231XX_BOARD_CNXT_RDU_250: - - dev->dvb->frontend = dvb_attach(s5h1411_attach, - &xc5000_s5h1411_config, - &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap); - - if (dev->dvb->frontend == NULL) { - printk(DRIVER_NAME - ": Failed to attach s5h1411 front end\n"); - result = -EINVAL; - goto out_free; - } - - /* define general-purpose callback pointer */ - dvb->frontend->callback = cx231xx_tuner_callback; - - if (!dvb_attach(xc5000_attach, dev->dvb->frontend, - &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap, - &cnxt_rdu250_tunerconfig)) { - result = -EINVAL; - goto out_free; - } - break; - case CX231XX_BOARD_CNXT_RDE_253S: - - dev->dvb->frontend = dvb_attach(s5h1432_attach, - &dvico_s5h1432_config, - &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap); - - if (dev->dvb->frontend == NULL) { - printk(DRIVER_NAME - ": Failed to attach s5h1432 front end\n"); - result = -EINVAL; - goto out_free; - } - - /* define general-purpose callback pointer */ - dvb->frontend->callback = cx231xx_tuner_callback; - - if (!dvb_attach(tda18271_attach, dev->dvb->frontend, - 0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap, - &cnxt_rde253s_tunerconfig)) { - result = -EINVAL; - goto out_free; - } - break; - case CX231XX_BOARD_CNXT_RDU_253S: - - dev->dvb->frontend = dvb_attach(s5h1411_attach, - &tda18271_s5h1411_config, - &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap); - - if (dev->dvb->frontend == NULL) { - printk(DRIVER_NAME - ": Failed to attach s5h1411 front end\n"); - result = -EINVAL; - goto out_free; - } - - /* define general-purpose callback pointer */ - dvb->frontend->callback = cx231xx_tuner_callback; - - if (!dvb_attach(tda18271_attach, dev->dvb->frontend, - 0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap, - &cnxt_rde253s_tunerconfig)) { - result = -EINVAL; - goto out_free; - } - break; - case CX231XX_BOARD_HAUPPAUGE_EXETER: - - printk(KERN_INFO "%s: looking for tuner / demod on i2c bus: %d\n", - __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap)); - - dev->dvb->frontend = dvb_attach(lgdt3305_attach, - &hcw_lgdt3305_config, - &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap); - - if (dev->dvb->frontend == NULL) { - printk(DRIVER_NAME - ": Failed to attach LG3305 front end\n"); - result = -EINVAL; - goto out_free; - } - - /* define general-purpose callback pointer */ - dvb->frontend->callback = cx231xx_tuner_callback; - - dvb_attach(tda18271_attach, dev->dvb->frontend, - 0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap, - &hcw_tda18271_config); - break; - - case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: - case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID: - - printk(KERN_INFO "%s: looking for demod on i2c bus: %d\n", - __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap)); - - dev->dvb->frontend = dvb_attach(mb86a20s_attach, - &pv_mb86a20s_config, - &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap); - - if (dev->dvb->frontend == NULL) { - printk(DRIVER_NAME - ": Failed to attach mb86a20s demod\n"); - result = -EINVAL; - goto out_free; - } - - /* define general-purpose callback pointer */ - dvb->frontend->callback = cx231xx_tuner_callback; - - dvb_attach(tda18271_attach, dev->dvb->frontend, - 0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap, - &pv_tda18271_config); - break; - - default: - printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" - " isn't supported yet\n", dev->name); - break; - } - if (NULL == dvb->frontend) { - printk(KERN_ERR - "%s/2: frontend initialization failed\n", dev->name); - result = -EINVAL; - goto out_free; - } - - /* register everything */ - result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); - - if (result < 0) - goto out_free; - - - printk(KERN_INFO "Successfully loaded cx231xx-dvb\n"); - -ret: - cx231xx_set_mode(dev, CX231XX_SUSPEND); - mutex_unlock(&dev->lock); - return result; - -out_free: - kfree(dvb); - dev->dvb = NULL; - goto ret; -} - -static int dvb_fini(struct cx231xx *dev) -{ - if (!dev->board.has_dvb) { - /* This device does not support the extension */ - return 0; - } - - if (dev->dvb) { - unregister_dvb(dev->dvb); - dev->dvb = NULL; - } - - return 0; -} - -static struct cx231xx_ops dvb_ops = { - .id = CX231XX_DVB, - .name = "Cx231xx dvb Extension", - .init = dvb_init, - .fini = dvb_fini, -}; - -static int __init cx231xx_dvb_register(void) -{ - return cx231xx_register_extension(&dvb_ops); -} - -static void __exit cx231xx_dvb_unregister(void) -{ - cx231xx_unregister_extension(&dvb_ops); -} - -module_init(cx231xx_dvb_register); -module_exit(cx231xx_dvb_unregister); diff --git a/drivers/media/video/cx231xx/cx231xx-i2c.c b/drivers/media/video/cx231xx/cx231xx-i2c.c deleted file mode 100644 index 781feed406f7..000000000000 --- a/drivers/media/video/cx231xx/cx231xx-i2c.c +++ /dev/null @@ -1,532 +0,0 @@ -/* - cx231xx-i2c.c - driver for Conexant Cx23100/101/102 USB video capture devices - - Copyright (C) 2008 <srinivasa.deevi at conexant dot com> - Based on em28xx driver - Based on Cx23885 driver - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/usb.h> -#include <linux/i2c.h> -#include <media/v4l2-common.h> -#include <media/tuner.h> - -#include "cx231xx.h" - -/* ----------------------------------------------------------- */ - -static unsigned int i2c_scan; -module_param(i2c_scan, int, 0444); -MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); - -static unsigned int i2c_debug; -module_param(i2c_debug, int, 0644); -MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); - -#define dprintk1(lvl, fmt, args...) \ -do { \ - if (i2c_debug >= lvl) { \ - printk(fmt, ##args); \ - } \ -} while (0) - -#define dprintk2(lvl, fmt, args...) \ -do { \ - if (i2c_debug >= lvl) { \ - printk(KERN_DEBUG "%s at %s: " fmt, \ - dev->name, __func__ , ##args); \ - } \ -} while (0) - -static inline bool is_tuner(struct cx231xx *dev, struct cx231xx_i2c *bus, - const struct i2c_msg *msg, int tuner_type) -{ - if (bus->nr != dev->board.tuner_i2c_master) - return false; - - if (msg->addr != dev->board.tuner_addr) - return false; - - if (dev->tuner_type != tuner_type) - return false; - - return true; -} - -/* - * cx231xx_i2c_send_bytes() - */ -int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap, - const struct i2c_msg *msg) -{ - struct cx231xx_i2c *bus = i2c_adap->algo_data; - struct cx231xx *dev = bus->dev; - struct cx231xx_i2c_xfer_data req_data; - int status = 0; - u16 size = 0; - u8 loop = 0; - u8 saddr_len = 1; - u8 *buf_ptr = NULL; - u16 saddr = 0; - u8 need_gpio = 0; - - if (is_tuner(dev, bus, msg, TUNER_XC5000)) { - size = msg->len; - - if (size == 2) { /* register write sub addr */ - /* Just writing sub address will cause problem - * to XC5000. So ignore the request */ - return 0; - } else if (size == 4) { /* register write with sub addr */ - if (msg->len >= 2) - saddr = msg->buf[0] << 8 | msg->buf[1]; - else if (msg->len == 1) - saddr = msg->buf[0]; - - switch (saddr) { - case 0x0000: /* start tuner calibration mode */ - need_gpio = 1; - /* FW Loading is done */ - dev->xc_fw_load_done = 1; - break; - case 0x000D: /* Set signal source */ - case 0x0001: /* Set TV standard - Video */ - case 0x0002: /* Set TV standard - Audio */ - case 0x0003: /* Set RF Frequency */ - need_gpio = 1; - break; - default: - if (dev->xc_fw_load_done) - need_gpio = 1; - break; - } - - if (need_gpio) { - dprintk1(1, - "GPIO WRITE: addr 0x%x, len %d, saddr 0x%x\n", - msg->addr, msg->len, saddr); - - return dev->cx231xx_gpio_i2c_write(dev, - msg->addr, - msg->buf, - msg->len); - } - } - - /* special case for Xc5000 tuner case */ - saddr_len = 1; - - /* adjust the length to correct length */ - size -= saddr_len; - buf_ptr = (u8 *) (msg->buf + 1); - - do { - /* prepare xfer_data struct */ - req_data.dev_addr = msg->addr; - req_data.direction = msg->flags; - req_data.saddr_len = saddr_len; - req_data.saddr_dat = msg->buf[0]; - req_data.buf_size = size > 16 ? 16 : size; - req_data.p_buffer = (u8 *) (buf_ptr + loop * 16); - - bus->i2c_nostop = (size > 16) ? 1 : 0; - bus->i2c_reserve = (loop == 0) ? 0 : 1; - - /* usb send command */ - status = dev->cx231xx_send_usb_command(bus, &req_data); - loop++; - - if (size >= 16) - size -= 16; - else - size = 0; - - } while (size > 0); - - bus->i2c_nostop = 0; - bus->i2c_reserve = 0; - - } else { /* regular case */ - - /* prepare xfer_data struct */ - req_data.dev_addr = msg->addr; - req_data.direction = msg->flags; - req_data.saddr_len = 0; - req_data.saddr_dat = 0; - req_data.buf_size = msg->len; - req_data.p_buffer = msg->buf; - - /* usb send command */ - status = dev->cx231xx_send_usb_command(bus, &req_data); - } - - return status < 0 ? status : 0; -} - -/* - * cx231xx_i2c_recv_bytes() - * read a byte from the i2c device - */ -static int cx231xx_i2c_recv_bytes(struct i2c_adapter *i2c_adap, - const struct i2c_msg *msg) -{ - struct cx231xx_i2c *bus = i2c_adap->algo_data; - struct cx231xx *dev = bus->dev; - struct cx231xx_i2c_xfer_data req_data; - int status = 0; - u16 saddr = 0; - u8 need_gpio = 0; - - if (is_tuner(dev, bus, msg, TUNER_XC5000)) { - if (msg->len == 2) - saddr = msg->buf[0] << 8 | msg->buf[1]; - else if (msg->len == 1) - saddr = msg->buf[0]; - - if (dev->xc_fw_load_done) { - - switch (saddr) { - case 0x0009: /* BUSY check */ - dprintk1(1, - "GPIO R E A D: Special case BUSY check \n"); - /*Try read BUSY register, just set it to zero*/ - msg->buf[0] = 0; - if (msg->len == 2) - msg->buf[1] = 0; - return 0; - case 0x0004: /* read Lock status */ - need_gpio = 1; - break; - - } - - if (need_gpio) { - /* this is a special case to handle Xceive tuner - clock stretch issue with gpio based I2C */ - - dprintk1(1, - "GPIO R E A D: addr 0x%x, len %d, saddr 0x%x\n", - msg->addr, msg->len, - msg->buf[0] << 8 | msg->buf[1]); - - status = - dev->cx231xx_gpio_i2c_write(dev, msg->addr, - msg->buf, - msg->len); - status = - dev->cx231xx_gpio_i2c_read(dev, msg->addr, - msg->buf, - msg->len); - return status; - } - } - - /* prepare xfer_data struct */ - req_data.dev_addr = msg->addr; - req_data.direction = msg->flags; - req_data.saddr_len = msg->len; - req_data.saddr_dat = msg->buf[0] << 8 | msg->buf[1]; - req_data.buf_size = msg->len; - req_data.p_buffer = msg->buf; - - /* usb send command */ - status = dev->cx231xx_send_usb_command(bus, &req_data); - - } else { - - /* prepare xfer_data struct */ - req_data.dev_addr = msg->addr; - req_data.direction = msg->flags; - req_data.saddr_len = 0; - req_data.saddr_dat = 0; - req_data.buf_size = msg->len; - req_data.p_buffer = msg->buf; - - /* usb send command */ - status = dev->cx231xx_send_usb_command(bus, &req_data); - } - - return status < 0 ? status : 0; -} - -/* - * cx231xx_i2c_recv_bytes_with_saddr() - * read a byte from the i2c device - */ -static int cx231xx_i2c_recv_bytes_with_saddr(struct i2c_adapter *i2c_adap, - const struct i2c_msg *msg1, - const struct i2c_msg *msg2) -{ - struct cx231xx_i2c *bus = i2c_adap->algo_data; - struct cx231xx *dev = bus->dev; - struct cx231xx_i2c_xfer_data req_data; - int status = 0; - u16 saddr = 0; - u8 need_gpio = 0; - - if (msg1->len == 2) - saddr = msg1->buf[0] << 8 | msg1->buf[1]; - else if (msg1->len == 1) - saddr = msg1->buf[0]; - - if (is_tuner(dev, bus, msg2, TUNER_XC5000)) { - if ((msg2->len < 16)) { - - dprintk1(1, - "i2c_read: addr 0x%x, len %d, saddr 0x%x, len %d\n", - msg2->addr, msg2->len, saddr, msg1->len); - - switch (saddr) { - case 0x0008: /* read FW load status */ - need_gpio = 1; - break; - case 0x0004: /* read Lock status */ - need_gpio = 1; - break; - } - - if (need_gpio) { - status = - dev->cx231xx_gpio_i2c_write(dev, msg1->addr, - msg1->buf, - msg1->len); - status = - dev->cx231xx_gpio_i2c_read(dev, msg2->addr, - msg2->buf, - msg2->len); - return status; - } - } - } - - /* prepare xfer_data struct */ - req_data.dev_addr = msg2->addr; - req_data.direction = msg2->flags; - req_data.saddr_len = msg1->len; - req_data.saddr_dat = saddr; - req_data.buf_size = msg2->len; - req_data.p_buffer = msg2->buf; - - /* usb send command */ - status = dev->cx231xx_send_usb_command(bus, &req_data); - - return status < 0 ? status : 0; -} - -/* - * cx231xx_i2c_check_for_device() - * check if there is a i2c_device at the supplied address - */ -static int cx231xx_i2c_check_for_device(struct i2c_adapter *i2c_adap, - const struct i2c_msg *msg) -{ - struct cx231xx_i2c *bus = i2c_adap->algo_data; - struct cx231xx *dev = bus->dev; - struct cx231xx_i2c_xfer_data req_data; - int status = 0; - - /* prepare xfer_data struct */ - req_data.dev_addr = msg->addr; - req_data.direction = msg->flags; - req_data.saddr_len = 0; - req_data.saddr_dat = 0; - req_data.buf_size = 0; - req_data.p_buffer = NULL; - - /* usb send command */ - status = dev->cx231xx_send_usb_command(bus, &req_data); - - return status < 0 ? status : 0; -} - -/* - * cx231xx_i2c_xfer() - * the main i2c transfer function - */ -static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msgs[], int num) -{ - struct cx231xx_i2c *bus = i2c_adap->algo_data; - struct cx231xx *dev = bus->dev; - int addr, rc, i, byte; - - if (num <= 0) - return 0; - mutex_lock(&dev->i2c_lock); - for (i = 0; i < num; i++) { - - addr = msgs[i].addr >> 1; - - dprintk2(2, "%s %s addr=%x len=%d:", - (msgs[i].flags & I2C_M_RD) ? "read" : "write", - i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); - if (!msgs[i].len) { - /* no len: check only for device presence */ - rc = cx231xx_i2c_check_for_device(i2c_adap, &msgs[i]); - if (rc < 0) { - dprintk2(2, " no device\n"); - mutex_unlock(&dev->i2c_lock); - return rc; - } - - } else if (msgs[i].flags & I2C_M_RD) { - /* read bytes */ - rc = cx231xx_i2c_recv_bytes(i2c_adap, &msgs[i]); - if (i2c_debug >= 2) { - for (byte = 0; byte < msgs[i].len; byte++) - printk(" %02x", msgs[i].buf[byte]); - } - } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && - msgs[i].addr == msgs[i + 1].addr - && (msgs[i].len <= 2) && (bus->nr < 3)) { - /* read bytes */ - rc = cx231xx_i2c_recv_bytes_with_saddr(i2c_adap, - &msgs[i], - &msgs[i + 1]); - if (i2c_debug >= 2) { - for (byte = 0; byte < msgs[i].len; byte++) - printk(" %02x", msgs[i].buf[byte]); - } - i++; - } else { - /* write bytes */ - if (i2c_debug >= 2) { - for (byte = 0; byte < msgs[i].len; byte++) - printk(" %02x", msgs[i].buf[byte]); - } - rc = cx231xx_i2c_send_bytes(i2c_adap, &msgs[i]); - } - if (rc < 0) - goto err; - if (i2c_debug >= 2) - printk("\n"); - } - mutex_unlock(&dev->i2c_lock); - return num; -err: - dprintk2(2, " ERROR: %i\n", rc); - mutex_unlock(&dev->i2c_lock); - return rc; -} - -/* ----------------------------------------------------------- */ - -/* - * functionality() - */ -static u32 functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; -} - -static struct i2c_algorithm cx231xx_algo = { - .master_xfer = cx231xx_i2c_xfer, - .functionality = functionality, -}; - -static struct i2c_adapter cx231xx_adap_template = { - .owner = THIS_MODULE, - .name = "cx231xx", - .algo = &cx231xx_algo, -}; - -static struct i2c_client cx231xx_client_template = { - .name = "cx231xx internal", -}; - -/* ----------------------------------------------------------- */ - -/* - * i2c_devs - * incomplete list of known devices - */ -static char *i2c_devs[128] = { - [0x60 >> 1] = "colibri", - [0x88 >> 1] = "hammerhead", - [0x8e >> 1] = "CIR", - [0x32 >> 1] = "GeminiIII", - [0x02 >> 1] = "Aquarius", - [0xa0 >> 1] = "eeprom", - [0xc0 >> 1] = "tuner", - [0xc2 >> 1] = "tuner", -}; - -/* - * cx231xx_do_i2c_scan() - * check i2c address range for devices - */ -void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c) -{ - unsigned char buf; - int i, rc; - - cx231xx_info(": Checking for I2C devices ..\n"); - for (i = 0; i < 128; i++) { - c->addr = i; - rc = i2c_master_recv(c, &buf, 0); - if (rc < 0) - continue; - cx231xx_info("%s: i2c scan: found device @ 0x%x [%s]\n", - dev->name, i << 1, - i2c_devs[i] ? i2c_devs[i] : "???"); - } - cx231xx_info(": Completed Checking for I2C devices.\n"); -} - -/* - * cx231xx_i2c_register() - * register i2c bus - */ -int cx231xx_i2c_register(struct cx231xx_i2c *bus) -{ - struct cx231xx *dev = bus->dev; - - BUG_ON(!dev->cx231xx_send_usb_command); - - bus->i2c_adap = cx231xx_adap_template; - bus->i2c_client = cx231xx_client_template; - bus->i2c_adap.dev.parent = &dev->udev->dev; - - strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); - - bus->i2c_adap.algo_data = bus; - i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev); - i2c_add_adapter(&bus->i2c_adap); - - bus->i2c_client.adapter = &bus->i2c_adap; - - if (0 == bus->i2c_rc) { - if (i2c_scan) - cx231xx_do_i2c_scan(dev, &bus->i2c_client); - } else - cx231xx_warn("%s: i2c bus %d register FAILED\n", - dev->name, bus->nr); - - return bus->i2c_rc; -} - -/* - * cx231xx_i2c_unregister() - * unregister i2c_bus - */ -int cx231xx_i2c_unregister(struct cx231xx_i2c *bus) -{ - i2c_del_adapter(&bus->i2c_adap); - return 0; -} diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c deleted file mode 100644 index 96176e9db5a2..000000000000 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * cx231xx IR glue driver - * - * Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.com> - * - * Polaris (cx231xx) has its support for IR's with a design close to MCE. - * however, a few designs are using an external I2C chip for IR, instead - * of using the one provided by the chip. - * This driver provides support for those extra devices - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#include "cx231xx.h" -#include <linux/usb.h> -#include <linux/slab.h> - -#define MODULE_NAME "cx231xx-input" - -static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key, - u32 *ir_raw) -{ - int rc; - u8 cmd, scancode; - - dev_dbg(&ir->rc->input_dev->dev, "%s\n", __func__); - - /* poll IR chip */ - rc = i2c_master_recv(ir->c, &cmd, 1); - if (rc < 0) - return rc; - if (rc != 1) - return -EIO; - - /* it seems that 0xFE indicates that a button is still hold - down, while 0xff indicates that no button is hold - down. 0xfe sequences are sometimes interrupted by 0xFF */ - - if (cmd == 0xff) - return 0; - - scancode = - ((cmd & 0x01) ? 0x80 : 0) | - ((cmd & 0x02) ? 0x40 : 0) | - ((cmd & 0x04) ? 0x20 : 0) | - ((cmd & 0x08) ? 0x10 : 0) | - ((cmd & 0x10) ? 0x08 : 0) | - ((cmd & 0x20) ? 0x04 : 0) | - ((cmd & 0x40) ? 0x02 : 0) | - ((cmd & 0x80) ? 0x01 : 0); - - dev_dbg(&ir->rc->input_dev->dev, "cmd %02x, scan = %02x\n", - cmd, scancode); - - *ir_key = scancode; - *ir_raw = scancode; - return 1; -} - -int cx231xx_ir_init(struct cx231xx *dev) -{ - struct i2c_board_info info; - u8 ir_i2c_bus; - - dev_dbg(&dev->udev->dev, "%s\n", __func__); - - /* Only initialize if a rc keycode map is defined */ - if (!cx231xx_boards[dev->model].rc_map_name) - return -ENODEV; - - request_module("ir-kbd-i2c"); - - memset(&info, 0, sizeof(struct i2c_board_info)); - memset(&dev->init_data, 0, sizeof(dev->init_data)); - dev->init_data.rc_dev = rc_allocate_device(); - if (!dev->init_data.rc_dev) - return -ENOMEM; - - dev->init_data.name = cx231xx_boards[dev->model].name; - - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); - info.platform_data = &dev->init_data; - - /* - * Board-dependent values - * - * For now, there's just one type of hardware design using - * an i2c device. - */ - dev->init_data.get_key = get_key_isdbt; - dev->init_data.ir_codes = cx231xx_boards[dev->model].rc_map_name; - /* The i2c micro-controller only outputs the cmd part of NEC protocol */ - dev->init_data.rc_dev->scanmask = 0xff; - dev->init_data.rc_dev->driver_name = "cx231xx"; - dev->init_data.type = RC_TYPE_NEC; - info.addr = 0x30; - - /* Load and bind ir-kbd-i2c */ - ir_i2c_bus = cx231xx_boards[dev->model].ir_i2c_master; - dev_dbg(&dev->udev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n", - ir_i2c_bus, info.addr); - dev->ir_i2c_client = i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info); - - return 0; -} - -void cx231xx_ir_exit(struct cx231xx *dev) -{ - if (dev->ir_i2c_client) - i2c_unregister_device(dev->ir_i2c_client); - dev->ir_i2c_client = NULL; -} diff --git a/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c b/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c deleted file mode 100644 index 7473c33e823e..000000000000 --- a/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c +++ /dev/null @@ -1,795 +0,0 @@ -/* - cx231xx-pcb-config.c - driver for Conexant - Cx23100/101/102 USB video capture devices - - Copyright (C) 2008 <srinivasa.deevi at conexant dot com> - - 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 "cx231xx.h" -#include "cx231xx-conf-reg.h" - -static unsigned int pcb_debug; -module_param(pcb_debug, int, 0644); -MODULE_PARM_DESC(pcb_debug, "enable pcb config debug messages [video]"); - -/******************************************************************************/ - -struct pcb_config cx231xx_Scenario[] = { - { - INDEX_SELFPOWER_DIGITAL_ONLY, /* index */ - USB_SELF_POWER, /* power_type */ - 0, /* speed , not decide yet */ - MOD_DIGITAL, /* mode */ - SOURCE_TS_BDA, /* ts1_source, digital tv only */ - NOT_SUPPORTED, /* ts2_source */ - NOT_SUPPORTED, /* analog source */ - - 0, /* digital_index */ - 0, /* analog index */ - 0, /* dif_index */ - 0, /* external_index */ - - 1, /* only one configuration */ - { - { - 0, /* config index */ - { - 0, /* interrupt ep index */ - 1, /* ts1 index */ - NOT_SUPPORTED, /* TS2 index */ - NOT_SUPPORTED, /* AUDIO */ - NOT_SUPPORTED, /* VIDEO */ - NOT_SUPPORTED, /* VANC */ - NOT_SUPPORTED, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - , - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - , - /* full-speed config */ - { - { - 0, /* config index */ - { - 0, /* interrupt ep index */ - 1, /* ts1 index */ - NOT_SUPPORTED, /* TS2 index */ - NOT_SUPPORTED, /* AUDIO */ - NOT_SUPPORTED, /* VIDEO */ - NOT_SUPPORTED, /* VANC */ - NOT_SUPPORTED, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - } - , - - { - INDEX_SELFPOWER_DUAL_DIGITAL, /* index */ - USB_SELF_POWER, /* power_type */ - 0, /* speed , not decide yet */ - MOD_DIGITAL, /* mode */ - SOURCE_TS_BDA, /* ts1_source, digital tv only */ - 0, /* ts2_source,need update from register */ - NOT_SUPPORTED, /* analog source */ - 0, /* digital_index */ - 0, /* analog index */ - 0, /* dif_index */ - 0, /* external_index */ - - 1, /* only one configuration */ - { - { - 0, /* config index */ - { - 0, /* interrupt ep index */ - 1, /* ts1 index */ - 2, /* TS2 index */ - NOT_SUPPORTED, /* AUDIO */ - NOT_SUPPORTED, /* VIDEO */ - NOT_SUPPORTED, /* VANC */ - NOT_SUPPORTED, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - , - /* full-speed */ - { - { - 0, /* config index */ - { - 0, /* interrupt ep index */ - 1, /* ts1 index */ - 2, /* TS2 index */ - NOT_SUPPORTED, /* AUDIO */ - NOT_SUPPORTED, /* VIDEO */ - NOT_SUPPORTED, /* VANC */ - NOT_SUPPORTED, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - } - , - - { - INDEX_SELFPOWER_ANALOG_ONLY, /* index */ - USB_SELF_POWER, /* power_type */ - 0, /* speed , not decide yet */ - MOD_ANALOG | MOD_DIF | MOD_EXTERNAL, /* mode ,analog tv only */ - NOT_SUPPORTED, /* ts1_source, NOT SUPPORT */ - NOT_SUPPORTED, /* ts2_source,NOT SUPPORT */ - 0, /* analog source, need update */ - - 0, /* digital_index */ - 0, /* analog index */ - 0, /* dif_index */ - 0, /* external_index */ - - 1, /* only one configuration */ - { - { - 0, /* config index */ - { - 0, /* interrupt ep index */ - NOT_SUPPORTED, /* ts1 index */ - NOT_SUPPORTED, /* TS2 index */ - 1, /* AUDIO */ - 2, /* VIDEO */ - 3, /* VANC */ - 4, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - , - /* full-speed */ - { - { - 0, /* config index */ - { - 0, /* interrupt ep index */ - NOT_SUPPORTED, /* ts1 index */ - NOT_SUPPORTED, /* TS2 index */ - 1, /* AUDIO */ - 2, /* VIDEO */ - NOT_SUPPORTED, /* VANC */ - NOT_SUPPORTED, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - } - , - - { - INDEX_SELFPOWER_DUAL, /* index */ - USB_SELF_POWER, /* power_type */ - 0, /* speed , not decide yet */ - /* mode ,analog tv and digital path */ - MOD_ANALOG | MOD_DIF | MOD_DIGITAL | MOD_EXTERNAL, - 0, /* ts1_source,will update in register */ - NOT_SUPPORTED, /* ts2_source,NOT SUPPORT */ - 0, /* analog source need update */ - 0, /* digital_index */ - 0, /* analog index */ - 0, /* dif_index */ - 0, /* external_index */ - 1, /* only one configuration */ - { - { - 0, /* config index */ - { - 0, /* interrupt ep index */ - 1, /* ts1 index */ - NOT_SUPPORTED, /* TS2 index */ - 2, /* AUDIO */ - 3, /* VIDEO */ - 4, /* VANC */ - 5, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - , - /* full-speed */ - { - { - 0, /* config index */ - { - 0, /* interrupt ep index */ - 1, /* ts1 index */ - NOT_SUPPORTED, /* TS2 index */ - 2, /* AUDIO */ - 3, /* VIDEO */ - NOT_SUPPORTED, /* VANC */ - NOT_SUPPORTED, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - } - , - - { - INDEX_SELFPOWER_TRIPLE, /* index */ - USB_SELF_POWER, /* power_type */ - 0, /* speed , not decide yet */ - /* mode ,analog tv and digital path */ - MOD_ANALOG | MOD_DIF | MOD_DIGITAL | MOD_EXTERNAL, - 0, /* ts1_source, update in register */ - 0, /* ts2_source,update in register */ - 0, /* analog source, need update */ - - 0, /* digital_index */ - 0, /* analog index */ - 0, /* dif_index */ - 0, /* external_index */ - 1, /* only one configuration */ - { - { - 0, /* config index */ - { - 0, /* interrupt ep index */ - 1, /* ts1 index */ - 2, /* TS2 index */ - 3, /* AUDIO */ - 4, /* VIDEO */ - 5, /* VANC */ - 6, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - , - /* full-speed */ - { - { - 0, /* config index */ - { - 0, /* interrupt ep index */ - 1, /* ts1 index */ - 2, /* TS2 index */ - 3, /* AUDIO */ - 4, /* VIDEO */ - NOT_SUPPORTED, /* VANC */ - NOT_SUPPORTED, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - } - , - - { - INDEX_SELFPOWER_COMPRESSOR, /* index */ - USB_SELF_POWER, /* power_type */ - 0, /* speed , not decide yet */ - /* mode ,analog tv AND DIGITAL path */ - MOD_ANALOG | MOD_DIF | MOD_DIGITAL | MOD_EXTERNAL, - NOT_SUPPORTED, /* ts1_source, disable */ - SOURCE_TS_BDA, /* ts2_source */ - 0, /* analog source,need update */ - 0, /* digital_index */ - 0, /* analog index */ - 0, /* dif_index */ - 0, /* external_index */ - 1, /* only one configuration */ - { - { - 0, /* config index */ - { - 0, /* interrupt ep index */ - NOT_SUPPORTED, /* ts1 index */ - 1, /* TS2 index */ - 2, /* AUDIO */ - 3, /* VIDEO */ - 4, /* VANC */ - 5, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - , - /* full-speed */ - { - { - 0, /* config index */ - { - 0, /* interrupt ep index */ - NOT_SUPPORTED, /* ts1 index */ - 1, /* TS2 index */ - 2, /* AUDIO */ - 3, /* VIDEO */ - NOT_SUPPORTED, /* VANC */ - NOT_SUPPORTED, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - } - , - - { - INDEX_BUSPOWER_DIGITAL_ONLY, /* index */ - USB_BUS_POWER, /* power_type */ - 0, /* speed , not decide yet */ - MOD_DIGITAL, /* mode ,analog tv AND DIGITAL path */ - SOURCE_TS_BDA, /* ts1_source, disable */ - NOT_SUPPORTED, /* ts2_source */ - NOT_SUPPORTED, /* analog source */ - - 0, /* digital_index */ - 0, /* analog index */ - 0, /* dif_index */ - 0, /* external_index */ - - 1, /* only one configuration */ - { - { - 0, /* config index */ - { - 0, /* interrupt ep index = 2 */ - 1, /* ts1 index */ - NOT_SUPPORTED, /* TS2 index */ - NOT_SUPPORTED, /* AUDIO */ - NOT_SUPPORTED, /* VIDEO */ - NOT_SUPPORTED, /* VANC */ - NOT_SUPPORTED, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - , - /* full-speed */ - { - { - 0, /* config index */ - { - 0, /* interrupt ep index = 2 */ - 1, /* ts1 index */ - NOT_SUPPORTED, /* TS2 index */ - NOT_SUPPORTED, /* AUDIO */ - NOT_SUPPORTED, /* VIDEO */ - NOT_SUPPORTED, /* VANC */ - NOT_SUPPORTED, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - } - , - { - INDEX_BUSPOWER_ANALOG_ONLY, /* index */ - USB_BUS_POWER, /* power_type */ - 0, /* speed , not decide yet */ - MOD_ANALOG, /* mode ,analog tv AND DIGITAL path */ - NOT_SUPPORTED, /* ts1_source, disable */ - NOT_SUPPORTED, /* ts2_source */ - SOURCE_ANALOG, /* analog source--analog */ - 0, /* digital_index */ - 0, /* analog index */ - 0, /* dif_index */ - 0, /* external_index */ - 1, /* only one configuration */ - { - { - 0, /* config index */ - { - 0, /* interrupt ep index */ - NOT_SUPPORTED, /* ts1 index */ - NOT_SUPPORTED, /* TS2 index */ - 1, /* AUDIO */ - 2, /* VIDEO */ - 3, /* VANC */ - 4, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - , - { /* full-speed */ - { - 0, /* config index */ - { - 0, /* interrupt ep index */ - NOT_SUPPORTED, /* ts1 index */ - NOT_SUPPORTED, /* TS2 index */ - 1, /* AUDIO */ - 2, /* VIDEO */ - NOT_SUPPORTED, /* VANC */ - NOT_SUPPORTED, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - } - , - { - INDEX_BUSPOWER_DIF_ONLY, /* index */ - USB_BUS_POWER, /* power_type */ - 0, /* speed , not decide yet */ - /* mode ,analog tv AND DIGITAL path */ - MOD_DIF | MOD_ANALOG | MOD_DIGITAL | MOD_EXTERNAL, - SOURCE_TS_BDA, /* ts1_source, disable */ - NOT_SUPPORTED, /* ts2_source */ - SOURCE_DIF | SOURCE_ANALOG | SOURCE_EXTERNAL, /* analog source, dif */ - 0, /* digital_index */ - 0, /* analog index */ - 0, /* dif_index */ - 0, /* external_index */ - 1, /* only one configuration */ - { - { - 0, /* config index */ - { - 0, /* interrupt ep index */ - 1, /* ts1 index */ - NOT_SUPPORTED, /* TS2 index */ - 2, /* AUDIO */ - 3, /* VIDEO */ - 4, /* VANC */ - 5, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - , - { /* full speed */ - { - 0, /* config index */ - { - 0, /* interrupt ep index */ - 1, /* ts1 index */ - NOT_SUPPORTED, /* TS2 index */ - 2, /* AUDIO */ - 3, /* VIDEO */ - NOT_SUPPORTED, /* VANC */ - NOT_SUPPORTED, /* HANC */ - NOT_SUPPORTED /* ir_index */ - } - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - , - {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED, - NOT_SUPPORTED} - } - } - } - , - -}; - -/*****************************************************************/ - -u32 initialize_cx231xx(struct cx231xx *dev) -{ - u32 config_info = 0; - struct pcb_config *p_pcb_info; - u8 usb_speed = 1; /* from register,1--HS, 0--FS */ - u8 data[4] = { 0, 0, 0, 0 }; - u32 ts1_source = 0; - u32 ts2_source = 0; - u32 analog_source = 0; - u8 _current_scenario_idx = 0xff; - - ts1_source = SOURCE_TS_BDA; - ts2_source = SOURCE_TS_BDA; - - /* read board config register to find out which - pcb config it is related to */ - cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT, data, 4); - - config_info = *((u32 *) data); - usb_speed = (u8) (config_info & 0x1); - - /* Verify this device belongs to Bus power or Self power device */ - if (config_info & BUS_POWER) { /* bus-power */ - switch (config_info & BUSPOWER_MASK) { - case TS1_PORT | BUS_POWER: - cx231xx_Scenario[INDEX_BUSPOWER_DIGITAL_ONLY].speed = - usb_speed; - p_pcb_info = - &cx231xx_Scenario[INDEX_BUSPOWER_DIGITAL_ONLY]; - _current_scenario_idx = INDEX_BUSPOWER_DIGITAL_ONLY; - break; - case AVDEC_ENABLE | BUS_POWER: - cx231xx_Scenario[INDEX_BUSPOWER_ANALOG_ONLY].speed = - usb_speed; - p_pcb_info = - &cx231xx_Scenario[INDEX_BUSPOWER_ANALOG_ONLY]; - _current_scenario_idx = INDEX_BUSPOWER_ANALOG_ONLY; - break; - case AVDEC_ENABLE | BUS_POWER | TS1_PORT: - cx231xx_Scenario[INDEX_BUSPOWER_DIF_ONLY].speed = - usb_speed; - p_pcb_info = &cx231xx_Scenario[INDEX_BUSPOWER_DIF_ONLY]; - _current_scenario_idx = INDEX_BUSPOWER_DIF_ONLY; - break; - default: - cx231xx_info("bad config in buspower!!!!\n"); - cx231xx_info("config_info=%x\n", - (config_info & BUSPOWER_MASK)); - return 1; - } - } else { /* self-power */ - - switch (config_info & SELFPOWER_MASK) { - case TS1_PORT | SELF_POWER: - cx231xx_Scenario[INDEX_SELFPOWER_DIGITAL_ONLY].speed = - usb_speed; - p_pcb_info = - &cx231xx_Scenario[INDEX_SELFPOWER_DIGITAL_ONLY]; - _current_scenario_idx = INDEX_SELFPOWER_DIGITAL_ONLY; - break; - case TS1_TS2_PORT | SELF_POWER: - cx231xx_Scenario[INDEX_SELFPOWER_DUAL_DIGITAL].speed = - usb_speed; - cx231xx_Scenario[INDEX_SELFPOWER_DUAL_DIGITAL]. - ts2_source = ts2_source; - p_pcb_info = - &cx231xx_Scenario[INDEX_SELFPOWER_DUAL_DIGITAL]; - _current_scenario_idx = INDEX_SELFPOWER_DUAL_DIGITAL; - break; - case AVDEC_ENABLE | SELF_POWER: - cx231xx_Scenario[INDEX_SELFPOWER_ANALOG_ONLY].speed = - usb_speed; - cx231xx_Scenario[INDEX_SELFPOWER_ANALOG_ONLY]. - analog_source = analog_source; - p_pcb_info = - &cx231xx_Scenario[INDEX_SELFPOWER_ANALOG_ONLY]; - _current_scenario_idx = INDEX_SELFPOWER_ANALOG_ONLY; - break; - case AVDEC_ENABLE | TS1_PORT | SELF_POWER: - cx231xx_Scenario[INDEX_SELFPOWER_DUAL].speed = - usb_speed; - cx231xx_Scenario[INDEX_SELFPOWER_DUAL].ts1_source = - ts1_source; - cx231xx_Scenario[INDEX_SELFPOWER_DUAL].analog_source = - analog_source; - p_pcb_info = &cx231xx_Scenario[INDEX_SELFPOWER_DUAL]; - _current_scenario_idx = INDEX_SELFPOWER_DUAL; - break; - case AVDEC_ENABLE | TS1_TS2_PORT | SELF_POWER: - cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].speed = - usb_speed; - cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].ts1_source = - ts1_source; - cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].ts2_source = - ts2_source; - cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].analog_source = - analog_source; - p_pcb_info = &cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE]; - _current_scenario_idx = INDEX_SELFPOWER_TRIPLE; - break; - case AVDEC_ENABLE | TS1VIP_TS2_PORT | SELF_POWER: - cx231xx_Scenario[INDEX_SELFPOWER_COMPRESSOR].speed = - usb_speed; - cx231xx_Scenario[INDEX_SELFPOWER_COMPRESSOR]. - analog_source = analog_source; - p_pcb_info = - &cx231xx_Scenario[INDEX_SELFPOWER_COMPRESSOR]; - _current_scenario_idx = INDEX_SELFPOWER_COMPRESSOR; - break; - default: - cx231xx_info("bad senario!!!!!\n"); - cx231xx_info("config_info=%x\n", - (config_info & SELFPOWER_MASK)); - return 1; - } - } - - dev->current_scenario_idx = _current_scenario_idx; - - memcpy(&dev->current_pcb_config, p_pcb_info, - sizeof(struct pcb_config)); - - if (pcb_debug) { - cx231xx_info("SC(0x00) register = 0x%x\n", config_info); - cx231xx_info("scenario %d\n", - (dev->current_pcb_config.index) + 1); - cx231xx_info("type=%x\n", dev->current_pcb_config.type); - cx231xx_info("mode=%x\n", dev->current_pcb_config.mode); - cx231xx_info("speed=%x\n", dev->current_pcb_config.speed); - cx231xx_info("ts1_source=%x\n", - dev->current_pcb_config.ts1_source); - cx231xx_info("ts2_source=%x\n", - dev->current_pcb_config.ts2_source); - cx231xx_info("analog_source=%x\n", - dev->current_pcb_config.analog_source); - } - - return 0; -} diff --git a/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h b/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h deleted file mode 100644 index f5e46e89f3ab..000000000000 --- a/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - cx231xx-pcb-cfg.h - driver for Conexant - Cx23100/101/102 USB video capture devices - - Copyright (C) 2008 <srinivasa.deevi at conexant dot com> - - 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. - */ - -#ifndef _PCB_CONFIG_H_ -#define _PCB_CONFIG_H_ - -#include <linux/init.h> -#include <linux/module.h> - -/*************************************************************************** - * Class Information * -***************************************************************************/ -#define CLASS_DEFAULT 0xFF - -enum VENDOR_REQUEST_TYPE { - /* Set/Get I2C */ - VRT_SET_I2C0 = 0x0, - VRT_SET_I2C1 = 0x1, - VRT_SET_I2C2 = 0x2, - VRT_GET_I2C0 = 0x4, - VRT_GET_I2C1 = 0x5, - VRT_GET_I2C2 = 0x6, - - /* Set/Get GPIO */ - VRT_SET_GPIO = 0x8, - VRT_GET_GPIO = 0x9, - - /* Set/Get GPIE */ - VRT_SET_GPIE = 0xA, - VRT_GET_GPIE = 0xB, - - /* Set/Get Register Control/Status */ - VRT_SET_REGISTER = 0xC, - VRT_GET_REGISTER = 0xD, - - /* Get Extended Compat ID Descriptor */ - VRT_GET_EXTCID_DESC = 0xFF, -}; - -enum BYTE_ENABLE_MASK { - ENABLE_ONE_BYTE = 0x1, - ENABLE_TWE_BYTE = 0x3, - ENABLE_THREE_BYTE = 0x7, - ENABLE_FOUR_BYTE = 0xF, -}; - -#define SPEED_MASK 0x1 -enum USB_SPEED{ - FULL_SPEED = 0x0, /* 0: full speed */ - HIGH_SPEED = 0x1 /* 1: high speed */ -}; - -enum _true_false{ - FALSE = 0, - TRUE = 1 -}; - -#define TS_MASK 0x6 -enum TS_PORT{ - NO_TS_PORT = 0x0, /* 2'b00: Neither port used. PCB not a Hybrid, - only offers Analog TV or Video */ - TS1_PORT = 0x4, /* 2'b10: TS1 Input (Hybrid mode : - Digital or External Analog/Compressed source) */ - TS1_TS2_PORT = 0x6, /* 2'b11: TS1 & TS2 Inputs - (Dual inputs from Digital and/or - External Analog/Compressed sources) */ - TS1_EXT_CLOCK = 0x6, /* 2'b11: TS1 & TS2 as selector - to external clock */ - TS1VIP_TS2_PORT = 0x2 /* 2'b01: TS1 used as 656/VIP Output, - TS2 Input (from Compressor) */ -}; - -#define EAVP_MASK 0x8 -enum EAV_PRESENT{ - NO_EXTERNAL_AV = 0x0, /* 0: No External A/V inputs - (no need for i2s blcok), - Analog Tuner must be present */ - EXTERNAL_AV = 0x8 /* 1: External A/V inputs - present (requires i2s blk) */ -}; - -#define ATM_MASK 0x30 -enum AT_MODE{ - DIF_TUNER = 0x30, /* 2'b11: IF Tuner (requires use of DIF) */ - BASEBAND_SOUND = 0x20, /* 2'b10: Baseband Composite & - Sound-IF Signals present */ - NO_TUNER = 0x10 /* 2'b0x: No Analog Tuner present */ -}; - -#define PWR_SEL_MASK 0x40 -enum POWE_TYPE{ - SELF_POWER = 0x0, /* 0: self power */ - BUS_POWER = 0x40 /* 1: bus power */ -}; - -enum USB_POWE_TYPE{ - USB_SELF_POWER = 0, - USB_BUS_POWER -}; - -#define BO_0_MASK 0x80 -enum AVDEC_STATUS{ - AVDEC_DISABLE = 0x0, /* 0: A/V Decoder Disabled */ - AVDEC_ENABLE = 0x80 /* 1: A/V Decoder Enabled */ -}; - -#define BO_1_MASK 0x100 - -#define BUSPOWER_MASK 0xC4 /* for Polaris spec 0.8 */ -#define SELFPOWER_MASK 0x86 - -/***************************************************************************/ -#define NOT_DECIDE_YET 0xFE -#define NOT_SUPPORTED 0xFF - -/*************************************************************************** - * for mod field use * -***************************************************************************/ -#define MOD_DIGITAL 0x1 -#define MOD_ANALOG 0x2 -#define MOD_DIF 0x4 -#define MOD_EXTERNAL 0x8 -#define CAP_ALL_MOD 0x0f - -/*************************************************************************** - * source define * -***************************************************************************/ -#define SOURCE_DIGITAL 0x1 -#define SOURCE_ANALOG 0x2 -#define SOURCE_DIF 0x4 -#define SOURCE_EXTERNAL 0x8 -#define SOURCE_TS_BDA 0x10 -#define SOURCE_TS_ENCODE 0x20 -#define SOURCE_TS_EXTERNAL 0x40 - -/*************************************************************************** - * interface information define * -***************************************************************************/ -struct INTERFACE_INFO { - u8 interrupt_index; - u8 ts1_index; - u8 ts2_index; - u8 audio_index; - u8 video_index; - u8 vanc_index; /* VBI */ - u8 hanc_index; /* Sliced CC */ - u8 ir_index; -}; - -enum INDEX_INTERFACE_INFO{ - INDEX_INTERRUPT = 0x0, - INDEX_TS1, - INDEX_TS2, - INDEX_AUDIO, - INDEX_VIDEO, - INDEX_VANC, - INDEX_HANC, - INDEX_IR, -}; - -/*************************************************************************** - * configuration information define * -***************************************************************************/ -struct CONFIG_INFO { - u8 config_index; - struct INTERFACE_INFO interface_info; -}; - -struct pcb_config { - u8 index; - u8 type; /* bus power or self power, - self power--0, bus_power--1 */ - u8 speed; /* usb speed, 2.0--1, 1.1--0 */ - u8 mode; /* digital , anlog, dif or external A/V */ - u32 ts1_source; /* three source -- BDA,External,encode */ - u32 ts2_source; - u32 analog_source; - u8 digital_index; /* bus-power used */ - u8 analog_index; /* bus-power used */ - u8 dif_index; /* bus-power used */ - u8 external_index; /* bus-power used */ - u8 config_num; /* current config num, 0,1,2, - for self-power, always 0 */ - struct CONFIG_INFO hs_config_info[3]; - struct CONFIG_INFO fs_config_info[3]; -}; - -enum INDEX_PCB_CONFIG{ - INDEX_SELFPOWER_DIGITAL_ONLY = 0x0, - INDEX_SELFPOWER_DUAL_DIGITAL, - INDEX_SELFPOWER_ANALOG_ONLY, - INDEX_SELFPOWER_DUAL, - INDEX_SELFPOWER_TRIPLE, - INDEX_SELFPOWER_COMPRESSOR, - INDEX_BUSPOWER_DIGITAL_ONLY, - INDEX_BUSPOWER_ANALOG_ONLY, - INDEX_BUSPOWER_DIF_ONLY, - INDEX_BUSPOWER_EXTERNAL_ONLY, - INDEX_BUSPOWER_EXTERNAL_ANALOG, - INDEX_BUSPOWER_EXTERNAL_DIF, - INDEX_BUSPOWER_EXTERNAL_DIGITAL, - INDEX_BUSPOWER_DIGITAL_ANALOG, - INDEX_BUSPOWER_DIGITAL_DIF, - INDEX_BUSPOWER_DIGITAL_ANALOG_EXTERNAL, - INDEX_BUSPOWER_DIGITAL_DIF_EXTERNAL, -}; - -/***************************************************************************/ -struct cx231xx; - -u32 initialize_cx231xx(struct cx231xx *p_dev); - -#endif diff --git a/drivers/media/video/cx231xx/cx231xx-reg.h b/drivers/media/video/cx231xx/cx231xx-reg.h deleted file mode 100644 index 750c5d37d569..000000000000 --- a/drivers/media/video/cx231xx/cx231xx-reg.h +++ /dev/null @@ -1,1564 +0,0 @@ -/* - cx231xx-reg.h - driver for Conexant Cx23100/101/102 - USB video capture devices - - Copyright (C) 2008 <srinivasa.deevi at conexant dot com> - - 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. - */ - -#ifndef _CX231XX_REG_H -#define _CX231XX_REG_H - -/***************************************************************************** - * VBI codes * -*****************************************************************************/ - -#define SAV_ACTIVE_VIDEO_FIELD1 0x80 -#define EAV_ACTIVE_VIDEO_FIELD1 0x90 - -#define SAV_ACTIVE_VIDEO_FIELD2 0xc0 -#define EAV_ACTIVE_VIDEO_FIELD2 0xd0 - -#define SAV_VBLANK_FIELD1 0xa0 -#define EAV_VBLANK_FIELD1 0xb0 - -#define SAV_VBLANK_FIELD2 0xe0 -#define EAV_VBLANK_FIELD2 0xf0 - -#define SAV_VBI_FIELD1 0x20 -#define EAV_VBI_FIELD1 0x30 - -#define SAV_VBI_FIELD2 0x60 -#define EAV_VBI_FIELD2 0x70 - -/*****************************************************************************/ -/* Audio ADC Registers */ -#define CH_PWR_CTRL1 0x0000000e -#define CH_PWR_CTRL2 0x0000000f -/*****************************************************************************/ - -#define HOST_REG1 0x000 -#define FLD_FORCE_CHIP_SEL 0x80 -#define FLD_AUTO_INC_DIS 0x20 -#define FLD_PREFETCH_EN 0x10 -/* Reserved [2:3] */ -#define FLD_DIGITAL_PWR_DN 0x02 -#define FLD_SLEEP 0x01 - -/*****************************************************************************/ -#define HOST_REG2 0x001 - -/*****************************************************************************/ -#define HOST_REG3 0x002 - -/*****************************************************************************/ -/* added for polaris */ -#define GPIO_PIN_CTL0 0x3 -#define GPIO_PIN_CTL1 0x4 -#define GPIO_PIN_CTL2 0x5 -#define GPIO_PIN_CTL3 0x6 -#define TS1_PIN_CTL0 0x7 -#define TS1_PIN_CTL1 0x8 -/*****************************************************************************/ - -#define FLD_CLK_IN_EN 0x80 -#define FLD_XTAL_CTRL 0x70 -#define FLD_BB_CLK_MODE 0x0C -#define FLD_REF_DIV_PLL 0x02 -#define FLD_REF_SEL_PLL1 0x01 - -/*****************************************************************************/ -#define CHIP_CTRL 0x100 -/* Reserved [27] */ -/* Reserved [31:21] */ -#define FLD_CHIP_ACFG_DIS 0x00100000 -/* Reserved [19] */ -#define FLD_DUAL_MODE_ADC2 0x00040000 -#define FLD_SIF_EN 0x00020000 -#define FLD_SOFT_RST 0x00010000 -#define FLD_DEVICE_ID 0x0000ffff - -/*****************************************************************************/ -#define AFE_CTRL 0x104 -#define AFE_CTRL_C2HH_SRC_CTRL 0x104 -#define FLD_DIF_OUT_SEL 0xc0000000 -#define FLD_AUX_PLL_CLK_ALT_SEL 0x3c000000 -#define FLD_UV_ORDER_MODE 0x02000000 -#define FLD_FUNC_MODE 0x01800000 -#define FLD_ROT1_PHASE_CTL 0x007f8000 -#define FLD_AUD_IN_SEL 0x00004000 -#define FLD_LUMA_IN_SEL 0x00002000 -#define FLD_CHROMA_IN_SEL 0x00001000 -/* reserve [11:10] */ -#define FLD_INV_SPEC_DIS 0x00000200 -#define FLD_VGA_SEL_CH3 0x00000100 -#define FLD_VGA_SEL_CH2 0x00000080 -#define FLD_VGA_SEL_CH1 0x00000040 -#define FLD_DCR_BYP_CH1 0x00000020 -#define FLD_DCR_BYP_CH2 0x00000010 -#define FLD_DCR_BYP_CH3 0x00000008 -#define FLD_EN_12DB_CH3 0x00000004 -#define FLD_EN_12DB_CH2 0x00000002 -#define FLD_EN_12DB_CH1 0x00000001 - -/* redefine in Cx231xx */ -/*****************************************************************************/ -#define DC_CTRL1 0x108 -/* reserve [31:30] */ -#define FLD_CLAMP_LVL_CH1 0x3fff8000 -#define FLD_CLAMP_LVL_CH2 0x00007fff -/*****************************************************************************/ - -/*****************************************************************************/ -#define DC_CTRL2 0x10c -/* reserve [31:28] */ -#define FLD_CLAMP_LVL_CH3 0x00fffe00 -#define FLD_CLAMP_WIND_LENTH 0x000001e0 -#define FLD_C2HH_SAT_MIN 0x0000001e -#define FLD_FLT_BYP_SEL 0x00000001 -/*****************************************************************************/ - -/*****************************************************************************/ -#define DC_CTRL3 0x110 -/* reserve [31:16] */ -#define FLD_ERR_GAIN_CTL 0x00070000 -#define FLD_LPF_MIN 0x0000ffff -/*****************************************************************************/ - -/*****************************************************************************/ -#define DC_CTRL4 0x114 -/* reserve [31:31] */ -#define FLD_INTG_CH1 0x7fffffff -/*****************************************************************************/ - -/*****************************************************************************/ -#define DC_CTRL5 0x118 -/* reserve [31:31] */ -#define FLD_INTG_CH2 0x7fffffff -/*****************************************************************************/ - -/*****************************************************************************/ -#define DC_CTRL6 0x11c -/* reserve [31:31] */ -#define FLD_INTG_CH3 0x7fffffff -/*****************************************************************************/ - -/*****************************************************************************/ -#define PIN_CTRL 0x120 -#define FLD_OEF_AGC_RF 0x00000001 -#define FLD_OEF_AGC_IFVGA 0x00000002 -#define FLD_OEF_AGC_IF 0x00000004 -#define FLD_REG_BO_PUD 0x80000000 -#define FLD_IR_IRQ_STAT 0x40000000 -#define FLD_AUD_IRQ_STAT 0x20000000 -#define FLD_VID_IRQ_STAT 0x10000000 -/* Reserved [27:26] */ -#define FLD_IRQ_N_OUT_EN 0x02000000 -#define FLD_IRQ_N_POLAR 0x01000000 -/* Reserved [23:6] */ -#define FLD_OE_AUX_PLL_CLK 0x00000020 -#define FLD_OE_I2S_BCLK 0x00000010 -#define FLD_OE_I2S_WCLK 0x00000008 -#define FLD_OE_AGC_IF 0x00000004 -#define FLD_OE_AGC_IFVGA 0x00000002 -#define FLD_OE_AGC_RF 0x00000001 - -/*****************************************************************************/ -#define AUD_IO_CTRL 0x124 -/* Reserved [31:8] */ -#define FLD_I2S_PORT_DIR 0x00000080 -#define FLD_I2S_OUT_SRC 0x00000040 -#define FLD_AUD_CHAN3_SRC 0x00000030 -#define FLD_AUD_CHAN2_SRC 0x0000000c -#define FLD_AUD_CHAN1_SRC 0x00000003 - -/*****************************************************************************/ -#define AUD_LOCK1 0x128 -#define FLD_AUD_LOCK_KI_SHIFT 0xc0000000 -#define FLD_AUD_LOCK_KD_SHIFT 0x30000000 -/* Reserved [27:25] */ -#define FLD_EN_AV_LOCK 0x01000000 -#define FLD_VID_COUNT 0x00ffffff - -/*****************************************************************************/ -#define AUD_LOCK2 0x12c -#define FLD_AUD_LOCK_KI_MULT 0xf0000000 -#define FLD_AUD_LOCK_KD_MULT 0x0F000000 -/* Reserved [23:22] */ -#define FLD_AUD_LOCK_FREQ_SHIFT 0x00300000 -#define FLD_AUD_COUNT 0x000fffff - -/*****************************************************************************/ -#define AFE_DIAG_CTRL1 0x134 -/* Reserved [31:16] */ -#define FLD_CUV_DLY_LENGTH 0x0000ff00 -#define FLD_YC_DLY_LENGTH 0x000000ff - -/*****************************************************************************/ -/* Poalris redefine */ -#define AFE_DIAG_CTRL3 0x138 -/* Reserved [31:26] */ -#define FLD_AUD_DUAL_FLAG_POL 0x02000000 -#define FLD_VID_DUAL_FLAG_POL 0x01000000 -/* Reserved [23:23] */ -#define FLD_COL_CLAMP_DIS_CH1 0x00400000 -#define FLD_COL_CLAMP_DIS_CH2 0x00200000 -#define FLD_COL_CLAMP_DIS_CH3 0x00100000 - -#define TEST_CTRL1 0x144 -/* Reserved [31:29] */ -#define FLD_LBIST_EN 0x10000000 -/* Reserved [27:10] */ -#define FLD_FI_BIST_INTR_R 0x0000200 -#define FLD_FI_BIST_INTR_L 0x0000100 -#define FLD_BIST_FAIL_AUD_PLL 0x0000080 -#define FLD_BIST_INTR_AUD_PLL 0x0000040 -#define FLD_BIST_FAIL_VID_PLL 0x0000020 -#define FLD_BIST_INTR_VID_PLL 0x0000010 -/* Reserved [3:1] */ -#define FLD_CIR_TEST_DIS 0x00000001 - -/*****************************************************************************/ -#define TEST_CTRL2 0x148 -#define FLD_TSXCLK_POL_CTL 0x80000000 -#define FLD_ISO_CTL_SEL 0x40000000 -#define FLD_ISO_CTL_EN 0x20000000 -#define FLD_BIST_DEBUGZ 0x10000000 -#define FLD_AUD_BIST_TEST_H 0x0f000000 -/* Reserved [23:22] */ -#define FLD_FLTRN_BIST_TEST_H 0x00020000 -#define FLD_VID_BIST_TEST_H 0x00010000 -/* Reserved [19:17] */ -#define FLD_BIST_TEST_H 0x00010000 -/* Reserved [15:13] */ -#define FLD_TAB_EN 0x00001000 -/* Reserved [11:0] */ - -/*****************************************************************************/ -#define BIST_STAT 0x14c -#define FLD_AUD_BIST_FAIL_H 0xfff00000 -#define FLD_FLTRN_BIST_FAIL_H 0x00180000 -#define FLD_VID_BIST_FAIL_H 0x00070000 -#define FLD_AUD_BIST_TST_DONE 0x0000fff0 -#define FLD_FLTRN_BIST_TST_DONE 0x00000008 -#define FLD_VID_BIST_TST_DONE 0x00000007 - -/*****************************************************************************/ -/* DirectIF registers definition have been moved to DIF_reg.h */ -/*****************************************************************************/ -#define MODE_CTRL 0x400 -#define FLD_AFD_PAL60_DIS 0x20000000 -#define FLD_AFD_FORCE_SECAM 0x10000000 -#define FLD_AFD_FORCE_PALNC 0x08000000 -#define FLD_AFD_FORCE_PAL 0x04000000 -#define FLD_AFD_PALM_SEL 0x03000000 -#define FLD_CKILL_MODE 0x00300000 -#define FLD_COMB_NOTCH_MODE 0x00c00000 /* bit[19:18] */ -#define FLD_CLR_LOCK_STAT 0x00020000 -#define FLD_FAST_LOCK_MD 0x00010000 -#define FLD_WCEN 0x00008000 -#define FLD_CAGCEN 0x00004000 -#define FLD_CKILLEN 0x00002000 -#define FLD_AUTO_SC_LOCK 0x00001000 -#define FLD_MAN_SC_FAST_LOCK 0x00000800 -#define FLD_INPUT_MODE 0x00000600 -#define FLD_AFD_ACQUIRE 0x00000100 -#define FLD_AFD_NTSC_SEL 0x00000080 -#define FLD_AFD_PAL_SEL 0x00000040 -#define FLD_ACFG_DIS 0x00000020 -#define FLD_SQ_PIXEL 0x00000010 -#define FLD_VID_FMT_SEL 0x0000000f - -/*****************************************************************************/ -#define OUT_CTRL1 0x404 -#define FLD_POLAR 0x7f000000 -/* Reserved [23] */ -#define FLD_RND_MODE 0x00600000 -#define FLD_VIPCLAMP_EN 0x00100000 -#define FLD_VIPBLANK_EN 0x00080000 -#define FLD_VIP_OPT_AL 0x00040000 -#define FLD_IDID0_SOURCE 0x00020000 -#define FLD_DCMODE 0x00010000 -#define FLD_CLK_GATING 0x0000c000 -#define FLD_CLK_INVERT 0x00002000 -#define FLD_HSFMT 0x00001000 -#define FLD_VALIDFMT 0x00000800 -#define FLD_ACTFMT 0x00000400 -#define FLD_SWAPRAW 0x00000200 -#define FLD_CLAMPRAW_EN 0x00000100 -#define FLD_BLUE_FIELD_EN 0x00000080 -#define FLD_BLUE_FIELD_ACT 0x00000040 -#define FLD_TASKBIT_VAL 0x00000020 -#define FLD_ANC_DATA_EN 0x00000010 -#define FLD_VBIHACTRAW_EN 0x00000008 -#define FLD_MODE10B 0x00000004 -#define FLD_OUT_MODE 0x00000003 - -/*****************************************************************************/ -#define OUT_CTRL2 0x408 -#define FLD_AUD_GRP 0xc0000000 -#define FLD_SAMPLE_RATE 0x30000000 -#define FLD_AUD_ANC_EN 0x08000000 -#define FLD_EN_C 0x04000000 -#define FLD_EN_B 0x02000000 -#define FLD_EN_A 0x01000000 -/* Reserved [23:20] */ -#define FLD_IDID1_LSB 0x000c0000 -#define FLD_IDID0_LSB 0x00030000 -#define FLD_IDID1_MSB 0x0000ff00 -#define FLD_IDID0_MSB 0x000000ff - -/*****************************************************************************/ -#define GEN_STAT 0x40c -#define FLD_VCR_DETECT 0x00800000 -#define FLD_SPECIAL_PLAY_N 0x00400000 -#define FLD_VPRES 0x00200000 -#define FLD_AGC_LOCK 0x00100000 -#define FLD_CSC_LOCK 0x00080000 -#define FLD_VLOCK 0x00040000 -#define FLD_SRC_LOCK 0x00020000 -#define FLD_HLOCK 0x00010000 -#define FLD_VSYNC_N 0x00008000 -#define FLD_SRC_FIFO_UFLOW 0x00004000 -#define FLD_SRC_FIFO_OFLOW 0x00002000 -#define FLD_FIELD 0x00001000 -#define FLD_AFD_FMT_STAT 0x00000f00 -#define FLD_MV_TYPE2_PAIR 0x00000080 -#define FLD_MV_T3CS 0x00000040 -#define FLD_MV_CS 0x00000020 -#define FLD_MV_PSP 0x00000010 -/* Reserved [3] */ -#define FLD_MV_CDAT 0x00000003 - -/*****************************************************************************/ -#define INT_STAT_MASK 0x410 -#define FLD_COMB_3D_FIFO_MSK 0x80000000 -#define FLD_WSS_DAT_AVAIL_MSK 0x40000000 -#define FLD_GS2_DAT_AVAIL_MSK 0x20000000 -#define FLD_GS1_DAT_AVAIL_MSK 0x10000000 -#define FLD_CC_DAT_AVAIL_MSK 0x08000000 -#define FLD_VPRES_CHANGE_MSK 0x04000000 -#define FLD_MV_CHANGE_MSK 0x02000000 -#define FLD_END_VBI_EVEN_MSK 0x01000000 -#define FLD_END_VBI_ODD_MSK 0x00800000 -#define FLD_FMT_CHANGE_MSK 0x00400000 -#define FLD_VSYNC_TRAIL_MSK 0x00200000 -#define FLD_HLOCK_CHANGE_MSK 0x00100000 -#define FLD_VLOCK_CHANGE_MSK 0x00080000 -#define FLD_CSC_LOCK_CHANGE_MSK 0x00040000 -#define FLD_SRC_FIFO_UFLOW_MSK 0x00020000 -#define FLD_SRC_FIFO_OFLOW_MSK 0x00010000 -#define FLD_COMB_3D_FIFO_STAT 0x00008000 -#define FLD_WSS_DAT_AVAIL_STAT 0x00004000 -#define FLD_GS2_DAT_AVAIL_STAT 0x00002000 -#define FLD_GS1_DAT_AVAIL_STAT 0x00001000 -#define FLD_CC_DAT_AVAIL_STAT 0x00000800 -#define FLD_VPRES_CHANGE_STAT 0x00000400 -#define FLD_MV_CHANGE_STAT 0x00000200 -#define FLD_END_VBI_EVEN_STAT 0x00000100 -#define FLD_END_VBI_ODD_STAT 0x00000080 -#define FLD_FMT_CHANGE_STAT 0x00000040 -#define FLD_VSYNC_TRAIL_STAT 0x00000020 -#define FLD_HLOCK_CHANGE_STAT 0x00000010 -#define FLD_VLOCK_CHANGE_STAT 0x00000008 -#define FLD_CSC_LOCK_CHANGE_STAT 0x00000004 -#define FLD_SRC_FIFO_UFLOW_STAT 0x00000002 -#define FLD_SRC_FIFO_OFLOW_STAT 0x00000001 - -/*****************************************************************************/ -#define LUMA_CTRL 0x414 -#define BRIGHTNESS_CTRL_BYTE 0x414 -#define CONTRAST_CTRL_BYTE 0x415 -#define LUMA_CTRL_BYTE_3 0x416 -#define FLD_LUMA_CORE_SEL 0x00c00000 -#define FLD_RANGE 0x00300000 -/* Reserved [19] */ -#define FLD_PEAK_EN 0x00040000 -#define FLD_PEAK_SEL 0x00030000 -#define FLD_CNTRST 0x0000ff00 -#define FLD_BRITE 0x000000ff - -/*****************************************************************************/ -#define HSCALE_CTRL 0x418 -#define FLD_HFILT 0x03000000 -#define FLD_HSCALE 0x00ffffff - -/*****************************************************************************/ -#define VSCALE_CTRL 0x41c -#define FLD_LINE_AVG_DIS 0x01000000 -/* Reserved [23:20] */ -#define FLD_VS_INTRLACE 0x00080000 -#define FLD_VFILT 0x00070000 -/* Reserved [15:13] */ -#define FLD_VSCALE 0x00001fff - -/*****************************************************************************/ -#define CHROMA_CTRL 0x420 -#define USAT_CTRL_BYTE 0x420 -#define VSAT_CTRL_BYTE 0x421 -#define HUE_CTRL_BYTE 0x422 -#define FLD_C_LPF_EN 0x20000000 -#define FLD_CHR_DELAY 0x1c000000 -#define FLD_C_CORE_SEL 0x03000000 -#define FLD_HUE 0x00ff0000 -#define FLD_VSAT 0x0000ff00 -#define FLD_USAT 0x000000ff - -/*****************************************************************************/ -#define VBI_LINE_CTRL1 0x424 -#define FLD_VBI_MD_LINE4 0xff000000 -#define FLD_VBI_MD_LINE3 0x00ff0000 -#define FLD_VBI_MD_LINE2 0x0000ff00 -#define FLD_VBI_MD_LINE1 0x000000ff - -/*****************************************************************************/ -#define VBI_LINE_CTRL2 0x428 -#define FLD_VBI_MD_LINE8 0xff000000 -#define FLD_VBI_MD_LINE7 0x00ff0000 -#define FLD_VBI_MD_LINE6 0x0000ff00 -#define FLD_VBI_MD_LINE5 0x000000ff - -/*****************************************************************************/ -#define VBI_LINE_CTRL3 0x42c -#define FLD_VBI_MD_LINE12 0xff000000 -#define FLD_VBI_MD_LINE11 0x00ff0000 -#define FLD_VBI_MD_LINE10 0x0000ff00 -#define FLD_VBI_MD_LINE9 0x000000ff - -/*****************************************************************************/ -#define VBI_LINE_CTRL4 0x430 -#define FLD_VBI_MD_LINE16 0xff000000 -#define FLD_VBI_MD_LINE15 0x00ff0000 -#define FLD_VBI_MD_LINE14 0x0000ff00 -#define FLD_VBI_MD_LINE13 0x000000ff - -/*****************************************************************************/ -#define VBI_LINE_CTRL5 0x434 -#define FLD_VBI_MD_LINE17 0x000000ff - -/*****************************************************************************/ -#define VBI_FC_CFG 0x438 -#define FLD_FC_ALT2 0xff000000 -#define FLD_FC_ALT1 0x00ff0000 -#define FLD_FC_ALT2_TYPE 0x0000f000 -#define FLD_FC_ALT1_TYPE 0x00000f00 -/* Reserved [7:1] */ -#define FLD_FC_SEARCH_MODE 0x00000001 - -/*****************************************************************************/ -#define VBI_MISC_CFG1 0x43c -#define FLD_TTX_PKTADRU 0xfff00000 -#define FLD_TTX_PKTADRL 0x000fff00 -/* Reserved [7:6] */ -#define FLD_MOJI_PACK_DIS 0x00000020 -#define FLD_VPS_DEC_DIS 0x00000010 -#define FLD_CRI_MARG_SCALE 0x0000000c -#define FLD_EDGE_RESYNC_EN 0x00000002 -#define FLD_ADAPT_SLICE_DIS 0x00000001 - -/*****************************************************************************/ -#define VBI_MISC_CFG2 0x440 -#define FLD_HAMMING_TYPE 0x0f000000 -/* Reserved [23:20] */ -#define FLD_WSS_FIFO_RST 0x00080000 -#define FLD_GS2_FIFO_RST 0x00040000 -#define FLD_GS1_FIFO_RST 0x00020000 -#define FLD_CC_FIFO_RST 0x00010000 -/* Reserved [15:12] */ -#define FLD_VBI3_SDID 0x00000f00 -#define FLD_VBI2_SDID 0x000000f0 -#define FLD_VBI1_SDID 0x0000000f - -/*****************************************************************************/ -#define VBI_PAY1 0x444 -#define FLD_GS1_FIFO_DAT 0xFF000000 -#define FLD_GS1_STAT 0x00FF0000 -#define FLD_CC_FIFO_DAT 0x0000FF00 -#define FLD_CC_STAT 0x000000FF - -/*****************************************************************************/ -#define VBI_PAY2 0x448 -#define FLD_WSS_FIFO_DAT 0xff000000 -#define FLD_WSS_STAT 0x00ff0000 -#define FLD_GS2_FIFO_DAT 0x0000ff00 -#define FLD_GS2_STAT 0x000000ff - -/*****************************************************************************/ -#define VBI_CUST1_CFG1 0x44c -/* Reserved [31] */ -#define FLD_VBI1_CRIWIN 0x7f000000 -#define FLD_VBI1_SLICE_DIST 0x00f00000 -#define FLD_VBI1_BITINC 0x000fff00 -#define FLD_VBI1_HDELAY 0x000000ff - -/*****************************************************************************/ -#define VBI_CUST1_CFG2 0x450 -#define FLD_VBI1_FC_LENGTH 0x1f000000 -#define FLD_VBI1_FRAME_CODE 0x00ffffff - -/*****************************************************************************/ -#define VBI_CUST1_CFG3 0x454 -#define FLD_VBI1_HAM_EN 0x80000000 -#define FLD_VBI1_FIFO_MODE 0x70000000 -#define FLD_VBI1_FORMAT_TYPE 0x0f000000 -#define FLD_VBI1_PAYLD_LENGTH 0x00ff0000 -#define FLD_VBI1_CRI_LENGTH 0x0000f000 -#define FLD_VBI1_CRI_MARGIN 0x00000f00 -#define FLD_VBI1_CRI_TIME 0x000000ff - -/*****************************************************************************/ -#define VBI_CUST2_CFG1 0x458 -/* Reserved [31] */ -#define FLD_VBI2_CRIWIN 0x7f000000 -#define FLD_VBI2_SLICE_DIST 0x00f00000 -#define FLD_VBI2_BITINC 0x000fff00 -#define FLD_VBI2_HDELAY 0x000000ff - -/*****************************************************************************/ -#define VBI_CUST2_CFG2 0x45c -#define FLD_VBI2_FC_LENGTH 0x1f000000 -#define FLD_VBI2_FRAME_CODE 0x00ffffff - -/*****************************************************************************/ -#define VBI_CUST2_CFG3 0x460 -#define FLD_VBI2_HAM_EN 0x80000000 -#define FLD_VBI2_FIFO_MODE 0x70000000 -#define FLD_VBI2_FORMAT_TYPE 0x0f000000 -#define FLD_VBI2_PAYLD_LENGTH 0x00ff0000 -#define FLD_VBI2_CRI_LENGTH 0x0000f000 -#define FLD_VBI2_CRI_MARGIN 0x00000f00 -#define FLD_VBI2_CRI_TIME 0x000000ff - -/*****************************************************************************/ -#define VBI_CUST3_CFG1 0x464 -/* Reserved [31] */ -#define FLD_VBI3_CRIWIN 0x7f000000 -#define FLD_VBI3_SLICE_DIST 0x00f00000 -#define FLD_VBI3_BITINC 0x000fff00 -#define FLD_VBI3_HDELAY 0x000000ff - -/*****************************************************************************/ -#define VBI_CUST3_CFG2 0x468 -#define FLD_VBI3_FC_LENGTH 0x1f000000 -#define FLD_VBI3_FRAME_CODE 0x00ffffff - -/*****************************************************************************/ -#define VBI_CUST3_CFG3 0x46c -#define FLD_VBI3_HAM_EN 0x80000000 -#define FLD_VBI3_FIFO_MODE 0x70000000 -#define FLD_VBI3_FORMAT_TYPE 0x0f000000 -#define FLD_VBI3_PAYLD_LENGTH 0x00ff0000 -#define FLD_VBI3_CRI_LENGTH 0x0000f000 -#define FLD_VBI3_CRI_MARGIN 0x00000f00 -#define FLD_VBI3_CRI_TIME 0x000000ff - -/*****************************************************************************/ -#define HORIZ_TIM_CTRL 0x470 -#define FLD_BGDEL_CNT 0xff000000 -/* Reserved [23:22] */ -#define FLD_HACTIVE_CNT 0x003ff000 -/* Reserved [11:10] */ -#define FLD_HBLANK_CNT 0x000003ff - -/*****************************************************************************/ -#define VERT_TIM_CTRL 0x474 -#define FLD_V656BLANK_CNT 0xff000000 -/* Reserved [23:22] */ -#define FLD_VACTIVE_CNT 0x003ff000 -/* Reserved [11:10] */ -#define FLD_VBLANK_CNT 0x000003ff - -/*****************************************************************************/ -#define SRC_COMB_CFG 0x478 -#define FLD_CCOMB_2LN_CHECK 0x80000000 -#define FLD_CCOMB_3LN_EN 0x40000000 -#define FLD_CCOMB_2LN_EN 0x20000000 -#define FLD_CCOMB_3D_EN 0x10000000 -/* Reserved [27] */ -#define FLD_LCOMB_3LN_EN 0x04000000 -#define FLD_LCOMB_2LN_EN 0x02000000 -#define FLD_LCOMB_3D_EN 0x01000000 -#define FLD_LUMA_LPF_SEL 0x00c00000 -#define FLD_UV_LPF_SEL 0x00300000 -#define FLD_BLEND_SLOPE 0x000f0000 -#define FLD_CCOMB_REDUCE_EN 0x00008000 -/* Reserved [14:10] */ -#define FLD_SRC_DECIM_RATIO 0x000003ff - -/*****************************************************************************/ -#define CHROMA_VBIOFF_CFG 0x47c -#define FLD_VBI_VOFFSET 0x1f000000 -/* Reserved [23:20] */ -#define FLD_SC_STEP 0x000fffff - -/*****************************************************************************/ -#define FIELD_COUNT 0x480 -#define FLD_FIELD_COUNT_FLD 0x000003ff - -/*****************************************************************************/ -#define MISC_TIM_CTRL 0x484 -#define FLD_DEBOUNCE_COUNT 0xc0000000 -#define FLD_VT_LINE_CNT_HYST 0x30000000 -/* Reserved [27] */ -#define FLD_AFD_STAT 0x07ff0000 -#define FLD_VPRES_VERT_EN 0x00008000 -/* Reserved [14:12] */ -#define FLD_HR32 0x00000800 -#define FLD_TDALGN 0x00000400 -#define FLD_TDFIELD 0x00000200 -/* Reserved [8:6] */ -#define FLD_TEMPDEC 0x0000003f - -/*****************************************************************************/ -#define DFE_CTRL1 0x488 -#define FLD_CLAMP_AUTO_EN 0x80000000 -#define FLD_AGC_AUTO_EN 0x40000000 -#define FLD_VGA_CRUSH_EN 0x20000000 -#define FLD_VGA_AUTO_EN 0x10000000 -#define FLD_VBI_GATE_EN 0x08000000 -#define FLD_CLAMP_LEVEL 0x07000000 -/* Reserved [23:22] */ -#define FLD_CLAMP_SKIP_CNT 0x00300000 -#define FLD_AGC_GAIN 0x000fff00 -/* Reserved [7:6] */ -#define FLD_VGA_GAIN 0x0000003f - -/*****************************************************************************/ -#define DFE_CTRL2 0x48c -#define FLD_VGA_ACQUIRE_RANGE 0x00ff0000 -#define FLD_VGA_TRACK_RANGE 0x0000ff00 -#define FLD_VGA_SYNC 0x000000ff - -/*****************************************************************************/ -#define DFE_CTRL3 0x490 -#define FLD_BP_PERCENT 0xff000000 -#define FLD_DFT_THRESHOLD 0x00ff0000 -/* Reserved [15:12] */ -#define FLD_SYNC_WIDTH_SEL 0x00000600 -#define FLD_BP_LOOP_GAIN 0x00000300 -#define FLD_SYNC_LOOP_GAIN 0x000000c0 -/* Reserved [5:4] */ -#define FLD_AGC_LOOP_GAIN 0x0000000c -#define FLD_DCC_LOOP_GAIN 0x00000003 - -/*****************************************************************************/ -#define PLL_CTRL 0x494 -#define FLD_PLL_KD 0xff000000 -#define FLD_PLL_KI 0x00ff0000 -#define FLD_PLL_MAX_OFFSET 0x0000ffff - -/*****************************************************************************/ -#define HTL_CTRL 0x498 -/* Reserved [31:24] */ -#define FLD_AUTO_LOCK_SPD 0x00080000 -#define FLD_MAN_FAST_LOCK 0x00040000 -#define FLD_HTL_15K_EN 0x00020000 -#define FLD_HTL_500K_EN 0x00010000 -#define FLD_HTL_KD 0x0000ff00 -#define FLD_HTL_KI 0x000000ff - -/*****************************************************************************/ -#define COMB_CTRL 0x49c -#define FLD_COMB_PHASE_LIMIT 0xff000000 -#define FLD_CCOMB_ERR_LIMIT 0x00ff0000 -#define FLD_LUMA_THRESHOLD 0x0000ff00 -#define FLD_LCOMB_ERR_LIMIT 0x000000ff - -/*****************************************************************************/ -#define CRUSH_CTRL 0x4a0 -#define FLD_WTW_EN 0x00400000 -#define FLD_CRUSH_FREQ 0x00200000 -#define FLD_MAJ_SEL_EN 0x00100000 -#define FLD_MAJ_SEL 0x000c0000 -/* Reserved [17:15] */ -#define FLD_SYNC_TIP_REDUCE 0x00007e00 -/* Reserved [8:6] */ -#define FLD_SYNC_TIP_INC 0x0000003f - -/*****************************************************************************/ -#define SOFT_RST_CTRL 0x4a4 -#define FLD_VD_SOFT_RST 0x00008000 -/* Reserved [14:12] */ -#define FLD_REG_RST_MSK 0x00000800 -#define FLD_VOF_RST_MSK 0x00000400 -#define FLD_MVDET_RST_MSK 0x00000200 -#define FLD_VBI_RST_MSK 0x00000100 -#define FLD_SCALE_RST_MSK 0x00000080 -#define FLD_CHROMA_RST_MSK 0x00000040 -#define FLD_LUMA_RST_MSK 0x00000020 -#define FLD_VTG_RST_MSK 0x00000010 -#define FLD_YCSEP_RST_MSK 0x00000008 -#define FLD_SRC_RST_MSK 0x00000004 -#define FLD_DFE_RST_MSK 0x00000002 -/* Reserved [0] */ - -/*****************************************************************************/ -#define MV_DT_CTRL1 0x4a8 -/* Reserved [31:29] */ -#define FLD_PSP_STOP_LINE 0x1f000000 -/* Reserved [23:21] */ -#define FLD_PSP_STRT_LINE 0x001f0000 -/* Reserved [15] */ -#define FLD_PSP_LLIMW 0x00007f00 -/* Reserved [7] */ -#define FLD_PSP_ULIMW 0x0000007f - -/*****************************************************************************/ -#define MV_DT_CTRL2 0x4aC -#define FLD_CS_STOPWIN 0xff000000 -#define FLD_CS_STRTWIN 0x00ff0000 -#define FLD_CS_WIDTH 0x0000ff00 -#define FLD_PSP_SPEC_VAL 0x000000ff - -/*****************************************************************************/ -#define MV_DT_CTRL3 0x4B0 -#define FLD_AUTO_RATE_DIS 0x80000000 -#define FLD_HLOCK_DIS 0x40000000 -#define FLD_SEL_FIELD_CNT 0x20000000 -#define FLD_CS_TYPE2_SEL 0x10000000 -#define FLD_CS_LINE_THRSH_SEL 0x08000000 -#define FLD_CS_ATHRESH_SEL 0x04000000 -#define FLD_PSP_SPEC_SEL 0x02000000 -#define FLD_PSP_LINES_SEL 0x01000000 -#define FLD_FIELD_CNT 0x00f00000 -#define FLD_CS_TYPE2_CNT 0x000fc000 -#define FLD_CS_LINE_CNT 0x00003f00 -#define FLD_CS_ATHRESH_LEV 0x000000ff - -/*****************************************************************************/ -#define CHIP_VERSION 0x4b4 -/* Cx231xx redefine */ -#define VERSION 0x4b4 -#define FLD_REV_ID 0x000000ff - -/*****************************************************************************/ -#define MISC_DIAG_CTRL 0x4b8 -/* Reserved [31:24] */ -#define FLD_SC_CONVERGE_THRESH 0x00ff0000 -#define FLD_CCOMB_ERR_LIMIT_3D 0x0000ff00 -#define FLD_LCOMB_ERR_LIMIT_3D 0x000000ff - -/*****************************************************************************/ -#define VBI_PASS_CTRL 0x4bc -#define FLD_VBI_PASS_MD 0x00200000 -#define FLD_VBI_SETUP_DIS 0x00100000 -#define FLD_PASS_LINE_CTRL 0x000fffff - -/*****************************************************************************/ -/* Cx231xx redefine */ -#define VCR_DET_CTRL 0x4c0 -#define FLD_EN_FIELD_PHASE_DET 0x80000000 -#define FLD_EN_HEAD_SW_DET 0x40000000 -#define FLD_FIELD_PHASE_LENGTH 0x01ff0000 -/* Reserved [29:25] */ -#define FLD_FIELD_PHASE_DELAY 0x0000ff00 -#define FLD_FIELD_PHASE_LIMIT 0x000000f0 -#define FLD_HEAD_SW_DET_LIMIT 0x0000000f - -/*****************************************************************************/ -#define DL_CTL 0x800 -#define DL_CTL_ADDRESS_LOW 0x800 /* Byte 1 in DL_CTL */ -#define DL_CTL_ADDRESS_HIGH 0x801 /* Byte 2 in DL_CTL */ -#define DL_CTL_DATA 0x802 /* Byte 3 in DL_CTL */ -#define DL_CTL_CONTROL 0x803 /* Byte 4 in DL_CTL */ -/* Reserved [31:5] */ -#define FLD_START_8051 0x10000000 -#define FLD_DL_ENABLE 0x08000000 -#define FLD_DL_AUTO_INC 0x04000000 -#define FLD_DL_MAP 0x03000000 - -/*****************************************************************************/ -#define STD_DET_STATUS 0x804 -#define FLD_SPARE_STATUS1 0xff000000 -#define FLD_SPARE_STATUS0 0x00ff0000 -#define FLD_MOD_DET_STATUS1 0x0000ff00 -#define FLD_MOD_DET_STATUS0 0x000000ff - -/*****************************************************************************/ -#define AUD_BUILD_NUM 0x806 -#define AUD_VER_NUM 0x807 -#define STD_DET_CTL 0x808 -#define STD_DET_CTL_AUD_CTL 0x808 /* Byte 1 in STD_DET_CTL */ -#define STD_DET_CTL_PREF_MODE 0x809 /* Byte 2 in STD_DET_CTL */ -#define FLD_SPARE_CTL0 0xff000000 -#define FLD_DIS_DBX 0x00800000 -#define FLD_DIS_BTSC 0x00400000 -#define FLD_DIS_NICAM_A2 0x00200000 -#define FLD_VIDEO_PRESENT 0x00100000 -#define FLD_DW8051_VIDEO_FORMAT 0x000f0000 -#define FLD_PREF_DEC_MODE 0x0000ff00 -#define FLD_AUD_CONFIG 0x000000ff - -/*****************************************************************************/ -#define DW8051_INT 0x80c -#define FLD_VIDEO_PRESENT_CHANGE 0x80000000 -#define FLD_VIDEO_CHANGE 0x40000000 -#define FLD_RDS_READY 0x20000000 -#define FLD_AC97_INT 0x10000000 -#define FLD_NICAM_BIT_ERROR_TOO_HIGH 0x08000000 -#define FLD_NICAM_LOCK 0x04000000 -#define FLD_NICAM_UNLOCK 0x02000000 -#define FLD_DFT4_TH_CMP 0x01000000 -/* Reserved [23:22] */ -#define FLD_LOCK_IND_INT 0x00200000 -#define FLD_DFT3_TH_CMP 0x00100000 -#define FLD_DFT2_TH_CMP 0x00080000 -#define FLD_DFT1_TH_CMP 0x00040000 -#define FLD_FM2_DFT_TH_CMP 0x00020000 -#define FLD_FM1_DFT_TH_CMP 0x00010000 -#define FLD_VIDEO_PRESENT_EN 0x00008000 -#define FLD_VIDEO_CHANGE_EN 0x00004000 -#define FLD_RDS_READY_EN 0x00002000 -#define FLD_AC97_INT_EN 0x00001000 -#define FLD_NICAM_BIT_ERROR_TOO_HIGH_EN 0x00000800 -#define FLD_NICAM_LOCK_EN 0x00000400 -#define FLD_NICAM_UNLOCK_EN 0x00000200 -#define FLD_DFT4_TH_CMP_EN 0x00000100 -/* Reserved [7] */ -#define FLD_DW8051_INT6_CTL1 0x00000040 -#define FLD_DW8051_INT5_CTL1 0x00000020 -#define FLD_DW8051_INT4_CTL1 0x00000010 -#define FLD_DW8051_INT3_CTL1 0x00000008 -#define FLD_DW8051_INT2_CTL1 0x00000004 -#define FLD_DW8051_INT1_CTL1 0x00000002 -#define FLD_DW8051_INT0_CTL1 0x00000001 - -/*****************************************************************************/ -#define GENERAL_CTL 0x810 -#define FLD_RDS_INT 0x80000000 -#define FLD_NBER_INT 0x40000000 -#define FLD_NLL_INT 0x20000000 -#define FLD_IFL_INT 0x10000000 -#define FLD_FDL_INT 0x08000000 -#define FLD_AFC_INT 0x04000000 -#define FLD_AMC_INT 0x02000000 -#define FLD_AC97_INT_CTL 0x01000000 -#define FLD_RDS_INT_DIS 0x00800000 -#define FLD_NBER_INT_DIS 0x00400000 -#define FLD_NLL_INT_DIS 0x00200000 -#define FLD_IFL_INT_DIS 0x00100000 -#define FLD_FDL_INT_DIS 0x00080000 -#define FLD_FC_INT_DIS 0x00040000 -#define FLD_AMC_INT_DIS 0x00020000 -#define FLD_AC97_INT_DIS 0x00010000 -#define FLD_REV_NUM 0x0000ff00 -/* Reserved [7:5] */ -#define FLD_DBX_SOFT_RESET_REG 0x00000010 -#define FLD_AD_SOFT_RESET_REG 0x00000008 -#define FLD_SRC_SOFT_RESET_REG 0x00000004 -#define FLD_CDMOD_SOFT_RESET 0x00000002 -#define FLD_8051_SOFT_RESET 0x00000001 - -/*****************************************************************************/ -#define AAGC_CTL 0x814 -#define FLD_AFE_12DB_EN 0x80000000 -#define FLD_AAGC_DEFAULT_EN 0x40000000 -#define FLD_AAGC_DEFAULT 0x3f000000 -/* Reserved [23] */ -#define FLD_AAGC_GAIN 0x00600000 -#define FLD_AAGC_TH 0x001f0000 -/* Reserved [15:14] */ -#define FLD_AAGC_HYST2 0x00003f00 -/* Reserved [7:6] */ -#define FLD_AAGC_HYST1 0x0000003f - -/*****************************************************************************/ -#define IF_SRC_CTL 0x818 -#define FLD_DBX_BYPASS 0x80000000 -/* Reserved [30:25] */ -#define FLD_IF_SRC_MODE 0x01000000 -/* Reserved [23:18] */ -#define FLD_IF_SRC_PHASE_INC 0x0001ffff - -/*****************************************************************************/ -#define ANALOG_DEMOD_CTL 0x81c -#define FLD_ROT1_PHACC_PROG 0xffff0000 -/* Reserved [15] */ -#define FLD_FM1_DELAY_FIX 0x00007000 -#define FLD_PDF4_SHIFT 0x00000c00 -#define FLD_PDF3_SHIFT 0x00000300 -#define FLD_PDF2_SHIFT 0x000000c0 -#define FLD_PDF1_SHIFT 0x00000030 -#define FLD_FMBYPASS_MODE2 0x00000008 -#define FLD_FMBYPASS_MODE1 0x00000004 -#define FLD_NICAM_MODE 0x00000002 -#define FLD_BTSC_FMRADIO_MODE 0x00000001 - -/*****************************************************************************/ -#define ROT_FREQ_CTL 0x820 -#define FLD_ROT3_PHACC_PROG 0xffff0000 -#define FLD_ROT2_PHACC_PROG 0x0000ffff - -/*****************************************************************************/ -#define FM_CTL 0x824 -#define FLD_FM2_DC_FB_SHIFT 0xf0000000 -#define FLD_FM2_DC_INT_SHIFT 0x0f000000 -#define FLD_FM2_AFC_RESET 0x00800000 -#define FLD_FM2_DC_PASS_IN 0x00400000 -#define FLD_FM2_DAGC_SHIFT 0x00380000 -#define FLD_FM2_CORDIC_SHIFT 0x00070000 -#define FLD_FM1_DC_FB_SHIFT 0x0000f000 -#define FLD_FM1_DC_INT_SHIFT 0x00000f00 -#define FLD_FM1_AFC_RESET 0x00000080 -#define FLD_FM1_DC_PASS_IN 0x00000040 -#define FLD_FM1_DAGC_SHIFT 0x00000038 -#define FLD_FM1_CORDIC_SHIFT 0x00000007 - -/*****************************************************************************/ -#define LPF_PDF_CTL 0x828 -/* Reserved [31:30] */ -#define FLD_LPF32_SHIFT1 0x30000000 -#define FLD_LPF32_SHIFT2 0x0c000000 -#define FLD_LPF160_SHIFTA 0x03000000 -#define FLD_LPF160_SHIFTB 0x00c00000 -#define FLD_LPF160_SHIFTC 0x00300000 -#define FLD_LPF32_COEF_SEL2 0x000c0000 -#define FLD_LPF32_COEF_SEL1 0x00030000 -#define FLD_LPF160_COEF_SELC 0x0000c000 -#define FLD_LPF160_COEF_SELB 0x00003000 -#define FLD_LPF160_COEF_SELA 0x00000c00 -#define FLD_LPF160_IN_EN_REG 0x00000300 -#define FLD_PDF4_PDF_SEL 0x000000c0 -#define FLD_PDF3_PDF_SEL 0x00000030 -#define FLD_PDF2_PDF_SEL 0x0000000c -#define FLD_PDF1_PDF_SEL 0x00000003 - -/*****************************************************************************/ -#define DFT1_CTL1 0x82c -#define FLD_DFT1_DWELL 0xffff0000 -#define FLD_DFT1_FREQ 0x0000ffff - -/*****************************************************************************/ -#define DFT1_CTL2 0x830 -#define FLD_DFT1_THRESHOLD 0xffffff00 -#define FLD_DFT1_CMP_CTL 0x00000080 -#define FLD_DFT1_AVG 0x00000070 -/* Reserved [3:1] */ -#define FLD_DFT1_START 0x00000001 - -/*****************************************************************************/ -#define DFT1_STATUS 0x834 -#define FLD_DFT1_DONE 0x80000000 -#define FLD_DFT1_TH_CMP_STAT 0x40000000 -#define FLD_DFT1_RESULT 0x3fffffff - -/*****************************************************************************/ -#define DFT2_CTL1 0x838 -#define FLD_DFT2_DWELL 0xffff0000 -#define FLD_DFT2_FREQ 0x0000ffff - -/*****************************************************************************/ -#define DFT2_CTL2 0x83C -#define FLD_DFT2_THRESHOLD 0xffffff00 -#define FLD_DFT2_CMP_CTL 0x00000080 -#define FLD_DFT2_AVG 0x00000070 -/* Reserved [3:1] */ -#define FLD_DFT2_START 0x00000001 - -/*****************************************************************************/ -#define DFT2_STATUS 0x840 -#define FLD_DFT2_DONE 0x80000000 -#define FLD_DFT2_TH_CMP_STAT 0x40000000 -#define FLD_DFT2_RESULT 0x3fffffff - -/*****************************************************************************/ -#define DFT3_CTL1 0x844 -#define FLD_DFT3_DWELL 0xffff0000 -#define FLD_DFT3_FREQ 0x0000ffff - -/*****************************************************************************/ -#define DFT3_CTL2 0x848 -#define FLD_DFT3_THRESHOLD 0xffffff00 -#define FLD_DFT3_CMP_CTL 0x00000080 -#define FLD_DFT3_AVG 0x00000070 -/* Reserved [3:1] */ -#define FLD_DFT3_START 0x00000001 - -/*****************************************************************************/ -#define DFT3_STATUS 0x84c -#define FLD_DFT3_DONE 0x80000000 -#define FLD_DFT3_TH_CMP_STAT 0x40000000 -#define FLD_DFT3_RESULT 0x3fffffff - -/*****************************************************************************/ -#define DFT4_CTL1 0x850 -#define FLD_DFT4_DWELL 0xffff0000 -#define FLD_DFT4_FREQ 0x0000ffff - -/*****************************************************************************/ -#define DFT4_CTL2 0x854 -#define FLD_DFT4_THRESHOLD 0xffffff00 -#define FLD_DFT4_CMP_CTL 0x00000080 -#define FLD_DFT4_AVG 0x00000070 -/* Reserved [3:1] */ -#define FLD_DFT4_START 0x00000001 - -/*****************************************************************************/ -#define DFT4_STATUS 0x858 -#define FLD_DFT4_DONE 0x80000000 -#define FLD_DFT4_TH_CMP_STAT 0x40000000 -#define FLD_DFT4_RESULT 0x3fffffff - -/*****************************************************************************/ -#define AM_MTS_DET 0x85c -#define FLD_AM_MTS_MODE 0x80000000 -/* Reserved [30:26] */ -#define FLD_AM_SUB 0x02000000 -#define FLD_AM_GAIN_EN 0x01000000 -/* Reserved [23:16] */ -#define FLD_AMMTS_GAIN_SCALE 0x0000e000 -#define FLD_MTS_PDF_SHIFT 0x00001800 -#define FLD_AM_REG_GAIN 0x00000700 -#define FLD_AGC_REF 0x000000ff - -/*****************************************************************************/ -#define ANALOG_MUX_CTL 0x860 -/* Reserved [31:29] */ -#define FLD_MUX21_SEL 0x10000000 -#define FLD_MUX20_SEL 0x08000000 -#define FLD_MUX19_SEL 0x04000000 -#define FLD_MUX18_SEL 0x02000000 -#define FLD_MUX17_SEL 0x01000000 -#define FLD_MUX16_SEL 0x00800000 -#define FLD_MUX15_SEL 0x00400000 -#define FLD_MUX14_SEL 0x00300000 -#define FLD_MUX13_SEL 0x000C0000 -#define FLD_MUX12_SEL 0x00020000 -#define FLD_MUX11_SEL 0x00018000 -#define FLD_MUX10_SEL 0x00004000 -#define FLD_MUX9_SEL 0x00002000 -#define FLD_MUX8_SEL 0x00001000 -#define FLD_MUX7_SEL 0x00000800 -#define FLD_MUX6_SEL 0x00000600 -#define FLD_MUX5_SEL 0x00000100 -#define FLD_MUX4_SEL 0x000000c0 -#define FLD_MUX3_SEL 0x00000030 -#define FLD_MUX2_SEL 0x0000000c -#define FLD_MUX1_SEL 0x00000003 - -/*****************************************************************************/ -/* Cx231xx redefine */ -#define DPLL_CTRL1 0x864 -#define DIG_PLL_CTL1 0x864 - -#define FLD_PLL_STATUS 0x07000000 -#define FLD_BANDWIDTH_SELECT 0x00030000 -#define FLD_PLL_SHIFT_REG 0x00007000 -#define FLD_PHASE_SHIFT 0x000007ff - -/*****************************************************************************/ -/* Cx231xx redefine */ -#define DPLL_CTRL2 0x868 -#define DIG_PLL_CTL2 0x868 -#define FLD_PLL_UNLOCK_THR 0xff000000 -#define FLD_PLL_LOCK_THR 0x00ff0000 -/* Reserved [15:8] */ -#define FLD_AM_PDF_SEL2 0x000000c0 -#define FLD_AM_PDF_SEL1 0x00000030 -#define FLD_DPLL_FSM_CTRL 0x0000000c -/* Reserved [1] */ -#define FLD_PLL_PILOT_DET 0x00000001 - -/*****************************************************************************/ -/* Cx231xx redefine */ -#define DPLL_CTRL3 0x86c -#define DIG_PLL_CTL3 0x86c -#define FLD_DISABLE_LOOP 0x01000000 -#define FLD_A1_DS1_SEL 0x000c0000 -#define FLD_A1_DS2_SEL 0x00030000 -#define FLD_A1_KI 0x0000ff00 -#define FLD_A1_KD 0x000000ff - -/*****************************************************************************/ -/* Cx231xx redefine */ -#define DPLL_CTRL4 0x870 -#define DIG_PLL_CTL4 0x870 -#define FLD_A2_DS1_SEL 0x000c0000 -#define FLD_A2_DS2_SEL 0x00030000 -#define FLD_A2_KI 0x0000ff00 -#define FLD_A2_KD 0x000000ff - -/*****************************************************************************/ -/* Cx231xx redefine */ -#define DPLL_CTRL5 0x874 -#define DIG_PLL_CTL5 0x874 -#define FLD_TRK_DS1_SEL 0x000c0000 -#define FLD_TRK_DS2_SEL 0x00030000 -#define FLD_TRK_KI 0x0000ff00 -#define FLD_TRK_KD 0x000000ff - -/*****************************************************************************/ -#define DEEMPH_GAIN_CTL 0x878 -#define FLD_DEEMPH2_GAIN 0xFFFF0000 -#define FLD_DEEMPH1_GAIN 0x0000FFFF - -/*****************************************************************************/ -/* Cx231xx redefine */ -#define DEEMPH_COEFF1 0x87c -#define DEEMPH_COEF1 0x87c -#define FLD_DEEMPH_B0 0xffff0000 -#define FLD_DEEMPH_A0 0x0000ffff - -/*****************************************************************************/ -/* Cx231xx redefine */ -#define DEEMPH_COEFF2 0x880 -#define DEEMPH_COEF2 0x880 -#define FLD_DEEMPH_B1 0xFFFF0000 -#define FLD_DEEMPH_A1 0x0000FFFF - -/*****************************************************************************/ -#define DBX1_CTL1 0x884 -#define FLD_DBX1_WBE_GAIN 0xffff0000 -#define FLD_DBX1_IN_GAIN 0x0000ffff - -/*****************************************************************************/ -#define DBX1_CTL2 0x888 -#define FLD_DBX1_SE_BYPASS 0xffff0000 -#define FLD_DBX1_SE_GAIN 0x0000ffff - -/*****************************************************************************/ -#define DBX1_RMS_SE 0x88C -#define FLD_DBX1_RMS_WBE 0xffff0000 -#define FLD_DBX1_RMS_SE_FLD 0x0000ffff - -/*****************************************************************************/ -#define DBX2_CTL1 0x890 -#define FLD_DBX2_WBE_GAIN 0xffff0000 -#define FLD_DBX2_IN_GAIN 0x0000ffff - -/*****************************************************************************/ -#define DBX2_CTL2 0x894 -#define FLD_DBX2_SE_BYPASS 0xffff0000 -#define FLD_DBX2_SE_GAIN 0x0000ffff - -/*****************************************************************************/ -#define DBX2_RMS_SE 0x898 -#define FLD_DBX2_RMS_WBE 0xffff0000 -#define FLD_DBX2_RMS_SE_FLD 0x0000ffff - -/*****************************************************************************/ -#define AM_FM_DIFF 0x89c -/* Reserved [31] */ -#define FLD_FM_DIFF_OUT 0x7fff0000 -/* Reserved [15] */ -#define FLD_AM_DIFF_OUT 0x00007fff - -/*****************************************************************************/ -#define NICAM_FAW 0x8a0 -#define FLD_FAWDETWINEND 0xFc000000 -#define FLD_FAWDETWINSTR 0x03ff0000 -/* Reserved [15:12] */ -#define FLD_FAWDETTHRSHLD3 0x00000f00 -#define FLD_FAWDETTHRSHLD2 0x000000f0 -#define FLD_FAWDETTHRSHLD1 0x0000000f - -/*****************************************************************************/ -/* Cx231xx redefine */ -#define DEEMPH_GAIN 0x8a4 -#define NICAM_DEEMPHGAIN 0x8a4 -/* Reserved [31:18] */ -#define FLD_DEEMPHGAIN 0x0003ffff - -/*****************************************************************************/ -/* Cx231xx redefine */ -#define DEEMPH_NUMER1 0x8a8 -#define NICAM_DEEMPHNUMER1 0x8a8 -/* Reserved [31:18] */ -#define FLD_DEEMPHNUMER1 0x0003ffff - -/*****************************************************************************/ -/* Cx231xx redefine */ -#define DEEMPH_NUMER2 0x8ac -#define NICAM_DEEMPHNUMER2 0x8ac -/* Reserved [31:18] */ -#define FLD_DEEMPHNUMER2 0x0003ffff - -/*****************************************************************************/ -/* Cx231xx redefine */ -#define DEEMPH_DENOM1 0x8b0 -#define NICAM_DEEMPHDENOM1 0x8b0 -/* Reserved [31:18] */ -#define FLD_DEEMPHDENOM1 0x0003ffff - -/*****************************************************************************/ -/* Cx231xx redefine */ -#define DEEMPH_DENOM2 0x8b4 -#define NICAM_DEEMPHDENOM2 0x8b4 -/* Reserved [31:18] */ -#define FLD_DEEMPHDENOM2 0x0003ffff - -/*****************************************************************************/ -#define NICAM_ERRLOG_CTL1 0x8B8 -/* Reserved [31:28] */ -#define FLD_ERRINTRPTTHSHLD1 0x0fff0000 -/* Reserved [15:12] */ -#define FLD_ERRLOGPERIOD 0x00000fff - -/*****************************************************************************/ -#define NICAM_ERRLOG_CTL2 0x8bc -/* Reserved [31:28] */ -#define FLD_ERRINTRPTTHSHLD3 0x0fff0000 -/* Reserved [15:12] */ -#define FLD_ERRINTRPTTHSHLD2 0x00000fff - -/*****************************************************************************/ -#define NICAM_ERRLOG_STS1 0x8c0 -/* Reserved [31:28] */ -#define FLD_ERRLOG2 0x0fff0000 -/* Reserved [15:12] */ -#define FLD_ERRLOG1 0x00000fff - -/*****************************************************************************/ -#define NICAM_ERRLOG_STS2 0x8c4 -/* Reserved [31:12] */ -#define FLD_ERRLOG3 0x00000fff - -/*****************************************************************************/ -#define NICAM_STATUS 0x8c8 -/* Reserved [31:20] */ -#define FLD_NICAM_CIB 0x000c0000 -#define FLD_NICAM_LOCK_STAT 0x00020000 -#define FLD_NICAM_MUTE 0x00010000 -#define FLD_NICAMADDIT_DATA 0x0000ffe0 -#define FLD_NICAMCNTRL 0x0000001f - -/*****************************************************************************/ -#define DEMATRIX_CTL 0x8cc -#define FLD_AC97_IN_SHIFT 0xf0000000 -#define FLD_I2S_IN_SHIFT 0x0f000000 -#define FLD_DEMATRIX_SEL_CTL 0x00ff0000 -/* Reserved [15:11] */ -#define FLD_DMTRX_BYPASS 0x00000400 -#define FLD_DEMATRIX_MODE 0x00000300 -/* Reserved [7:6] */ -#define FLD_PH_DBX_SEL 0x00000020 -#define FLD_PH_CH_SEL 0x00000010 -#define FLD_PHASE_FIX 0x0000000f - -/*****************************************************************************/ -#define PATH1_CTL1 0x8d0 -/* Reserved [31:29] */ -#define FLD_PATH1_MUTE_CTL 0x1f000000 -/* Reserved [23:22] */ -#define FLD_PATH1_AVC_CG 0x00300000 -#define FLD_PATH1_AVC_RT 0x000f0000 -#define FLD_PATH1_AVC_AT 0x0000f000 -#define FLD_PATH1_AVC_STEREO 0x00000800 -#define FLD_PATH1_AVC_CR 0x00000700 -#define FLD_PATH1_AVC_RMS_CON 0x000000f0 -#define FLD_PATH1_SEL_CTL 0x0000000f - -/*****************************************************************************/ -#define PATH1_VOL_CTL 0x8d4 -#define FLD_PATH1_AVC_THRESHOLD 0x7fff0000 -#define FLD_PATH1_BAL_LEFT 0x00008000 -#define FLD_PATH1_BAL_LEVEL 0x00007f00 -#define FLD_PATH1_VOLUME 0x000000ff - -/*****************************************************************************/ -#define PATH1_EQ_CTL 0x8d8 -/* Reserved [31:30] */ -#define FLD_PATH1_EQ_TREBLE_VOL 0x3f000000 -/* Reserved [23:22] */ -#define FLD_PATH1_EQ_MID_VOL 0x003f0000 -/* Reserved [15:14] */ -#define FLD_PATH1_EQ_BASS_VOL 0x00003f00 -/* Reserved [7:1] */ -#define FLD_PATH1_EQ_BAND_SEL 0x00000001 - -/*****************************************************************************/ -#define PATH1_SC_CTL 0x8dc -#define FLD_PATH1_SC_THRESHOLD 0x7fff0000 -#define FLD_PATH1_SC_RT 0x0000f000 -#define FLD_PATH1_SC_AT 0x00000f00 -#define FLD_PATH1_SC_STEREO 0x00000080 -#define FLD_PATH1_SC_CR 0x00000070 -#define FLD_PATH1_SC_RMS_CON 0x0000000f - -/*****************************************************************************/ -#define PATH2_CTL1 0x8e0 -/* Reserved [31:26] */ -#define FLD_PATH2_MUTE_CTL 0x03000000 -/* Reserved [23:22] */ -#define FLD_PATH2_AVC_CG 0x00300000 -#define FLD_PATH2_AVC_RT 0x000f0000 -#define FLD_PATH2_AVC_AT 0x0000f000 -#define FLD_PATH2_AVC_STEREO 0x00000800 -#define FLD_PATH2_AVC_CR 0x00000700 -#define FLD_PATH2_AVC_RMS_CON 0x000000f0 -#define FLD_PATH2_SEL_CTL 0x0000000f - -/*****************************************************************************/ -#define PATH2_VOL_CTL 0x8e4 -#define FLD_PATH2_AVC_THRESHOLD 0xffff0000 -#define FLD_PATH2_BAL_LEFT 0x00008000 -#define FLD_PATH2_BAL_LEVEL 0x00007f00 -#define FLD_PATH2_VOLUME 0x000000ff - -/*****************************************************************************/ -#define PATH2_EQ_CTL 0x8e8 -/* Reserved [31:30] */ -#define FLD_PATH2_EQ_TREBLE_VOL 0x3f000000 -/* Reserved [23:22] */ -#define FLD_PATH2_EQ_MID_VOL 0x003f0000 -/* Reserved [15:14] */ -#define FLD_PATH2_EQ_BASS_VOL 0x00003f00 -/* Reserved [7:1] */ -#define FLD_PATH2_EQ_BAND_SEL 0x00000001 - -/*****************************************************************************/ -#define PATH2_SC_CTL 0x8eC -#define FLD_PATH2_SC_THRESHOLD 0xffff0000 -#define FLD_PATH2_SC_RT 0x0000f000 -#define FLD_PATH2_SC_AT 0x00000f00 -#define FLD_PATH2_SC_STEREO 0x00000080 -#define FLD_PATH2_SC_CR 0x00000070 -#define FLD_PATH2_SC_RMS_CON 0x0000000f - -/*****************************************************************************/ -#define SRC_CTL 0x8f0 -#define FLD_SRC_STATUS 0xffffff00 -#define FLD_FIFO_LF_EN 0x000000fc -#define FLD_BYPASS_LI 0x00000002 -#define FLD_BYPASS_PF 0x00000001 - -/*****************************************************************************/ -#define SRC_LF_COEF 0x8f4 -#define FLD_LOOP_FILTER_COEF2 0xffff0000 -#define FLD_LOOP_FILTER_COEF1 0x0000ffff - -/*****************************************************************************/ -#define SRC1_CTL 0x8f8 -/* Reserved [31:28] */ -#define FLD_SRC1_FIFO_RD_TH 0x0f000000 -/* Reserved [23:18] */ -#define FLD_SRC1_PHASE_INC 0x0003ffff - -/*****************************************************************************/ -#define SRC2_CTL 0x8fc -/* Reserved [31:28] */ -#define FLD_SRC2_FIFO_RD_TH 0x0f000000 -/* Reserved [23:18] */ -#define FLD_SRC2_PHASE_INC 0x0003ffff - -/*****************************************************************************/ -#define SRC3_CTL 0x900 -/* Reserved [31:28] */ -#define FLD_SRC3_FIFO_RD_TH 0x0f000000 -/* Reserved [23:18] */ -#define FLD_SRC3_PHASE_INC 0x0003ffff - -/*****************************************************************************/ -#define SRC4_CTL 0x904 -/* Reserved [31:28] */ -#define FLD_SRC4_FIFO_RD_TH 0x0f000000 -/* Reserved [23:18] */ -#define FLD_SRC4_PHASE_INC 0x0003ffff - -/*****************************************************************************/ -#define SRC5_CTL 0x908 -/* Reserved [31:28] */ -#define FLD_SRC5_FIFO_RD_TH 0x0f000000 -/* Reserved [23:18] */ -#define FLD_SRC5_PHASE_INC 0x0003ffff - -/*****************************************************************************/ -#define SRC6_CTL 0x90c -/* Reserved [31:28] */ -#define FLD_SRC6_FIFO_RD_TH 0x0f000000 -/* Reserved [23:18] */ -#define FLD_SRC6_PHASE_INC 0x0003ffff - -/*****************************************************************************/ -#define BAND_OUT_SEL 0x910 -#define FLD_SRC6_IN_SEL 0xc0000000 -#define FLD_SRC6_CLK_SEL 0x30000000 -#define FLD_SRC5_IN_SEL 0x0c000000 -#define FLD_SRC5_CLK_SEL 0x03000000 -#define FLD_SRC4_IN_SEL 0x00c00000 -#define FLD_SRC4_CLK_SEL 0x00300000 -#define FLD_SRC3_IN_SEL 0x000c0000 -#define FLD_SRC3_CLK_SEL 0x00030000 -#define FLD_BASEBAND_BYPASS_CTL 0x0000ff00 -#define FLD_AC97_SRC_SEL 0x000000c0 -#define FLD_I2S_SRC_SEL 0x00000030 -#define FLD_PARALLEL2_SRC_SEL 0x0000000c -#define FLD_PARALLEL1_SRC_SEL 0x00000003 - -/*****************************************************************************/ -#define I2S_IN_CTL 0x914 -/* Reserved [31:11] */ -#define FLD_I2S_UP2X_BW20K 0x00000400 -#define FLD_I2S_UP2X_BYPASS 0x00000200 -#define FLD_I2S_IN_MASTER_MODE 0x00000100 -#define FLD_I2S_IN_SONY_MODE 0x00000080 -#define FLD_I2S_IN_RIGHT_JUST 0x00000040 -#define FLD_I2S_IN_WS_SEL 0x00000020 -#define FLD_I2S_IN_BCN_DEL 0x0000001f - -/*****************************************************************************/ -#define I2S_OUT_CTL 0x918 -/* Reserved [31:17] */ -#define FLD_I2S_OUT_SOFT_RESET_EN 0x00010000 -/* Reserved [15:9] */ -#define FLD_I2S_OUT_MASTER_MODE 0x00000100 -#define FLD_I2S_OUT_SONY_MODE 0x00000080 -#define FLD_I2S_OUT_RIGHT_JUST 0x00000040 -#define FLD_I2S_OUT_WS_SEL 0x00000020 -#define FLD_I2S_OUT_BCN_DEL 0x0000001f - -/*****************************************************************************/ -#define AC97_CTL 0x91c -/* Reserved [31:26] */ -#define FLD_AC97_UP2X_BW20K 0x02000000 -#define FLD_AC97_UP2X_BYPASS 0x01000000 -/* Reserved [23:17] */ -#define FLD_AC97_RST_ACL 0x00010000 -/* Reserved [15:9] */ -#define FLD_AC97_WAKE_UP_SYNC 0x00000100 -/* Reserved [7:1] */ -#define FLD_AC97_SHUTDOWN 0x00000001 - -/* Cx231xx redefine */ -#define QPSK_IAGC_CTL1 0x94c -#define QPSK_IAGC_CTL2 0x950 -#define QPSK_FEPR_FREQ 0x954 -#define QPSK_BTL_CTL1 0x958 -#define QPSK_BTL_CTL2 0x95c -#define QPSK_CTL_CTL1 0x960 -#define QPSK_CTL_CTL2 0x964 -#define QPSK_MF_FAGC_CTL 0x968 -#define QPSK_EQ_CTL 0x96c -#define QPSK_LOCK_CTL 0x970 - -/*****************************************************************************/ -#define FM1_DFT_CTL 0x9a8 -#define FLD_FM1_DFT_THRESHOLD 0xffff0000 -/* Reserved [15:8] */ -#define FLD_FM1_DFT_CMP_CTL 0x00000080 -#define FLD_FM1_DFT_AVG 0x00000070 -/* Reserved [3:1] */ -#define FLD_FM1_DFT_START 0x00000001 - -/*****************************************************************************/ -#define FM1_DFT_STATUS 0x9ac -#define FLD_FM1_DFT_DONE 0x80000000 -/* Reserved [30:19] */ -#define FLD_FM_DFT_TH_CMP 0x00040000 -#define FLD_FM1_DFT 0x0003ffff - -/*****************************************************************************/ -#define FM2_DFT_CTL 0x9b0 -#define FLD_FM2_DFT_THRESHOLD 0xffff0000 -/* Reserved [15:8] */ -#define FLD_FM2_DFT_CMP_CTL 0x00000080 -#define FLD_FM2_DFT_AVG 0x00000070 -/* Reserved [3:1] */ -#define FLD_FM2_DFT_START 0x00000001 - -/*****************************************************************************/ -#define FM2_DFT_STATUS 0x9b4 -#define FLD_FM2_DFT_DONE 0x80000000 -/* Reserved [30:19] */ -#define FLD_FM2_DFT_TH_CMP_STAT 0x00040000 -#define FLD_FM2_DFT 0x0003ffff - -/*****************************************************************************/ -/* Cx231xx redefine */ -#define AAGC_STATUS_REG 0x9b8 -#define AAGC_STATUS 0x9b8 -/* Reserved [31:27] */ -#define FLD_FM2_DAGC_OUT 0x07000000 -/* Reserved [23:19] */ -#define FLD_FM1_DAGC_OUT 0x00070000 -/* Reserved [15:6] */ -#define FLD_AFE_VGA_OUT 0x0000003f - -/*****************************************************************************/ -#define MTS_GAIN_STATUS 0x9bc -/* Reserved [31:14] */ -#define FLD_MTS_GAIN 0x00003fff - -#define RDS_OUT 0x9c0 -#define FLD_RDS_Q 0xffff0000 -#define FLD_RDS_I 0x0000ffff - -/*****************************************************************************/ -#define AUTOCONFIG_REG 0x9c4 -/* Reserved [31:4] */ -#define FLD_AUTOCONFIG_MODE 0x0000000f - -#define FM_AFC 0x9c8 -#define FLD_FM2_AFC 0xffff0000 -#define FLD_FM1_AFC 0x0000ffff - -/*****************************************************************************/ -/* Cx231xx redefine */ -#define NEW_SPARE 0x9cc -#define NEW_SPARE_REG 0x9cc - -/*****************************************************************************/ -#define DBX_ADJ 0x9d0 -/* Reserved [31:28] */ -#define FLD_DBX2_ADJ 0x0fff0000 -/* Reserved [15:12] */ -#define FLD_DBX1_ADJ 0x00000fff - -#define VID_FMT_AUTO 0 -#define VID_FMT_NTSC_M 1 -#define VID_FMT_NTSC_J 2 -#define VID_FMT_NTSC_443 3 -#define VID_FMT_PAL_BDGHI 4 -#define VID_FMT_PAL_M 5 -#define VID_FMT_PAL_N 6 -#define VID_FMT_PAL_NC 7 -#define VID_FMT_PAL_60 8 -#define VID_FMT_SECAM 12 -#define VID_FMT_SECAM_60 13 - -#define INPUT_MODE_CVBS_0 0 /* INPUT_MODE_VALUE(0) */ -#define INPUT_MODE_YC_1 1 /* INPUT_MODE_VALUE(1) */ -#define INPUT_MODE_YC2_2 2 /* INPUT_MODE_VALUE(2) */ -#define INPUT_MODE_YUV_3 3 /* INPUT_MODE_VALUE(3) */ - -#define LUMA_LPF_LOW_BANDPASS 0 /* 0.6Mhz LPF BW */ -#define LUMA_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz LPF BW */ -#define LUMA_LPF_HIGH_BANDPASS 2 /* 1.5Mhz LPF BW */ - -#define UV_LPF_LOW_BANDPASS 0 /* 0.6Mhz LPF BW */ -#define UV_LPF_MEDIUM_BANDPASS 1 /* 1.0Mhz LPF BW */ -#define UV_LPF_HIGH_BANDPASS 2 /* 1.5Mhz LPF BW */ - -#define TWO_TAP_FILT 0 -#define THREE_TAP_FILT 1 -#define FOUR_TAP_FILT 2 -#define FIVE_TAP_FILT 3 - -#define AUD_CHAN_SRC_PARALLEL 0 -#define AUD_CHAN_SRC_I2S_INPUT 1 -#define AUD_CHAN_SRC_FLATIRON 2 -#define AUD_CHAN_SRC_PARALLEL3 3 - -#define OUT_MODE_601 0 -#define OUT_MODE_656 1 -#define OUT_MODE_VIP11 2 -#define OUT_MODE_VIP20 3 - -#define PHASE_INC_49MHZ 0x0df22 -#define PHASE_INC_56MHZ 0x0fa5b -#define PHASE_INC_28MHZ 0x010000 - -#endif diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/video/cx231xx/cx231xx-vbi.c deleted file mode 100644 index ac7db52f404f..000000000000 --- a/drivers/media/video/cx231xx/cx231xx-vbi.c +++ /dev/null @@ -1,710 +0,0 @@ -/* - cx231xx_vbi.c - driver for Conexant Cx23100/101/102 USB video capture devices - - Copyright (C) 2008 <srinivasa.deevi at conexant dot com> - Based on cx88 driver - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/init.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/bitmap.h> -#include <linux/usb.h> -#include <linux/i2c.h> -#include <linux/mm.h> -#include <linux/mutex.h> -#include <linux/slab.h> - -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-chip-ident.h> -#include <media/msp3400.h> -#include <media/tuner.h> - -#include "cx231xx.h" -#include "cx231xx-vbi.h" - -static inline void print_err_status(struct cx231xx *dev, int packet, int status) -{ - char *errmsg = "Unknown"; - - switch (status) { - case -ENOENT: - errmsg = "unlinked synchronuously"; - break; - case -ECONNRESET: - errmsg = "unlinked asynchronuously"; - break; - case -ENOSR: - errmsg = "Buffer error (overrun)"; - break; - case -EPIPE: - errmsg = "Stalled (device not responding)"; - break; - case -EOVERFLOW: - errmsg = "Babble (bad cable?)"; - break; - case -EPROTO: - errmsg = "Bit-stuff error (bad cable?)"; - break; - case -EILSEQ: - errmsg = "CRC/Timeout (could be anything)"; - break; - case -ETIME: - errmsg = "Device does not respond"; - break; - } - if (packet < 0) { - cx231xx_err(DRIVER_NAME "URB status %d [%s].\n", status, - errmsg); - } else { - cx231xx_err(DRIVER_NAME "URB packet %d, status %d [%s].\n", - packet, status, errmsg); - } -} - -/* - * Controls the isoc copy of each urb packet - */ -static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb) -{ - struct cx231xx_dmaqueue *dma_q = urb->context; - int rc = 1; - unsigned char *p_buffer; - u32 bytes_parsed = 0, buffer_size = 0; - u8 sav_eav = 0; - - if (!dev) - return 0; - - if (dev->state & DEV_DISCONNECTED) - return 0; - - if (urb->status < 0) { - print_err_status(dev, -1, urb->status); - if (urb->status == -ENOENT) - return 0; - } - - /* get buffer pointer and length */ - p_buffer = urb->transfer_buffer; - buffer_size = urb->actual_length; - - if (buffer_size > 0) { - bytes_parsed = 0; - - if (dma_q->is_partial_line) { - /* Handle the case where we were working on a partial - line */ - sav_eav = dma_q->last_sav; - } else { - /* Check for a SAV/EAV overlapping the - buffer boundary */ - - sav_eav = cx231xx_find_boundary_SAV_EAV(p_buffer, - dma_q->partial_buf, - &bytes_parsed); - } - - sav_eav &= 0xF0; - /* Get the first line if we have some portion of an SAV/EAV from - the last buffer or a partial line */ - if (sav_eav) { - bytes_parsed += cx231xx_get_vbi_line(dev, dma_q, - sav_eav, /* SAV/EAV */ - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed); /* buffer size */ - } - - /* Now parse data that is completely in this buffer */ - dma_q->is_partial_line = 0; - - while (bytes_parsed < buffer_size) { - u32 bytes_used = 0; - - sav_eav = cx231xx_find_next_SAV_EAV( - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed, /* buffer size */ - &bytes_used); /* bytes used to get SAV/EAV */ - - bytes_parsed += bytes_used; - - sav_eav &= 0xF0; - if (sav_eav && (bytes_parsed < buffer_size)) { - bytes_parsed += cx231xx_get_vbi_line(dev, - dma_q, sav_eav, /* SAV/EAV */ - p_buffer+bytes_parsed, /* p_buffer */ - buffer_size-bytes_parsed);/*buf size*/ - } - } - - /* Save the last four bytes of the buffer so we can - check the buffer boundary condition next time */ - memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4); - bytes_parsed = 0; - } - - return rc; -} - -/* ------------------------------------------------------------------ - Vbi buf operations - ------------------------------------------------------------------*/ - -static int -vbi_buffer_setup(struct videobuf_queue *vq, unsigned int *count, - unsigned int *size) -{ - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; - u32 height = 0; - - height = ((dev->norm & V4L2_STD_625_50) ? - PAL_VBI_LINES : NTSC_VBI_LINES); - - *size = (dev->width * height * 2 * 2); - if (0 == *count) - *count = CX231XX_DEF_VBI_BUF; - - if (*count < CX231XX_MIN_BUF) - *count = CX231XX_MIN_BUF; - - return 0; -} - -/* This is called *without* dev->slock held; please keep it that way */ -static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) -{ - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; - unsigned long flags = 0; - if (in_interrupt()) - BUG(); - - /* We used to wait for the buffer to finish here, but this didn't work - because, as we were keeping the state as VIDEOBUF_QUEUED, - videobuf_queue_cancel marked it as finished for us. - (Also, it could wedge forever if the hardware was misconfigured.) - - This should be safe; by the time we get here, the buffer isn't - queued anymore. If we ever start marking the buffers as - VIDEOBUF_ACTIVE, it won't be, though. - */ - spin_lock_irqsave(&dev->vbi_mode.slock, flags); - if (dev->vbi_mode.bulk_ctl.buf == buf) - dev->vbi_mode.bulk_ctl.buf = NULL; - spin_unlock_irqrestore(&dev->vbi_mode.slock, flags); - - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int -vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx *dev = fh->dev; - int rc = 0, urb_init = 0; - u32 height = 0; - - height = ((dev->norm & V4L2_STD_625_50) ? - PAL_VBI_LINES : NTSC_VBI_LINES); - buf->vb.size = ((dev->width << 1) * height * 2); - - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - buf->vb.width = dev->width; - buf->vb.height = height; - buf->vb.field = field; - buf->vb.field = V4L2_FIELD_SEQ_TB; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(vq, &buf->vb, NULL); - if (rc < 0) - goto fail; - } - - if (!dev->vbi_mode.bulk_ctl.num_bufs) - urb_init = 1; - - if (urb_init) { - rc = cx231xx_init_vbi_isoc(dev, CX231XX_NUM_VBI_PACKETS, - CX231XX_NUM_VBI_BUFS, - dev->vbi_mode.alt_max_pkt_size[0], - cx231xx_isoc_vbi_copy); - if (rc < 0) - goto fail; - } - - buf->vb.state = VIDEOBUF_PREPARED; - return 0; - -fail: - free_buffer(vq, buf); - return rc; -} - -static void -vbi_buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; - struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq; - - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vidq->active); - -} - -static void vbi_buffer_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) -{ - struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - - - free_buffer(vq, buf); -} - -struct videobuf_queue_ops cx231xx_vbi_qops = { - .buf_setup = vbi_buffer_setup, - .buf_prepare = vbi_buffer_prepare, - .buf_queue = vbi_buffer_queue, - .buf_release = vbi_buffer_release, -}; - -/* ------------------------------------------------------------------ - URB control - ------------------------------------------------------------------*/ - -/* - * IRQ callback, called by URB callback - */ -static void cx231xx_irq_vbi_callback(struct urb *urb) -{ - struct cx231xx_dmaqueue *dma_q = urb->context; - struct cx231xx_video_mode *vmode = - container_of(dma_q, struct cx231xx_video_mode, vidq); - struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode); - - switch (urb->status) { - case 0: /* success */ - case -ETIMEDOUT: /* NAK */ - break; - case -ECONNRESET: /* kill */ - case -ENOENT: - case -ESHUTDOWN: - return; - default: /* error */ - cx231xx_err(DRIVER_NAME "urb completition error %d.\n", - urb->status); - break; - } - - /* Copy data from URB */ - spin_lock(&dev->vbi_mode.slock); - dev->vbi_mode.bulk_ctl.bulk_copy(dev, urb); - spin_unlock(&dev->vbi_mode.slock); - - /* Reset status */ - urb->status = 0; - - urb->status = usb_submit_urb(urb, GFP_ATOMIC); - if (urb->status) { - cx231xx_err(DRIVER_NAME "urb resubmit failed (error=%i)\n", - urb->status); - } -} - -/* - * Stop and Deallocate URBs - */ -void cx231xx_uninit_vbi_isoc(struct cx231xx *dev) -{ - struct urb *urb; - int i; - - cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_uninit_vbi_isoc\n"); - - dev->vbi_mode.bulk_ctl.nfields = -1; - for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) { - urb = dev->vbi_mode.bulk_ctl.urb[i]; - if (urb) { - if (!irqs_disabled()) - usb_kill_urb(urb); - else - usb_unlink_urb(urb); - - if (dev->vbi_mode.bulk_ctl.transfer_buffer[i]) { - - kfree(dev->vbi_mode.bulk_ctl. - transfer_buffer[i]); - dev->vbi_mode.bulk_ctl.transfer_buffer[i] = - NULL; - } - usb_free_urb(urb); - dev->vbi_mode.bulk_ctl.urb[i] = NULL; - } - dev->vbi_mode.bulk_ctl.transfer_buffer[i] = NULL; - } - - kfree(dev->vbi_mode.bulk_ctl.urb); - kfree(dev->vbi_mode.bulk_ctl.transfer_buffer); - - dev->vbi_mode.bulk_ctl.urb = NULL; - dev->vbi_mode.bulk_ctl.transfer_buffer = NULL; - dev->vbi_mode.bulk_ctl.num_bufs = 0; - - cx231xx_capture_start(dev, 0, Vbi); -} -EXPORT_SYMBOL_GPL(cx231xx_uninit_vbi_isoc); - -/* - * Allocate URBs and start IRQ - */ -int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, - int num_bufs, int max_pkt_size, - int (*bulk_copy) (struct cx231xx *dev, - struct urb *urb)) -{ - struct cx231xx_dmaqueue *dma_q = &dev->vbi_mode.vidq; - int i; - int sb_size, pipe; - struct urb *urb; - int rc; - - cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_prepare_isoc\n"); - - /* De-allocates all pending stuff */ - cx231xx_uninit_vbi_isoc(dev); - - /* clear if any halt */ - usb_clear_halt(dev->udev, - usb_rcvbulkpipe(dev->udev, - dev->vbi_mode.end_point_addr)); - - dev->vbi_mode.bulk_ctl.bulk_copy = bulk_copy; - dev->vbi_mode.bulk_ctl.num_bufs = num_bufs; - dma_q->pos = 0; - dma_q->is_partial_line = 0; - dma_q->last_sav = 0; - dma_q->current_field = -1; - dma_q->bytes_left_in_line = dev->width << 1; - dma_q->lines_per_field = ((dev->norm & V4L2_STD_625_50) ? - PAL_VBI_LINES : NTSC_VBI_LINES); - dma_q->lines_completed = 0; - for (i = 0; i < 8; i++) - dma_q->partial_buf[i] = 0; - - dev->vbi_mode.bulk_ctl.urb = kzalloc(sizeof(void *) * num_bufs, - GFP_KERNEL); - if (!dev->vbi_mode.bulk_ctl.urb) { - cx231xx_errdev("cannot alloc memory for usb buffers\n"); - return -ENOMEM; - } - - dev->vbi_mode.bulk_ctl.transfer_buffer = - kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); - if (!dev->vbi_mode.bulk_ctl.transfer_buffer) { - cx231xx_errdev("cannot allocate memory for usbtransfer\n"); - kfree(dev->vbi_mode.bulk_ctl.urb); - return -ENOMEM; - } - - dev->vbi_mode.bulk_ctl.max_pkt_size = max_pkt_size; - dev->vbi_mode.bulk_ctl.buf = NULL; - - sb_size = max_packets * dev->vbi_mode.bulk_ctl.max_pkt_size; - - /* allocate urbs and transfer buffers */ - for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) { - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - cx231xx_err(DRIVER_NAME - ": cannot alloc bulk_ctl.urb %i\n", i); - cx231xx_uninit_vbi_isoc(dev); - return -ENOMEM; - } - dev->vbi_mode.bulk_ctl.urb[i] = urb; - urb->transfer_flags = 0; - - dev->vbi_mode.bulk_ctl.transfer_buffer[i] = - kzalloc(sb_size, GFP_KERNEL); - if (!dev->vbi_mode.bulk_ctl.transfer_buffer[i]) { - cx231xx_err(DRIVER_NAME - ": unable to allocate %i bytes for transfer" - " buffer %i%s\n", sb_size, i, - in_interrupt() ? " while in int" : ""); - cx231xx_uninit_vbi_isoc(dev); - return -ENOMEM; - } - - pipe = usb_rcvbulkpipe(dev->udev, dev->vbi_mode.end_point_addr); - usb_fill_bulk_urb(urb, dev->udev, pipe, - dev->vbi_mode.bulk_ctl.transfer_buffer[i], - sb_size, cx231xx_irq_vbi_callback, dma_q); - } - - init_waitqueue_head(&dma_q->wq); - - /* submit urbs and enables IRQ */ - for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) { - rc = usb_submit_urb(dev->vbi_mode.bulk_ctl.urb[i], GFP_ATOMIC); - if (rc) { - cx231xx_err(DRIVER_NAME - ": submit of urb %i failed (error=%i)\n", i, - rc); - cx231xx_uninit_vbi_isoc(dev); - return rc; - } - } - - cx231xx_capture_start(dev, 1, Vbi); - - return 0; -} -EXPORT_SYMBOL_GPL(cx231xx_init_vbi_isoc); - -u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 sav_eav, u8 *p_buffer, u32 buffer_size) -{ - u32 bytes_copied = 0; - int current_field = -1; - - switch (sav_eav) { - - case SAV_VBI_FIELD1: - current_field = 1; - break; - - case SAV_VBI_FIELD2: - current_field = 2; - break; - default: - break; - } - - if (current_field < 0) - return bytes_copied; - - dma_q->last_sav = sav_eav; - - bytes_copied = - cx231xx_copy_vbi_line(dev, dma_q, p_buffer, buffer_size, - current_field); - - return bytes_copied; -} - -/* - * Announces that a buffer were filled and request the next - */ -static inline void vbi_buffer_filled(struct cx231xx *dev, - struct cx231xx_dmaqueue *dma_q, - struct cx231xx_buffer *buf) -{ - /* Advice that buffer was filled */ - /* cx231xx_info(DRIVER_NAME "[%p/%d] wakeup\n", buf, buf->vb.i); */ - - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - do_gettimeofday(&buf->vb.ts); - - dev->vbi_mode.bulk_ctl.buf = NULL; - - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); -} - -u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 *p_line, u32 length, int field_number) -{ - u32 bytes_to_copy; - struct cx231xx_buffer *buf; - u32 _line_size = dev->width * 2; - - if (dma_q->current_field == -1) { - /* Just starting up */ - cx231xx_reset_vbi_buffer(dev, dma_q); - } - - if (dma_q->current_field != field_number) - dma_q->lines_completed = 0; - - /* get the buffer pointer */ - buf = dev->vbi_mode.bulk_ctl.buf; - - /* Remember the field number for next time */ - dma_q->current_field = field_number; - - bytes_to_copy = dma_q->bytes_left_in_line; - if (bytes_to_copy > length) - bytes_to_copy = length; - - if (dma_q->lines_completed >= dma_q->lines_per_field) { - dma_q->bytes_left_in_line -= bytes_to_copy; - dma_q->is_partial_line = - (dma_q->bytes_left_in_line == 0) ? 0 : 1; - return 0; - } - - dma_q->is_partial_line = 1; - - /* If we don't have a buffer, just return the number of bytes we would - have copied if we had a buffer. */ - if (!buf) { - dma_q->bytes_left_in_line -= bytes_to_copy; - dma_q->is_partial_line = - (dma_q->bytes_left_in_line == 0) ? 0 : 1; - return bytes_to_copy; - } - - /* copy the data to video buffer */ - cx231xx_do_vbi_copy(dev, dma_q, p_line, bytes_to_copy); - - dma_q->pos += bytes_to_copy; - dma_q->bytes_left_in_line -= bytes_to_copy; - - if (dma_q->bytes_left_in_line == 0) { - - dma_q->bytes_left_in_line = _line_size; - dma_q->lines_completed++; - dma_q->is_partial_line = 0; - - if (cx231xx_is_vbi_buffer_done(dev, dma_q) && buf) { - - vbi_buffer_filled(dev, dma_q, buf); - - dma_q->pos = 0; - dma_q->lines_completed = 0; - cx231xx_reset_vbi_buffer(dev, dma_q); - } - } - - return bytes_to_copy; -} - -/* - * video-buf generic routine to get the next available buffer - */ -static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q, - struct cx231xx_buffer **buf) -{ - struct cx231xx_video_mode *vmode = - container_of(dma_q, struct cx231xx_video_mode, vidq); - struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode); - char *outp; - - if (list_empty(&dma_q->active)) { - cx231xx_err(DRIVER_NAME ": No active queue to serve\n"); - dev->vbi_mode.bulk_ctl.buf = NULL; - *buf = NULL; - return; - } - - /* Get the next buffer */ - *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue); - - /* Cleans up buffer - Useful for testing for frame/URB loss */ - outp = videobuf_to_vmalloc(&(*buf)->vb); - memset(outp, 0, (*buf)->vb.size); - - dev->vbi_mode.bulk_ctl.buf = *buf; - - return; -} - -void cx231xx_reset_vbi_buffer(struct cx231xx *dev, - struct cx231xx_dmaqueue *dma_q) -{ - struct cx231xx_buffer *buf; - - buf = dev->vbi_mode.bulk_ctl.buf; - - if (buf == NULL) { - /* first try to get the buffer */ - get_next_vbi_buf(dma_q, &buf); - - dma_q->pos = 0; - dma_q->current_field = -1; - } - - dma_q->bytes_left_in_line = dev->width << 1; - dma_q->lines_completed = 0; -} - -int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 *p_buffer, u32 bytes_to_copy) -{ - u8 *p_out_buffer = NULL; - u32 current_line_bytes_copied = 0; - struct cx231xx_buffer *buf; - u32 _line_size = dev->width << 1; - void *startwrite; - int offset, lencopy; - - buf = dev->vbi_mode.bulk_ctl.buf; - - if (buf == NULL) - return -EINVAL; - - p_out_buffer = videobuf_to_vmalloc(&buf->vb); - - if (dma_q->bytes_left_in_line != _line_size) { - current_line_bytes_copied = - _line_size - dma_q->bytes_left_in_line; - } - - offset = (dma_q->lines_completed * _line_size) + - current_line_bytes_copied; - - if (dma_q->current_field == 2) { - /* Populate the second half of the frame */ - offset += (dev->width * 2 * dma_q->lines_per_field); - } - - /* prepare destination address */ - startwrite = p_out_buffer + offset; - - lencopy = dma_q->bytes_left_in_line > bytes_to_copy ? - bytes_to_copy : dma_q->bytes_left_in_line; - - memcpy(startwrite, p_buffer, lencopy); - - return 0; -} - -u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev, - struct cx231xx_dmaqueue *dma_q) -{ - u32 height = 0; - - height = ((dev->norm & V4L2_STD_625_50) ? - PAL_VBI_LINES : NTSC_VBI_LINES); - if (dma_q->lines_completed == height && dma_q->current_field == 2) - return 1; - else - return 0; -} diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.h b/drivers/media/video/cx231xx/cx231xx-vbi.h deleted file mode 100644 index 16c7d20a22a4..000000000000 --- a/drivers/media/video/cx231xx/cx231xx-vbi.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - cx231xx_vbi.h - driver for Conexant Cx23100/101/102 USB video capture devices - - Copyright (C) 2008 <srinivasa.deevi at conexant dot com> - Based on cx88 driver - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _CX231XX_VBI_H -#define _CX231XX_VBI_H - -extern struct videobuf_queue_ops cx231xx_vbi_qops; - -#define NTSC_VBI_START_LINE 10 /* line 10 - 21 */ -#define NTSC_VBI_END_LINE 21 -#define NTSC_VBI_LINES (NTSC_VBI_END_LINE-NTSC_VBI_START_LINE+1) - -#define PAL_VBI_START_LINE 6 -#define PAL_VBI_END_LINE 23 -#define PAL_VBI_LINES (PAL_VBI_END_LINE-PAL_VBI_START_LINE+1) - -#define VBI_STRIDE 1440 -#define VBI_SAMPLES_PER_LINE 1440 - -#define CX231XX_NUM_VBI_PACKETS 4 -#define CX231XX_NUM_VBI_BUFS 5 - -/* stream functions */ -int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, - int num_bufs, int max_pkt_size, - int (*bulk_copy) (struct cx231xx *dev, - struct urb *urb)); - -void cx231xx_uninit_vbi_isoc(struct cx231xx *dev); - -/* vbi data copy functions */ -u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 sav_eav, u8 *p_buffer, u32 buffer_size); - -u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 *p_line, u32 length, int field_number); - -void cx231xx_reset_vbi_buffer(struct cx231xx *dev, - struct cx231xx_dmaqueue *dma_q); - -int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 *p_buffer, u32 bytes_to_copy); - -u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev, - struct cx231xx_dmaqueue *dma_q); - -#endif diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c deleted file mode 100644 index 790b28d7f764..000000000000 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ /dev/null @@ -1,2670 +0,0 @@ -/* - cx231xx-video.c - driver for Conexant Cx23100/101/102 - USB video capture devices - - Copyright (C) 2008 <srinivasa.deevi at conexant dot com> - Based on em28xx driver - Based on cx23885 driver - Based on cx88 driver - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/init.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/bitmap.h> -#include <linux/usb.h> -#include <linux/i2c.h> -#include <linux/mm.h> -#include <linux/mutex.h> -#include <linux/slab.h> - -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-chip-ident.h> -#include <media/msp3400.h> -#include <media/tuner.h> - -#include "dvb_frontend.h" - -#include "cx231xx.h" -#include "cx231xx-vbi.h" - -#define CX231XX_VERSION "0.0.2" - -#define DRIVER_AUTHOR "Srinivasa Deevi <srinivasa.deevi@conexant.com>" -#define DRIVER_DESC "Conexant cx231xx based USB video device driver" - -#define cx231xx_videodbg(fmt, arg...) do {\ - if (video_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __func__ , ##arg); } while (0) - -static unsigned int isoc_debug; -module_param(isoc_debug, int, 0644); -MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]"); - -#define cx231xx_isocdbg(fmt, arg...) \ -do {\ - if (isoc_debug) { \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __func__ , ##arg); \ - } \ - } while (0) - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -MODULE_VERSION(CX231XX_VERSION); - -static unsigned int card[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; -static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; -static unsigned int vbi_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; -static unsigned int radio_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET }; - -module_param_array(card, int, NULL, 0444); -module_param_array(video_nr, int, NULL, 0444); -module_param_array(vbi_nr, int, NULL, 0444); -module_param_array(radio_nr, int, NULL, 0444); - -MODULE_PARM_DESC(card, "card type"); -MODULE_PARM_DESC(video_nr, "video device numbers"); -MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); -MODULE_PARM_DESC(radio_nr, "radio device numbers"); - -static unsigned int video_debug; -module_param(video_debug, int, 0644); -MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); - -/* supported video standards */ -static struct cx231xx_fmt format[] = { - { - .name = "16bpp YUY2, 4:2:2, packed", - .fourcc = V4L2_PIX_FMT_YUYV, - .depth = 16, - .reg = 0, - }, -}; - -/* supported controls */ -/* Common to all boards */ - -/* ------------------------------------------------------------------- */ - -static const struct v4l2_queryctrl no_ctl = { - .name = "42", - .flags = V4L2_CTRL_FLAG_DISABLED, -}; - -static struct cx231xx_ctrl cx231xx_ctls[] = { - /* --- video --- */ - { - .v = { - .id = V4L2_CID_BRIGHTNESS, - .name = "Brightness", - .minimum = 0x00, - .maximum = 0xff, - .step = 1, - .default_value = 0x7f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 128, - .reg = LUMA_CTRL, - .mask = 0x00ff, - .shift = 0, - }, { - .v = { - .id = V4L2_CID_CONTRAST, - .name = "Contrast", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0x3f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 0, - .reg = LUMA_CTRL, - .mask = 0xff00, - .shift = 8, - }, { - .v = { - .id = V4L2_CID_HUE, - .name = "Hue", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0x7f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 128, - .reg = CHROMA_CTRL, - .mask = 0xff0000, - .shift = 16, - }, { - /* strictly, this only describes only U saturation. - * V saturation is handled specially through code. - */ - .v = { - .id = V4L2_CID_SATURATION, - .name = "Saturation", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0x7f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .off = 0, - .reg = CHROMA_CTRL, - .mask = 0x00ff, - .shift = 0, - }, { - /* --- audio --- */ - .v = { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, - .reg = PATH1_CTL1, - .mask = (0x1f << 24), - .shift = 24, - }, { - .v = { - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 0x3f, - .step = 1, - .default_value = 0x3f, - .type = V4L2_CTRL_TYPE_INTEGER, - }, - .reg = PATH1_VOL_CTL, - .mask = 0xff, - .shift = 0, - } -}; -static const int CX231XX_CTLS = ARRAY_SIZE(cx231xx_ctls); - -static const u32 cx231xx_user_ctrls[] = { - V4L2_CID_USER_CLASS, - V4L2_CID_BRIGHTNESS, - V4L2_CID_CONTRAST, - V4L2_CID_SATURATION, - V4L2_CID_HUE, - V4L2_CID_AUDIO_VOLUME, -#if 0 - V4L2_CID_AUDIO_BALANCE, -#endif - V4L2_CID_AUDIO_MUTE, - 0 -}; - -static const u32 *ctrl_classes[] = { - cx231xx_user_ctrls, - NULL -}; - -/* ------------------------------------------------------------------ - Video buffer and parser functions - ------------------------------------------------------------------*/ - -/* - * Announces that a buffer were filled and request the next - */ -static inline void buffer_filled(struct cx231xx *dev, - struct cx231xx_dmaqueue *dma_q, - struct cx231xx_buffer *buf) -{ - /* Advice that buffer was filled */ - cx231xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - do_gettimeofday(&buf->vb.ts); - - if (dev->USE_ISO) - dev->video_mode.isoc_ctl.buf = NULL; - else - dev->video_mode.bulk_ctl.buf = NULL; - - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); -} - -static inline void print_err_status(struct cx231xx *dev, int packet, int status) -{ - char *errmsg = "Unknown"; - - switch (status) { - case -ENOENT: - errmsg = "unlinked synchronuously"; - break; - case -ECONNRESET: - errmsg = "unlinked asynchronuously"; - break; - case -ENOSR: - errmsg = "Buffer error (overrun)"; - break; - case -EPIPE: - errmsg = "Stalled (device not responding)"; - break; - case -EOVERFLOW: - errmsg = "Babble (bad cable?)"; - break; - case -EPROTO: - errmsg = "Bit-stuff error (bad cable?)"; - break; - case -EILSEQ: - errmsg = "CRC/Timeout (could be anything)"; - break; - case -ETIME: - errmsg = "Device does not respond"; - break; - } - if (packet < 0) { - cx231xx_isocdbg("URB status %d [%s].\n", status, errmsg); - } else { - cx231xx_isocdbg("URB packet %d, status %d [%s].\n", - packet, status, errmsg); - } -} - -/* - * video-buf generic routine to get the next available buffer - */ -static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q, - struct cx231xx_buffer **buf) -{ - struct cx231xx_video_mode *vmode = - container_of(dma_q, struct cx231xx_video_mode, vidq); - struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode); - - char *outp; - - if (list_empty(&dma_q->active)) { - cx231xx_isocdbg("No active queue to serve\n"); - if (dev->USE_ISO) - dev->video_mode.isoc_ctl.buf = NULL; - else - dev->video_mode.bulk_ctl.buf = NULL; - *buf = NULL; - return; - } - - /* Get the next buffer */ - *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue); - - /* Cleans up buffer - Useful for testing for frame/URB loss */ - outp = videobuf_to_vmalloc(&(*buf)->vb); - memset(outp, 0, (*buf)->vb.size); - - if (dev->USE_ISO) - dev->video_mode.isoc_ctl.buf = *buf; - else - dev->video_mode.bulk_ctl.buf = *buf; - - return; -} - -/* - * Controls the isoc copy of each urb packet - */ -static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) -{ - struct cx231xx_dmaqueue *dma_q = urb->context; - int i, rc = 1; - unsigned char *p_buffer; - u32 bytes_parsed = 0, buffer_size = 0; - u8 sav_eav = 0; - - if (!dev) - return 0; - - if (dev->state & DEV_DISCONNECTED) - return 0; - - if (urb->status < 0) { - print_err_status(dev, -1, urb->status); - if (urb->status == -ENOENT) - return 0; - } - - for (i = 0; i < urb->number_of_packets; i++) { - int status = urb->iso_frame_desc[i].status; - - if (status < 0) { - print_err_status(dev, i, status); - if (urb->iso_frame_desc[i].status != -EPROTO) - continue; - } - - if (urb->iso_frame_desc[i].actual_length <= 0) { - /* cx231xx_isocdbg("packet %d is empty",i); - spammy */ - continue; - } - if (urb->iso_frame_desc[i].actual_length > - dev->video_mode.max_pkt_size) { - cx231xx_isocdbg("packet bigger than packet size"); - continue; - } - - /* get buffer pointer and length */ - p_buffer = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - buffer_size = urb->iso_frame_desc[i].actual_length; - bytes_parsed = 0; - - if (dma_q->is_partial_line) { - /* Handle the case of a partial line */ - sav_eav = dma_q->last_sav; - } else { - /* Check for a SAV/EAV overlapping - the buffer boundary */ - sav_eav = - cx231xx_find_boundary_SAV_EAV(p_buffer, - dma_q->partial_buf, - &bytes_parsed); - } - - sav_eav &= 0xF0; - /* Get the first line if we have some portion of an SAV/EAV from - the last buffer or a partial line */ - if (sav_eav) { - bytes_parsed += cx231xx_get_video_line(dev, dma_q, - sav_eav, /* SAV/EAV */ - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed);/* buf size */ - } - - /* Now parse data that is completely in this buffer */ - /* dma_q->is_partial_line = 0; */ - - while (bytes_parsed < buffer_size) { - u32 bytes_used = 0; - - sav_eav = cx231xx_find_next_SAV_EAV( - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed, /* buf size */ - &bytes_used);/* bytes used to get SAV/EAV */ - - bytes_parsed += bytes_used; - - sav_eav &= 0xF0; - if (sav_eav && (bytes_parsed < buffer_size)) { - bytes_parsed += cx231xx_get_video_line(dev, - dma_q, sav_eav, /* SAV/EAV */ - p_buffer + bytes_parsed,/* p_buffer */ - buffer_size - bytes_parsed);/*buf size*/ - } - } - - /* Save the last four bytes of the buffer so we can check the - buffer boundary condition next time */ - memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4); - bytes_parsed = 0; - - } - return rc; -} - -static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb) -{ - struct cx231xx_dmaqueue *dma_q = urb->context; - int rc = 1; - unsigned char *p_buffer; - u32 bytes_parsed = 0, buffer_size = 0; - u8 sav_eav = 0; - - if (!dev) - return 0; - - if (dev->state & DEV_DISCONNECTED) - return 0; - - if (urb->status < 0) { - print_err_status(dev, -1, urb->status); - if (urb->status == -ENOENT) - return 0; - } - - if (1) { - - /* get buffer pointer and length */ - p_buffer = urb->transfer_buffer; - buffer_size = urb->actual_length; - bytes_parsed = 0; - - if (dma_q->is_partial_line) { - /* Handle the case of a partial line */ - sav_eav = dma_q->last_sav; - } else { - /* Check for a SAV/EAV overlapping - the buffer boundary */ - sav_eav = - cx231xx_find_boundary_SAV_EAV(p_buffer, - dma_q->partial_buf, - &bytes_parsed); - } - - sav_eav &= 0xF0; - /* Get the first line if we have some portion of an SAV/EAV from - the last buffer or a partial line */ - if (sav_eav) { - bytes_parsed += cx231xx_get_video_line(dev, dma_q, - sav_eav, /* SAV/EAV */ - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed);/* buf size */ - } - - /* Now parse data that is completely in this buffer */ - /* dma_q->is_partial_line = 0; */ - - while (bytes_parsed < buffer_size) { - u32 bytes_used = 0; - - sav_eav = cx231xx_find_next_SAV_EAV( - p_buffer + bytes_parsed, /* p_buffer */ - buffer_size - bytes_parsed, /* buf size */ - &bytes_used);/* bytes used to get SAV/EAV */ - - bytes_parsed += bytes_used; - - sav_eav &= 0xF0; - if (sav_eav && (bytes_parsed < buffer_size)) { - bytes_parsed += cx231xx_get_video_line(dev, - dma_q, sav_eav, /* SAV/EAV */ - p_buffer + bytes_parsed,/* p_buffer */ - buffer_size - bytes_parsed);/*buf size*/ - } - } - - /* Save the last four bytes of the buffer so we can check the - buffer boundary condition next time */ - memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4); - bytes_parsed = 0; - - } - return rc; -} - - -u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf, - u32 *p_bytes_used) -{ - u32 bytes_used; - u8 boundary_bytes[8]; - u8 sav_eav = 0; - - *p_bytes_used = 0; - - /* Create an array of the last 4 bytes of the last buffer and the first - 4 bytes of the current buffer. */ - - memcpy(boundary_bytes, partial_buf, 4); - memcpy(boundary_bytes + 4, p_buffer, 4); - - /* Check for the SAV/EAV in the boundary buffer */ - sav_eav = cx231xx_find_next_SAV_EAV((u8 *)&boundary_bytes, 8, - &bytes_used); - - if (sav_eav) { - /* found a boundary SAV/EAV. Updates the bytes used to reflect - only those used in the new buffer */ - *p_bytes_used = bytes_used - 4; - } - - return sav_eav; -} - -u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size, u32 *p_bytes_used) -{ - u32 i; - u8 sav_eav = 0; - - /* - * Don't search if the buffer size is less than 4. It causes a page - * fault since buffer_size - 4 evaluates to a large number in that - * case. - */ - if (buffer_size < 4) { - *p_bytes_used = buffer_size; - return 0; - } - - for (i = 0; i < (buffer_size - 3); i++) { - - if ((p_buffer[i] == 0xFF) && - (p_buffer[i + 1] == 0x00) && (p_buffer[i + 2] == 0x00)) { - - *p_bytes_used = i + 4; - sav_eav = p_buffer[i + 3]; - return sav_eav; - } - } - - *p_bytes_used = buffer_size; - return 0; -} - -u32 cx231xx_get_video_line(struct cx231xx *dev, - struct cx231xx_dmaqueue *dma_q, u8 sav_eav, - u8 *p_buffer, u32 buffer_size) -{ - u32 bytes_copied = 0; - int current_field = -1; - - switch (sav_eav) { - case SAV_ACTIVE_VIDEO_FIELD1: - /* looking for skipped line which occurred in PAL 720x480 mode. - In this case, there will be no active data contained - between the SAV and EAV */ - if ((buffer_size > 3) && (p_buffer[0] == 0xFF) && - (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) && - ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) || - (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) || - (p_buffer[3] == EAV_VBLANK_FIELD1) || - (p_buffer[3] == EAV_VBLANK_FIELD2))) - return bytes_copied; - current_field = 1; - break; - - case SAV_ACTIVE_VIDEO_FIELD2: - /* looking for skipped line which occurred in PAL 720x480 mode. - In this case, there will be no active data contained between - the SAV and EAV */ - if ((buffer_size > 3) && (p_buffer[0] == 0xFF) && - (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) && - ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) || - (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) || - (p_buffer[3] == EAV_VBLANK_FIELD1) || - (p_buffer[3] == EAV_VBLANK_FIELD2))) - return bytes_copied; - current_field = 2; - break; - } - - dma_q->last_sav = sav_eav; - - bytes_copied = cx231xx_copy_video_line(dev, dma_q, p_buffer, - buffer_size, current_field); - - return bytes_copied; -} - -u32 cx231xx_copy_video_line(struct cx231xx *dev, - struct cx231xx_dmaqueue *dma_q, u8 *p_line, - u32 length, int field_number) -{ - u32 bytes_to_copy; - struct cx231xx_buffer *buf; - u32 _line_size = dev->width * 2; - - if (dma_q->current_field != field_number) - cx231xx_reset_video_buffer(dev, dma_q); - - /* get the buffer pointer */ - if (dev->USE_ISO) - buf = dev->video_mode.isoc_ctl.buf; - else - buf = dev->video_mode.bulk_ctl.buf; - - /* Remember the field number for next time */ - dma_q->current_field = field_number; - - bytes_to_copy = dma_q->bytes_left_in_line; - if (bytes_to_copy > length) - bytes_to_copy = length; - - if (dma_q->lines_completed >= dma_q->lines_per_field) { - dma_q->bytes_left_in_line -= bytes_to_copy; - dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ? - 0 : 1; - return 0; - } - - dma_q->is_partial_line = 1; - - /* If we don't have a buffer, just return the number of bytes we would - have copied if we had a buffer. */ - if (!buf) { - dma_q->bytes_left_in_line -= bytes_to_copy; - dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) - ? 0 : 1; - return bytes_to_copy; - } - - /* copy the data to video buffer */ - cx231xx_do_copy(dev, dma_q, p_line, bytes_to_copy); - - dma_q->pos += bytes_to_copy; - dma_q->bytes_left_in_line -= bytes_to_copy; - - if (dma_q->bytes_left_in_line == 0) { - dma_q->bytes_left_in_line = _line_size; - dma_q->lines_completed++; - dma_q->is_partial_line = 0; - - if (cx231xx_is_buffer_done(dev, dma_q) && buf) { - buffer_filled(dev, dma_q, buf); - - dma_q->pos = 0; - buf = NULL; - dma_q->lines_completed = 0; - } - } - - return bytes_to_copy; -} - -void cx231xx_reset_video_buffer(struct cx231xx *dev, - struct cx231xx_dmaqueue *dma_q) -{ - struct cx231xx_buffer *buf; - - /* handle the switch from field 1 to field 2 */ - if (dma_q->current_field == 1) { - if (dma_q->lines_completed >= dma_q->lines_per_field) - dma_q->field1_done = 1; - else - dma_q->field1_done = 0; - } - - if (dev->USE_ISO) - buf = dev->video_mode.isoc_ctl.buf; - else - buf = dev->video_mode.bulk_ctl.buf; - - if (buf == NULL) { - /* first try to get the buffer */ - get_next_buf(dma_q, &buf); - - dma_q->pos = 0; - dma_q->field1_done = 0; - dma_q->current_field = -1; - } - - /* reset the counters */ - dma_q->bytes_left_in_line = dev->width << 1; - dma_q->lines_completed = 0; -} - -int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 *p_buffer, u32 bytes_to_copy) -{ - u8 *p_out_buffer = NULL; - u32 current_line_bytes_copied = 0; - struct cx231xx_buffer *buf; - u32 _line_size = dev->width << 1; - void *startwrite; - int offset, lencopy; - - if (dev->USE_ISO) - buf = dev->video_mode.isoc_ctl.buf; - else - buf = dev->video_mode.bulk_ctl.buf; - - if (buf == NULL) - return -1; - - p_out_buffer = videobuf_to_vmalloc(&buf->vb); - - current_line_bytes_copied = _line_size - dma_q->bytes_left_in_line; - - /* Offset field 2 one line from the top of the buffer */ - offset = (dma_q->current_field == 1) ? 0 : _line_size; - - /* Offset for field 2 */ - startwrite = p_out_buffer + offset; - - /* lines already completed in the current field */ - startwrite += (dma_q->lines_completed * _line_size * 2); - - /* bytes already completed in the current line */ - startwrite += current_line_bytes_copied; - - lencopy = dma_q->bytes_left_in_line > bytes_to_copy ? - bytes_to_copy : dma_q->bytes_left_in_line; - - if ((u8 *)(startwrite + lencopy) > (u8 *)(p_out_buffer + buf->vb.size)) - return 0; - - /* The below copies the UYVY data straight into video buffer */ - cx231xx_swab((u16 *) p_buffer, (u16 *) startwrite, (u16) lencopy); - - return 0; -} - -void cx231xx_swab(u16 *from, u16 *to, u16 len) -{ - u16 i; - - if (len <= 0) - return; - - for (i = 0; i < len / 2; i++) - to[i] = (from[i] << 8) | (from[i] >> 8); -} - -u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q) -{ - u8 buffer_complete = 0; - - /* Dual field stream */ - buffer_complete = ((dma_q->current_field == 2) && - (dma_q->lines_completed >= dma_q->lines_per_field) && - dma_q->field1_done); - - return buffer_complete; -} - -/* ------------------------------------------------------------------ - Videobuf operations - ------------------------------------------------------------------*/ - -static int -buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) -{ - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; - - *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7)>>3; - if (0 == *count) - *count = CX231XX_DEF_BUF; - - if (*count < CX231XX_MIN_BUF) - *count = CX231XX_MIN_BUF; - - return 0; -} - -/* This is called *without* dev->slock held; please keep it that way */ -static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) -{ - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; - unsigned long flags = 0; - - if (in_interrupt()) - BUG(); - - /* We used to wait for the buffer to finish here, but this didn't work - because, as we were keeping the state as VIDEOBUF_QUEUED, - videobuf_queue_cancel marked it as finished for us. - (Also, it could wedge forever if the hardware was misconfigured.) - - This should be safe; by the time we get here, the buffer isn't - queued anymore. If we ever start marking the buffers as - VIDEOBUF_ACTIVE, it won't be, though. - */ - spin_lock_irqsave(&dev->video_mode.slock, flags); - if (dev->USE_ISO) { - if (dev->video_mode.isoc_ctl.buf == buf) - dev->video_mode.isoc_ctl.buf = NULL; - } else { - if (dev->video_mode.bulk_ctl.buf == buf) - dev->video_mode.bulk_ctl.buf = NULL; - } - spin_unlock_irqrestore(&dev->video_mode.slock, flags); - - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int -buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx *dev = fh->dev; - int rc = 0, urb_init = 0; - - /* The only currently supported format is 16 bits/pixel */ - buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth - + 7) >> 3; - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - buf->vb.width = dev->width; - buf->vb.height = dev->height; - buf->vb.field = field; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(vq, &buf->vb, NULL); - if (rc < 0) - goto fail; - } - - if (dev->USE_ISO) { - if (!dev->video_mode.isoc_ctl.num_bufs) - urb_init = 1; - } else { - if (!dev->video_mode.bulk_ctl.num_bufs) - urb_init = 1; - } - /*cx231xx_info("urb_init=%d dev->video_mode.max_pkt_size=%d\n", - urb_init, dev->video_mode.max_pkt_size);*/ - if (urb_init) { - dev->mode_tv = 0; - if (dev->USE_ISO) - rc = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS, - CX231XX_NUM_BUFS, - dev->video_mode.max_pkt_size, - cx231xx_isoc_copy); - else - rc = cx231xx_init_bulk(dev, CX231XX_NUM_PACKETS, - CX231XX_NUM_BUFS, - dev->video_mode.max_pkt_size, - cx231xx_bulk_copy); - if (rc < 0) - goto fail; - } - - buf->vb.state = VIDEOBUF_PREPARED; - return 0; - -fail: - free_buffer(vq, buf); - return rc; -} - -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = fh->dev; - struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq; - - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vidq->active); - -} - -static void buffer_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) -{ - struct cx231xx_buffer *buf = - container_of(vb, struct cx231xx_buffer, vb); - struct cx231xx_fh *fh = vq->priv_data; - struct cx231xx *dev = (struct cx231xx *)fh->dev; - - cx231xx_isocdbg("cx231xx: called buffer_release\n"); - - free_buffer(vq, buf); -} - -static struct videobuf_queue_ops cx231xx_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, -}; - -/********************* v4l2 interface **************************************/ - -void video_mux(struct cx231xx *dev, int index) -{ - dev->video_input = index; - dev->ctl_ainput = INPUT(index)->amux; - - cx231xx_set_video_input_mux(dev, index); - - cx25840_call(dev, video, s_routing, INPUT(index)->vmux, 0, 0); - - cx231xx_set_audio_input(dev, dev->ctl_ainput); - - cx231xx_info("video_mux : %d\n", index); - - /* do mode control overrides if required */ - cx231xx_do_mode_ctrl_overrides(dev); -} - -/* Usage lock check functions */ -static int res_get(struct cx231xx_fh *fh) -{ - struct cx231xx *dev = fh->dev; - int rc = 0; - - /* This instance already has stream_on */ - if (fh->stream_on) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (dev->stream_on) - return -EBUSY; - dev->stream_on = 1; - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - if (dev->vbi_stream_on) - return -EBUSY; - dev->vbi_stream_on = 1; - } else - return -EINVAL; - - fh->stream_on = 1; - - return rc; -} - -static int res_check(struct cx231xx_fh *fh) -{ - return fh->stream_on; -} - -static void res_free(struct cx231xx_fh *fh) -{ - struct cx231xx *dev = fh->dev; - - fh->stream_on = 0; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - dev->stream_on = 0; - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - dev->vbi_stream_on = 0; -} - -static int check_dev(struct cx231xx *dev) -{ - if (dev->state & DEV_DISCONNECTED) { - cx231xx_errdev("v4l2 ioctl: device not present\n"); - return -ENODEV; - } - return 0; -} - -/* ------------------------------------------------------------------ - IOCTL vidioc handling - ------------------------------------------------------------------*/ - -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - - f->fmt.pix.width = dev->width; - f->fmt.pix.height = dev->height; - f->fmt.pix.pixelformat = dev->format->fourcc; - f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3; - f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height; - f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - - f->fmt.pix.field = V4L2_FIELD_INTERLACED; - - return 0; -} - -static struct cx231xx_fmt *format_by_fourcc(unsigned int fourcc) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(format); i++) - if (format[i].fourcc == fourcc) - return &format[i]; - - return NULL; -} - -static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - unsigned int width = f->fmt.pix.width; - unsigned int height = f->fmt.pix.height; - unsigned int maxw = norm_maxw(dev); - unsigned int maxh = norm_maxh(dev); - struct cx231xx_fmt *fmt; - - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - if (!fmt) { - cx231xx_videodbg("Fourcc format (%08x) invalid.\n", - f->fmt.pix.pixelformat); - return -EINVAL; - } - - /* width must even because of the YUYV format - height must be even because of interlacing */ - v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0); - - f->fmt.pix.width = width; - f->fmt.pix.height = height; - f->fmt.pix.pixelformat = fmt->fourcc; - f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3; - f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height; - f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.field = V4L2_FIELD_INTERLACED; - - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - struct cx231xx_fmt *fmt; - struct v4l2_mbus_framefmt mbus_fmt; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - vidioc_try_fmt_vid_cap(file, priv, f); - - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - if (!fmt) - return -EINVAL; - - if (videobuf_queue_is_busy(&fh->vb_vidq)) { - cx231xx_errdev("%s queue busy\n", __func__); - return -EBUSY; - } - - if (dev->stream_on && !fh->stream_on) { - cx231xx_errdev("%s device in use by another fh\n", __func__); - return -EBUSY; - } - - /* set new image size */ - dev->width = f->fmt.pix.width; - dev->height = f->fmt.pix.height; - dev->format = fmt; - - v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED); - call_all(dev, video, s_mbus_fmt, &mbus_fmt); - v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt); - - return rc; -} - -static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - - *id = dev->norm; - return 0; -} - -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - struct v4l2_mbus_framefmt mbus_fmt; - struct v4l2_format f; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - cx231xx_info("vidioc_s_std : 0x%x\n", (unsigned int)*norm); - - dev->norm = *norm; - - /* Adjusts width/height, if needed */ - f.fmt.pix.width = dev->width; - f.fmt.pix.height = dev->height; - vidioc_try_fmt_vid_cap(file, priv, &f); - - call_all(dev, core, s_std, dev->norm); - - /* We need to reset basic properties in the decoder related to - resolution (since a standard change effects things like the number - of lines in VACT, etc) */ - v4l2_fill_mbus_format(&mbus_fmt, &f.fmt.pix, V4L2_MBUS_FMT_FIXED); - call_all(dev, video, s_mbus_fmt, &mbus_fmt); - v4l2_fill_pix_format(&f.fmt.pix, &mbus_fmt); - - /* set new image size */ - dev->width = f.fmt.pix.width; - dev->height = f.fmt.pix.height; - - /* do mode control overrides */ - cx231xx_do_mode_ctrl_overrides(dev); - - return 0; -} - -static const char *iname[] = { - [CX231XX_VMUX_COMPOSITE1] = "Composite1", - [CX231XX_VMUX_SVIDEO] = "S-Video", - [CX231XX_VMUX_TELEVISION] = "Television", - [CX231XX_VMUX_CABLE] = "Cable TV", - [CX231XX_VMUX_DVB] = "DVB", - [CX231XX_VMUX_DEBUG] = "for debug only", -}; - -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *i) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - u32 gen_stat; - unsigned int ret, n; - - n = i->index; - if (n >= MAX_CX231XX_INPUT) - return -EINVAL; - if (0 == INPUT(n)->type) - return -EINVAL; - - i->index = n; - i->type = V4L2_INPUT_TYPE_CAMERA; - - strcpy(i->name, iname[INPUT(n)->type]); - - if ((CX231XX_VMUX_TELEVISION == INPUT(n)->type) || - (CX231XX_VMUX_CABLE == INPUT(n)->type)) - i->type = V4L2_INPUT_TYPE_TUNER; - - i->std = dev->vdev->tvnorms; - - /* If they are asking about the active input, read signal status */ - if (n == dev->video_input) { - ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, - GEN_STAT, 2, &gen_stat, 4); - if (ret > 0) { - if ((gen_stat & FLD_VPRES) == 0x00) - i->status |= V4L2_IN_ST_NO_SIGNAL; - if ((gen_stat & FLD_HLOCK) == 0x00) - i->status |= V4L2_IN_ST_NO_H_LOCK; - } - } - - return 0; -} - -static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - - *i = dev->video_input; - - return 0; -} - -static int vidioc_s_input(struct file *file, void *priv, unsigned int i) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - dev->mode_tv = 0; - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (i >= MAX_CX231XX_INPUT) - return -EINVAL; - if (0 == INPUT(i)->type) - return -EINVAL; - - video_mux(dev, i); - - if (INPUT(i)->type == CX231XX_VMUX_TELEVISION || - INPUT(i)->type == CX231XX_VMUX_CABLE) { - /* There's a tuner, so reset the standard and put it on the - last known frequency (since it was probably powered down - until now */ - call_all(dev, core, s_std, dev->norm); - } - - return 0; -} - -static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - - switch (a->index) { - case CX231XX_AMUX_VIDEO: - strcpy(a->name, "Television"); - break; - case CX231XX_AMUX_LINE_IN: - strcpy(a->name, "Line In"); - break; - default: - return -EINVAL; - } - - a->index = dev->ctl_ainput; - a->capability = V4L2_AUDCAP_STEREO; - - return 0; -} - -static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int status = 0; - - /* Doesn't allow manual routing */ - if (a->index != dev->ctl_ainput) - return -EINVAL; - - dev->ctl_ainput = INPUT(a->index)->amux; - status = cx231xx_set_audio_input(dev, dev->ctl_ainput); - - return status; -} - -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int id = qc->id; - int i; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - qc->id = v4l2_ctrl_next(ctrl_classes, qc->id); - if (unlikely(qc->id == 0)) - return -EINVAL; - - memset(qc, 0, sizeof(*qc)); - - qc->id = id; - - if (qc->id < V4L2_CID_BASE || qc->id >= V4L2_CID_LASTP1) - return -EINVAL; - - for (i = 0; i < CX231XX_CTLS; i++) - if (cx231xx_ctls[i].v.id == qc->id) - break; - - if (i == CX231XX_CTLS) { - *qc = no_ctl; - return 0; - } - *qc = cx231xx_ctls[i].v; - - call_all(dev, core, queryctrl, qc); - - if (qc->type) - return 0; - else - return -EINVAL; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - call_all(dev, core, g_ctrl, ctrl); - return rc; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - call_all(dev, core, s_ctrl, ctrl); - return rc; -} - -static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (0 != t->index) - return -EINVAL; - - strcpy(t->name, "Tuner"); - - t->type = V4L2_TUNER_ANALOG_TV; - t->capability = V4L2_TUNER_CAP_NORM; - t->rangehigh = 0xffffffffUL; - t->signal = 0xffff; /* LOCKED */ - - return 0; -} - -static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (0 != t->index) - return -EINVAL; -#if 0 - call_all(dev, tuner, s_tuner, t); -#endif - return 0; -} - -static int vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - - f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - f->frequency = dev->ctl_freq; - - call_all(dev, tuner, g_frequency, f); - - return 0; -} - -static int vidioc_s_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - u32 if_frequency = 5400000; - - cx231xx_info("Enter vidioc_s_frequency()f->frequency=%d;f->type=%d\n", - f->frequency, f->type); - /*cx231xx_info("f->type: 1-radio 2-analogTV 3-digitalTV\n");*/ - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (0 != f->tuner) - return -EINVAL; - - if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV)) - return -EINVAL; - if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO)) - return -EINVAL; - - /* set pre channel change settings in DIF first */ - rc = cx231xx_tuner_pre_channel_change(dev); - - dev->ctl_freq = f->frequency; - call_all(dev, tuner, s_frequency, f); - - /* set post channel change settings in DIF first */ - rc = cx231xx_tuner_post_channel_change(dev); - - if (dev->tuner_type == TUNER_NXP_TDA18271) { - if (dev->norm & (V4L2_STD_MN | V4L2_STD_NTSC_443)) - if_frequency = 5400000; /*5.4MHz */ - else if (dev->norm & V4L2_STD_B) - if_frequency = 6000000; /*6.0MHz */ - else if (dev->norm & (V4L2_STD_PAL_DK | V4L2_STD_SECAM_DK)) - if_frequency = 6900000; /*6.9MHz */ - else if (dev->norm & V4L2_STD_GH) - if_frequency = 7100000; /*7.1MHz */ - else if (dev->norm & V4L2_STD_PAL_I) - if_frequency = 7250000; /*7.25MHz */ - else if (dev->norm & V4L2_STD_SECAM_L) - if_frequency = 6900000; /*6.9MHz */ - else if (dev->norm & V4L2_STD_SECAM_LC) - if_frequency = 1250000; /*1.25MHz */ - - cx231xx_info("if_frequency is set to %d\n", if_frequency); - cx231xx_set_Colibri_For_LowIF(dev, if_frequency, 1, 1); - - update_HH_register_after_set_DIF(dev); - } - - cx231xx_info("Set New FREQUENCY to %d\n", f->frequency); - - return rc; -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG - -/* - -R, --list-registers=type=<host/i2cdrv/i2caddr>, - chip=<chip>[,min=<addr>,max=<addr>] - dump registers from <min> to <max> [VIDIOC_DBG_G_REGISTER] - -r, --set-register=type=<host/i2cdrv/i2caddr>, - chip=<chip>,reg=<addr>,val=<val> - set the register [VIDIOC_DBG_S_REGISTER] - - if type == host, then <chip> is the hosts chip ID (default 0) - if type == i2cdrv (default), then <chip> is the I2C driver name or ID - if type == i2caddr, then <chip> is the 7-bit I2C address -*/ - -static int vidioc_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int ret = 0; - u8 value[4] = { 0, 0, 0, 0 }; - u32 data = 0; - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_HOST: - switch (reg->match.addr) { - case 0: /* Cx231xx - internal registers */ - ret = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, - (u16)reg->reg, value, 4); - reg->val = value[0] | value[1] << 8 | - value[2] << 16 | value[3] << 24; - break; - case 1: /* AFE - read byte */ - ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, &data, 1); - reg->val = le32_to_cpu(data & 0xff); - break; - case 14: /* AFE - read dword */ - ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, &data, 4); - reg->val = le32_to_cpu(data); - break; - case 2: /* Video Block - read byte */ - ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, &data, 1); - reg->val = le32_to_cpu(data & 0xff); - break; - case 24: /* Video Block - read dword */ - ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, &data, 4); - reg->val = le32_to_cpu(data); - break; - case 3: /* I2S block - read byte */ - ret = cx231xx_read_i2c_data(dev, - I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, - &data, 1); - reg->val = le32_to_cpu(data & 0xff); - break; - case 34: /* I2S Block - read dword */ - ret = - cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, &data, 4); - reg->val = le32_to_cpu(data); - break; - } - return ret < 0 ? ret : 0; - - case V4L2_CHIP_MATCH_I2C_DRIVER: - call_all(dev, core, g_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR:/*for register debug*/ - switch (reg->match.addr) { - case 0: /* Cx231xx - internal registers */ - ret = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, - (u16)reg->reg, value, 4); - reg->val = value[0] | value[1] << 8 | - value[2] << 16 | value[3] << 24; - - break; - case 0x600:/* AFE - read byte */ - ret = cx231xx_read_i2c_master(dev, AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, - &data, 1 , 0); - reg->val = le32_to_cpu(data & 0xff); - break; - - case 0x880:/* Video Block - read byte */ - if (reg->reg < 0x0b) { - ret = cx231xx_read_i2c_master(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - &data, 1 , 0); - reg->val = le32_to_cpu(data & 0xff); - } else { - ret = cx231xx_read_i2c_master(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - &data, 4 , 0); - reg->val = le32_to_cpu(data); - } - break; - case 0x980: - ret = cx231xx_read_i2c_master(dev, - I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, - &data, 1 , 0); - reg->val = le32_to_cpu(data & 0xff); - break; - case 0x400: - ret = - cx231xx_read_i2c_master(dev, 0x40, - (u16)reg->reg, 1, - &data, 1 , 0); - reg->val = le32_to_cpu(data & 0xff); - break; - case 0xc01: - ret = - cx231xx_read_i2c_master(dev, 0xc0, - (u16)reg->reg, 2, - &data, 38, 1); - reg->val = le32_to_cpu(data); - break; - case 0x022: - ret = - cx231xx_read_i2c_master(dev, 0x02, - (u16)reg->reg, 1, - &data, 1, 2); - reg->val = le32_to_cpu(data & 0xff); - break; - case 0x322: - ret = cx231xx_read_i2c_master(dev, - 0x32, - (u16)reg->reg, 1, - &data, 4 , 2); - reg->val = le32_to_cpu(data); - break; - case 0x342: - ret = cx231xx_read_i2c_master(dev, - 0x34, - (u16)reg->reg, 1, - &data, 4 , 2); - reg->val = le32_to_cpu(data); - break; - - default: - cx231xx_info("no match device address!!\n"); - break; - } - return ret < 0 ? ret : 0; - /*return -EINVAL;*/ - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - - call_all(dev, core, g_register, reg); - - return ret; -} - -static int vidioc_s_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int ret = 0; - __le64 buf; - u32 value; - u8 data[4] = { 0, 0, 0, 0 }; - - buf = cpu_to_le64(reg->val); - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_HOST: - { - value = (u32) buf & 0xffffffff; - - switch (reg->match.addr) { - case 0: /* cx231xx internal registers */ - data[0] = (u8) value; - data[1] = (u8) (value >> 8); - data[2] = (u8) (value >> 16); - data[3] = (u8) (value >> 24); - ret = cx231xx_write_ctrl_reg(dev, - VRT_SET_REGISTER, - (u16)reg->reg, data, - 4); - break; - case 1: /* AFE - read byte */ - ret = cx231xx_write_i2c_data(dev, - AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, - value, 1); - break; - case 14: /* AFE - read dword */ - ret = cx231xx_write_i2c_data(dev, - AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, - value, 4); - break; - case 2: /* Video Block - read byte */ - ret = - cx231xx_write_i2c_data(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - value, 1); - break; - case 24: /* Video Block - read dword */ - ret = - cx231xx_write_i2c_data(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - value, 4); - break; - case 3: /* I2S block - read byte */ - ret = - cx231xx_write_i2c_data(dev, - I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, - value, 1); - break; - case 34: /* I2S block - read dword */ - ret = - cx231xx_write_i2c_data(dev, - I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, - value, 4); - break; - } - } - return ret < 0 ? ret : 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - { - value = (u32) buf & 0xffffffff; - - switch (reg->match.addr) { - case 0:/*cx231xx internal registers*/ - data[0] = (u8) value; - data[1] = (u8) (value >> 8); - data[2] = (u8) (value >> 16); - data[3] = (u8) (value >> 24); - ret = cx231xx_write_ctrl_reg(dev, - VRT_SET_REGISTER, - (u16)reg->reg, data, - 4); - break; - case 0x600:/* AFE - read byte */ - ret = cx231xx_write_i2c_master(dev, - AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, - value, 1 , 0); - break; - - case 0x880:/* Video Block - read byte */ - if (reg->reg < 0x0b) - cx231xx_write_i2c_master(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - value, 1, 0); - else - cx231xx_write_i2c_master(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - value, 4, 0); - break; - case 0x980: - ret = - cx231xx_write_i2c_master(dev, - I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, - value, 1, 0); - break; - case 0x400: - ret = - cx231xx_write_i2c_master(dev, - 0x40, - (u16)reg->reg, 1, - value, 1, 0); - break; - case 0xc01: - ret = - cx231xx_write_i2c_master(dev, - 0xc0, - (u16)reg->reg, 1, - value, 1, 1); - break; - - case 0x022: - ret = - cx231xx_write_i2c_master(dev, - 0x02, - (u16)reg->reg, 1, - value, 1, 2); - case 0x322: - ret = - cx231xx_write_i2c_master(dev, - 0x32, - (u16)reg->reg, 1, - value, 4, 2); - break; - - case 0x342: - ret = - cx231xx_write_i2c_master(dev, - 0x34, - (u16)reg->reg, 1, - value, 4, 2); - break; - default: - cx231xx_info("no match device address, " - "the value is %x\n", reg->match.addr); - break; - - } - - } - default: - break; - } - - call_all(dev, core, s_register, reg); - - return ret; -} -#endif - -static int vidioc_cropcap(struct file *file, void *priv, - struct v4l2_cropcap *cc) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - - if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - cc->bounds.left = 0; - cc->bounds.top = 0; - cc->bounds.width = dev->width; - cc->bounds.height = dev->height; - cc->defrect = cc->bounds; - cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */ - cc->pixelaspect.denominator = 59; - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - rc = res_get(fh); - - if (likely(rc >= 0)) - rc = videobuf_streamon(&fh->vb_vidq); - - call_all(dev, video, s_stream, 1); - - return rc; -} - -static int vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && - (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)) - return -EINVAL; - if (type != fh->type) - return -EINVAL; - - cx25840_call(dev, video, s_stream, 0); - - videobuf_streamoff(&fh->vb_vidq); - res_free(fh); - - return 0; -} - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - - strlcpy(cap->driver, "cx231xx", sizeof(cap->driver)); - strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card)); - usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); - - cap->capabilities = V4L2_CAP_VBI_CAPTURE | -#if 0 - V4L2_CAP_SLICED_VBI_CAPTURE | -#endif - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_AUDIO | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - - if (dev->tuner_type != TUNER_ABSENT) - cap->capabilities |= V4L2_CAP_TUNER; - - return 0; -} - -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - if (unlikely(f->index >= ARRAY_SIZE(format))) - return -EINVAL; - - strlcpy(f->description, format[f->index].name, sizeof(f->description)); - f->pixelformat = format[f->index].fourcc; - - return 0; -} - -/* Sliced VBI ioctls */ -static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - f->fmt.sliced.service_set = 0; - - call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced); - - if (f->fmt.sliced.service_set == 0) - rc = -EINVAL; - - return rc; -} - -static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced); - - if (f->fmt.sliced.service_set == 0) - return -EINVAL; - - return 0; -} - -/* RAW VBI ioctls */ - -static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - f->fmt.vbi.sampling_rate = 6750000 * 4; - f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; - f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - f->fmt.vbi.offset = 0; - f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ? - PAL_VBI_START_LINE : NTSC_VBI_START_LINE; - f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ? - PAL_VBI_LINES : NTSC_VBI_LINES; - f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ? - PAL_VBI_START_LINE + 312 : NTSC_VBI_START_LINE + 263; - f->fmt.vbi.count[1] = f->fmt.vbi.count[0]; - - return 0; - -} - -static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - - if (dev->vbi_stream_on && !fh->stream_on) { - cx231xx_errdev("%s device in use by another fh\n", __func__); - return -EBUSY; - } - - f->type = V4L2_BUF_TYPE_VBI_CAPTURE; - f->fmt.vbi.sampling_rate = 6750000 * 4; - f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; - f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - f->fmt.vbi.offset = 0; - f->fmt.vbi.flags = 0; - f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ? - PAL_VBI_START_LINE : NTSC_VBI_START_LINE; - f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ? - PAL_VBI_LINES : NTSC_VBI_LINES; - f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ? - PAL_VBI_START_LINE + 312 : NTSC_VBI_START_LINE + 263; - f->fmt.vbi.count[1] = f->fmt.vbi.count[0]; - - return 0; - -} - -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - return videobuf_reqbufs(&fh->vb_vidq, rb); -} - -static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - return videobuf_querybuf(&fh->vb_vidq, b); -} - -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - return videobuf_qbuf(&fh->vb_vidq, b); -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct cx231xx_fh *fh = priv; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); -} - -/* ----------------------------------------------------------- */ -/* RADIO ESPECIFIC IOCTLS */ -/* ----------------------------------------------------------- */ - -static int radio_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev; - - strlcpy(cap->driver, "cx231xx", sizeof(cap->driver)); - strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card)); - usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); - - cap->capabilities = V4L2_CAP_TUNER; - return 0; -} - -static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) -{ - struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev; - - if (unlikely(t->index > 0)) - return -EINVAL; - - strcpy(t->name, "Radio"); - t->type = V4L2_TUNER_RADIO; - - call_all(dev, tuner, s_tuner, t); - - return 0; -} - -static int radio_enum_input(struct file *file, void *priv, struct v4l2_input *i) -{ - if (i->index != 0) - return -EINVAL; - strcpy(i->name, "Radio"); - i->type = V4L2_INPUT_TYPE_TUNER; - - return 0; -} - -static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - if (unlikely(a->index)) - return -EINVAL; - - strcpy(a->name, "Radio"); - return 0; -} - -static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) -{ - struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev; - - if (0 != t->index) - return -EINVAL; - - call_all(dev, tuner, s_tuner, t); - - return 0; -} - -static int radio_s_audio(struct file *file, void *fh, struct v4l2_audio *a) -{ - return 0; -} - -static int radio_s_input(struct file *file, void *fh, unsigned int i) -{ - return 0; -} - -static int radio_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *c) -{ - int i; - - if (c->id < V4L2_CID_BASE || c->id >= V4L2_CID_LASTP1) - return -EINVAL; - if (c->id == V4L2_CID_AUDIO_MUTE) { - for (i = 0; i < CX231XX_CTLS; i++) { - if (cx231xx_ctls[i].v.id == c->id) - break; - } - if (i == CX231XX_CTLS) - return -EINVAL; - *c = cx231xx_ctls[i].v; - } else - *c = no_ctl; - return 0; -} - -/* - * cx231xx_v4l2_open() - * inits the device and starts isoc transfer - */ -static int cx231xx_v4l2_open(struct file *filp) -{ - int errCode = 0, radio = 0; - struct video_device *vdev = video_devdata(filp); - struct cx231xx *dev = video_drvdata(filp); - struct cx231xx_fh *fh; - enum v4l2_buf_type fh_type = 0; - - switch (vdev->vfl_type) { - case VFL_TYPE_GRABBER: - fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - break; - case VFL_TYPE_VBI: - fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; - break; - case VFL_TYPE_RADIO: - radio = 1; - break; - } - - cx231xx_videodbg("open dev=%s type=%s users=%d\n", - video_device_node_name(vdev), v4l2_type_names[fh_type], - dev->users); - -#if 0 - errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); - if (errCode < 0) { - cx231xx_errdev - ("Device locked on digital mode. Can't open analog\n"); - return -EBUSY; - } -#endif - - fh = kzalloc(sizeof(struct cx231xx_fh), GFP_KERNEL); - if (!fh) { - cx231xx_errdev("cx231xx-video.c: Out of memory?!\n"); - return -ENOMEM; - } - if (mutex_lock_interruptible(&dev->lock)) { - kfree(fh); - return -ERESTARTSYS; - } - fh->dev = dev; - fh->radio = radio; - fh->type = fh_type; - filp->private_data = fh; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { - dev->width = norm_maxw(dev); - dev->height = norm_maxh(dev); - - /* Power up in Analog TV mode */ - if (dev->board.external_av) - cx231xx_set_power_mode(dev, - POLARIS_AVMODE_ENXTERNAL_AV); - else - cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); - -#if 0 - cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); -#endif - - /* set video alternate setting */ - cx231xx_set_video_alternate(dev); - - /* Needed, since GPIO might have disabled power of - some i2c device */ - cx231xx_config_i2c(dev); - - /* device needs to be initialized before isoc transfer */ - dev->video_input = dev->video_input > 2 ? 2 : dev->video_input; - - } - if (fh->radio) { - cx231xx_videodbg("video_open: setting radio device\n"); - - /* cx231xx_start_radio(dev); */ - - call_all(dev, tuner, s_radio); - } - - dev->users++; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_video_qops, - NULL, &dev->video_mode.slock, - fh->type, V4L2_FIELD_INTERLACED, - sizeof(struct cx231xx_buffer), - fh, &dev->lock); - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - /* Set the required alternate setting VBI interface works in - Bulk mode only */ - cx231xx_set_alt_setting(dev, INDEX_VANC, 0); - - videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops, - NULL, &dev->vbi_mode.slock, - fh->type, V4L2_FIELD_SEQ_TB, - sizeof(struct cx231xx_buffer), - fh, &dev->lock); - } - mutex_unlock(&dev->lock); - - return errCode; -} - -/* - * cx231xx_realease_resources() - * unregisters the v4l2,i2c and usb devices - * called when the device gets disconected or at module unload -*/ -void cx231xx_release_analog_resources(struct cx231xx *dev) -{ - - /*FIXME: I2C IR should be disconnected */ - - if (dev->radio_dev) { - if (video_is_registered(dev->radio_dev)) - video_unregister_device(dev->radio_dev); - else - video_device_release(dev->radio_dev); - dev->radio_dev = NULL; - } - if (dev->vbi_dev) { - cx231xx_info("V4L2 device %s deregistered\n", - video_device_node_name(dev->vbi_dev)); - if (video_is_registered(dev->vbi_dev)) - video_unregister_device(dev->vbi_dev); - else - video_device_release(dev->vbi_dev); - dev->vbi_dev = NULL; - } - if (dev->vdev) { - cx231xx_info("V4L2 device %s deregistered\n", - video_device_node_name(dev->vdev)); - - if (dev->board.has_417) - cx231xx_417_unregister(dev); - - if (video_is_registered(dev->vdev)) - video_unregister_device(dev->vdev); - else - video_device_release(dev->vdev); - dev->vdev = NULL; - } -} - -/* - * cx231xx_close() - * stops streaming and deallocates all resources allocated by the v4l2 - * calls and ioctls - */ -static int cx231xx_close(struct file *filp) -{ - struct cx231xx_fh *fh = filp->private_data; - struct cx231xx *dev = fh->dev; - - cx231xx_videodbg("users=%d\n", dev->users); - - cx231xx_videodbg("users=%d\n", dev->users); - if (res_check(fh)) - res_free(fh); - - /* - * To workaround error number=-71 on EP0 for VideoGrabber, - * need exclude following. - * FIXME: It is probably safe to remove most of these, as we're - * now avoiding the alternate setting for INDEX_VANC - */ - if (!dev->board.no_alt_vanc) - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - videobuf_stop(&fh->vb_vidq); - videobuf_mmap_free(&fh->vb_vidq); - - /* the device is already disconnect, - free the remaining resources */ - if (dev->state & DEV_DISCONNECTED) { - if (atomic_read(&dev->devlist_count) > 0) { - cx231xx_release_resources(dev); - fh->dev = NULL; - return 0; - } - return 0; - } - - /* do this before setting alternate! */ - cx231xx_uninit_vbi_isoc(dev); - - /* set alternate 0 */ - if (!dev->vbi_or_sliced_cc_mode) - cx231xx_set_alt_setting(dev, INDEX_VANC, 0); - else - cx231xx_set_alt_setting(dev, INDEX_HANC, 0); - - kfree(fh); - dev->users--; - wake_up_interruptible_nr(&dev->open, 1); - return 0; - } - - dev->users--; - if (!dev->users) { - videobuf_stop(&fh->vb_vidq); - videobuf_mmap_free(&fh->vb_vidq); - - /* the device is already disconnect, - free the remaining resources */ - if (dev->state & DEV_DISCONNECTED) { - cx231xx_release_resources(dev); - fh->dev = NULL; - return 0; - } - - /* Save some power by putting tuner to sleep */ - call_all(dev, core, s_power, 0); - - /* do this before setting alternate! */ - if (dev->USE_ISO) - cx231xx_uninit_isoc(dev); - else - cx231xx_uninit_bulk(dev); - cx231xx_set_mode(dev, CX231XX_SUSPEND); - - /* set alternate 0 */ - cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0); - } - kfree(fh); - wake_up_interruptible_nr(&dev->open, 1); - return 0; -} - -static int cx231xx_v4l2_close(struct file *filp) -{ - struct cx231xx_fh *fh = filp->private_data; - struct cx231xx *dev = fh->dev; - int rc; - - mutex_lock(&dev->lock); - rc = cx231xx_close(filp); - mutex_unlock(&dev->lock); - return rc; -} - -/* - * cx231xx_v4l2_read() - * will allocate buffers when called for the first time - */ -static ssize_t -cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count, - loff_t *pos) -{ - struct cx231xx_fh *fh = filp->private_data; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if ((fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) || - (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)) { - rc = res_get(fh); - - if (unlikely(rc < 0)) - return rc; - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - rc = videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, - filp->f_flags & O_NONBLOCK); - mutex_unlock(&dev->lock); - return rc; - } - return 0; -} - -/* - * cx231xx_v4l2_poll() - * will allocate buffers when called for the first time - */ -static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table *wait) -{ - struct cx231xx_fh *fh = filp->private_data; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - rc = res_get(fh); - - if (unlikely(rc < 0)) - return POLLERR; - - if ((V4L2_BUF_TYPE_VIDEO_CAPTURE == fh->type) || - (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)) { - unsigned int res; - - mutex_lock(&dev->lock); - res = videobuf_poll_stream(filp, &fh->vb_vidq, wait); - mutex_unlock(&dev->lock); - return res; - } - return POLLERR; -} - -/* - * cx231xx_v4l2_mmap() - */ -static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct cx231xx_fh *fh = filp->private_data; - struct cx231xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - rc = res_get(fh); - - if (unlikely(rc < 0)) - return rc; - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); - mutex_unlock(&dev->lock); - - cx231xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n", - (unsigned long)vma->vm_start, - (unsigned long)vma->vm_end - - (unsigned long)vma->vm_start, rc); - - return rc; -} - -static const struct v4l2_file_operations cx231xx_v4l_fops = { - .owner = THIS_MODULE, - .open = cx231xx_v4l2_open, - .release = cx231xx_v4l2_close, - .read = cx231xx_v4l2_read, - .poll = cx231xx_v4l2_poll, - .mmap = cx231xx_v4l2_mmap, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, - .vidioc_try_fmt_vbi_cap = vidioc_try_fmt_vbi_cap, - .vidioc_s_fmt_vbi_cap = vidioc_try_fmt_vbi_cap, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_cropcap = vidioc_cropcap, - .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, - .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, - .vidioc_s_std = vidioc_s_std, - .vidioc_g_std = vidioc_g_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_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .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 -}; - -static struct video_device cx231xx_vbi_template; - -static const struct video_device cx231xx_video_template = { - .fops = &cx231xx_v4l_fops, - .release = video_device_release, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = V4L2_STD_ALL, - .current_norm = V4L2_STD_PAL, -}; - -static const struct v4l2_file_operations radio_fops = { - .owner = THIS_MODULE, - .open = cx231xx_v4l2_open, - .release = cx231xx_v4l2_close, - .ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops radio_ioctl_ops = { - .vidioc_querycap = radio_querycap, - .vidioc_g_tuner = radio_g_tuner, - .vidioc_enum_input = radio_enum_input, - .vidioc_g_audio = radio_g_audio, - .vidioc_s_tuner = radio_s_tuner, - .vidioc_s_audio = radio_s_audio, - .vidioc_s_input = radio_s_input, - .vidioc_queryctrl = radio_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .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 -}; - -static struct video_device cx231xx_radio_template = { - .name = "cx231xx-radio", - .fops = &radio_fops, - .ioctl_ops = &radio_ioctl_ops, -}; - -/******************************** usb interface ******************************/ - -static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, - const struct video_device - *template, const char *type_name) -{ - struct video_device *vfd; - - vfd = video_device_alloc(); - if (NULL == vfd) - return NULL; - - *vfd = *template; - vfd->v4l2_dev = &dev->v4l2_dev; - vfd->release = video_device_release; - vfd->debug = video_debug; - vfd->lock = &dev->lock; - - snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); - - video_set_drvdata(vfd, dev); - return vfd; -} - -int cx231xx_register_analog_devices(struct cx231xx *dev) -{ - int ret; - - cx231xx_info("%s: v4l2 driver version %s\n", - dev->name, CX231XX_VERSION); - - /* set default norm */ - /*dev->norm = cx231xx_video_template.current_norm; */ - dev->width = norm_maxw(dev); - dev->height = norm_maxh(dev); - dev->interlaced = 0; - - /* Analog specific initialization */ - dev->format = &format[0]; - - /* Set the initial input */ - video_mux(dev, dev->video_input); - - /* Audio defaults */ - dev->mute = 1; - dev->volume = 0x1f; - - /* enable vbi capturing */ - /* write code here... */ - - /* allocate and fill video video_device struct */ - dev->vdev = cx231xx_vdev_init(dev, &cx231xx_video_template, "video"); - if (!dev->vdev) { - cx231xx_errdev("cannot allocate video_device.\n"); - return -ENODEV; - } - - /* register v4l2 video video_device */ - ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER, - video_nr[dev->devno]); - if (ret) { - cx231xx_errdev("unable to register video device (error=%i).\n", - ret); - return ret; - } - - cx231xx_info("%s/0: registered device %s [v4l2]\n", - dev->name, video_device_node_name(dev->vdev)); - - /* Initialize VBI template */ - memcpy(&cx231xx_vbi_template, &cx231xx_video_template, - sizeof(cx231xx_vbi_template)); - strcpy(cx231xx_vbi_template.name, "cx231xx-vbi"); - - /* Allocate and fill vbi video_device struct */ - dev->vbi_dev = cx231xx_vdev_init(dev, &cx231xx_vbi_template, "vbi"); - - /* register v4l2 vbi video_device */ - ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, - vbi_nr[dev->devno]); - if (ret < 0) { - cx231xx_errdev("unable to register vbi device\n"); - return ret; - } - - cx231xx_info("%s/0: registered device %s\n", - dev->name, video_device_node_name(dev->vbi_dev)); - - if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) { - dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template, - "radio"); - if (!dev->radio_dev) { - cx231xx_errdev("cannot allocate video_device.\n"); - return -ENODEV; - } - ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, - radio_nr[dev->devno]); - if (ret < 0) { - cx231xx_errdev("can't register radio device\n"); - return ret; - } - cx231xx_info("Registered radio device as %s\n", - video_device_node_name(dev->radio_dev)); - } - - cx231xx_info("V4L2 device registered as %s and %s\n", - video_device_node_name(dev->vdev), - video_device_node_name(dev->vbi_dev)); - - return 0; -} diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h deleted file mode 100644 index a89d020de948..000000000000 --- a/drivers/media/video/cx231xx/cx231xx.h +++ /dev/null @@ -1,1012 +0,0 @@ -/* - cx231xx.h - driver for Conexant Cx23100/101/102 USB video capture devices - - Copyright (C) 2008 <srinivasa.deevi at conexant dot com> - Based on em28xx driver - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _CX231XX_H -#define _CX231XX_H - -#include <linux/videodev2.h> -#include <linux/types.h> -#include <linux/ioctl.h> -#include <linux/i2c.h> -#include <linux/workqueue.h> -#include <linux/mutex.h> - -#include <media/cx2341x.h> - -#include <media/videobuf-vmalloc.h> -#include <media/v4l2-device.h> -#include <media/rc-core.h> -#include <media/ir-kbd-i2c.h> -#include <media/videobuf-dvb.h> - -#include "cx231xx-reg.h" -#include "cx231xx-pcb-cfg.h" -#include "cx231xx-conf-reg.h" - -#define DRIVER_NAME "cx231xx" -#define PWR_SLEEP_INTERVAL 10 - -/* I2C addresses for control block in Cx231xx */ -#define AFE_DEVICE_ADDRESS 0x60 -#define I2S_BLK_DEVICE_ADDRESS 0x98 -#define VID_BLK_I2C_ADDRESS 0x88 -#define VERVE_I2C_ADDRESS 0x40 -#define DIF_USE_BASEBAND 0xFFFFFFFF - -/* Boards supported by driver */ -#define CX231XX_BOARD_UNKNOWN 0 -#define CX231XX_BOARD_CNXT_CARRAERA 1 -#define CX231XX_BOARD_CNXT_SHELBY 2 -#define CX231XX_BOARD_CNXT_RDE_253S 3 -#define CX231XX_BOARD_CNXT_RDU_253S 4 -#define CX231XX_BOARD_CNXT_VIDEO_GRABBER 5 -#define CX231XX_BOARD_CNXT_RDE_250 6 -#define CX231XX_BOARD_CNXT_RDU_250 7 -#define CX231XX_BOARD_HAUPPAUGE_EXETER 8 -#define CX231XX_BOARD_HAUPPAUGE_USBLIVE2 9 -#define CX231XX_BOARD_PV_PLAYTV_USB_HYBRID 10 -#define CX231XX_BOARD_PV_XCAPTURE_USB 11 -#define CX231XX_BOARD_KWORLD_UB430_USB_HYBRID 12 -#define CX231XX_BOARD_ICONBIT_U100 13 -#define CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL 14 -#define CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC 15 - -/* Limits minimum and default number of buffers */ -#define CX231XX_MIN_BUF 4 -#define CX231XX_DEF_BUF 12 -#define CX231XX_DEF_VBI_BUF 6 - -#define VBI_LINE_COUNT 17 -#define VBI_LINE_LENGTH 1440 - -/*Limits the max URB message size */ -#define URB_MAX_CTRL_SIZE 80 - -/* Params for validated field */ -#define CX231XX_BOARD_NOT_VALIDATED 1 -#define CX231XX_BOARD_VALIDATED 0 - -/* maximum number of cx231xx boards */ -#define CX231XX_MAXBOARDS 8 - -/* maximum number of frames that can be queued */ -#define CX231XX_NUM_FRAMES 5 - -/* number of buffers for isoc transfers */ -#define CX231XX_NUM_BUFS 8 - -/* number of packets for each buffer - windows requests only 40 packets .. so we better do the same - this is what I found out for all alternate numbers there! - */ -#define CX231XX_NUM_PACKETS 40 - -/* default alternate; 0 means choose the best */ -#define CX231XX_PINOUT 0 - -#define CX231XX_INTERLACED_DEFAULT 1 - -/* time to wait when stopping the isoc transfer */ -#define CX231XX_URB_TIMEOUT \ - msecs_to_jiffies(CX231XX_NUM_BUFS * CX231XX_NUM_PACKETS) - -#define CX231xx_NORMS (\ - V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_443 | \ - V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_I | \ - V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | \ - V4L2_STD_PAL_60 | V4L2_STD_SECAM_L | V4L2_STD_SECAM_DK) - -#define SLEEP_S5H1432 30 -#define CX23417_OSC_EN 8 -#define CX23417_RESET 9 - -struct cx23417_fmt { - char *name; - u32 fourcc; /* v4l2 format id */ - int depth; - int flags; - u32 cxformat; -}; -enum cx231xx_mode { - CX231XX_SUSPEND, - CX231XX_ANALOG_MODE, - CX231XX_DIGITAL_MODE, -}; - -enum cx231xx_std_mode { - CX231XX_TV_AIR = 0, - CX231XX_TV_CABLE -}; - -enum cx231xx_stream_state { - STREAM_OFF, - STREAM_INTERRUPT, - STREAM_ON, -}; - -struct cx231xx; - -struct cx231xx_isoc_ctl { - /* max packet size of isoc transaction */ - int max_pkt_size; - - /* number of allocated urbs */ - int num_bufs; - - /* urb for isoc transfers */ - struct urb **urb; - - /* transfer buffers for isoc transfer */ - char **transfer_buffer; - - /* Last buffer command and region */ - u8 cmd; - int pos, size, pktsize; - - /* Last field: ODD or EVEN? */ - int field; - - /* Stores incomplete commands */ - u32 tmp_buf; - int tmp_buf_len; - - /* Stores already requested buffers */ - struct cx231xx_buffer *buf; - - /* Stores the number of received fields */ - int nfields; - - /* isoc urb callback */ - int (*isoc_copy) (struct cx231xx *dev, struct urb *urb); -}; - -struct cx231xx_bulk_ctl { - /* max packet size of bulk transaction */ - int max_pkt_size; - - /* number of allocated urbs */ - int num_bufs; - - /* urb for bulk transfers */ - struct urb **urb; - - /* transfer buffers for bulk transfer */ - char **transfer_buffer; - - /* Last buffer command and region */ - u8 cmd; - int pos, size, pktsize; - - /* Last field: ODD or EVEN? */ - int field; - - /* Stores incomplete commands */ - u32 tmp_buf; - int tmp_buf_len; - - /* Stores already requested buffers */ - struct cx231xx_buffer *buf; - - /* Stores the number of received fields */ - int nfields; - - /* bulk urb callback */ - int (*bulk_copy) (struct cx231xx *dev, struct urb *urb); -}; - -struct cx231xx_fmt { - char *name; - u32 fourcc; /* v4l2 format id */ - int depth; - int reg; -}; - -/* buffer for one video frame */ -struct cx231xx_buffer { - /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - - struct list_head frame; - int top_field; - int receiving; -}; - -enum ps_package_head { - CX231XX_NEED_ADD_PS_PACKAGE_HEAD = 0, - CX231XX_NONEED_PS_PACKAGE_HEAD -}; - -struct cx231xx_dmaqueue { - struct list_head active; - struct list_head queued; - - wait_queue_head_t wq; - - /* Counters to control buffer fill */ - int pos; - u8 is_partial_line; - u8 partial_buf[8]; - u8 last_sav; - int current_field; - u32 bytes_left_in_line; - u32 lines_completed; - u8 field1_done; - u32 lines_per_field; - - /*Mpeg2 control buffer*/ - u8 *p_left_data; - u32 left_data_count; - u8 mpeg_buffer_done; - u32 mpeg_buffer_completed; - enum ps_package_head add_ps_package_head; - char ps_head[10]; -}; - -/* inputs */ - -#define MAX_CX231XX_INPUT 4 - -enum cx231xx_itype { - CX231XX_VMUX_COMPOSITE1 = 1, - CX231XX_VMUX_SVIDEO, - CX231XX_VMUX_TELEVISION, - CX231XX_VMUX_CABLE, - CX231XX_RADIO, - CX231XX_VMUX_DVB, - CX231XX_VMUX_DEBUG -}; - -enum cx231xx_v_input { - CX231XX_VIN_1_1 = 0x1, - CX231XX_VIN_2_1, - CX231XX_VIN_3_1, - CX231XX_VIN_4_1, - CX231XX_VIN_1_2 = 0x01, - CX231XX_VIN_2_2, - CX231XX_VIN_3_2, - CX231XX_VIN_1_3 = 0x1, - CX231XX_VIN_2_3, - CX231XX_VIN_3_3, -}; - -/* cx231xx has two audio inputs: tuner and line in */ -enum cx231xx_amux { - /* This is the only entry for cx231xx tuner input */ - CX231XX_AMUX_VIDEO, /* cx231xx tuner */ - CX231XX_AMUX_LINE_IN, /* Line In */ -}; - -struct cx231xx_reg_seq { - unsigned char bit; - unsigned char val; - int sleep; -}; - -struct cx231xx_input { - enum cx231xx_itype type; - unsigned int vmux; - enum cx231xx_amux amux; - struct cx231xx_reg_seq *gpio; -}; - -#define INPUT(nr) (&cx231xx_boards[dev->model].input[nr]) - -enum cx231xx_decoder { - CX231XX_NODECODER, - CX231XX_AVDECODER -}; - -enum CX231XX_I2C_MASTER_PORT { - I2C_0 = 0, - I2C_1 = 1, - I2C_2 = 2, - I2C_3 = 3 -}; - -struct cx231xx_board { - char *name; - int vchannels; - int tuner_type; - int tuner_addr; - v4l2_std_id norm; /* tv norm */ - - /* demod related */ - int demod_addr; - u8 demod_xfer_mode; /* 0 - Serial; 1 - parallel */ - - /* GPIO Pins */ - struct cx231xx_reg_seq *dvb_gpio; - struct cx231xx_reg_seq *suspend_gpio; - struct cx231xx_reg_seq *tuner_gpio; - /* Negative means don't use it */ - s8 tuner_sif_gpio; - s8 tuner_scl_gpio; - s8 tuner_sda_gpio; - - /* PIN ctrl */ - u32 ctl_pin_status_mask; - u8 agc_analog_digital_select_gpio; - u32 gpio_pin_status_mask; - - /* i2c masters */ - u8 tuner_i2c_master; - u8 demod_i2c_master; - u8 ir_i2c_master; - - /* for devices with I2C chips for IR */ - char *rc_map_name; - - unsigned int max_range_640_480:1; - unsigned int has_dvb:1; - unsigned int has_417:1; - unsigned int valid:1; - unsigned int no_alt_vanc:1; - unsigned int external_av:1; - unsigned int dont_use_port_3:1; - - unsigned char xclk, i2c_speed; - - enum cx231xx_decoder decoder; - int output_mode; - - struct cx231xx_input input[MAX_CX231XX_INPUT]; - struct cx231xx_input radio; - struct rc_map *ir_codes; -}; - -/* device states */ -enum cx231xx_dev_state { - DEV_INITIALIZED = 0x01, - DEV_DISCONNECTED = 0x02, -}; - -enum AFE_MODE { - AFE_MODE_LOW_IF, - AFE_MODE_BASEBAND, - AFE_MODE_EU_HI_IF, - AFE_MODE_US_HI_IF, - AFE_MODE_JAPAN_HI_IF -}; - -enum AUDIO_INPUT { - AUDIO_INPUT_MUTE, - AUDIO_INPUT_LINE, - AUDIO_INPUT_TUNER_TV, - AUDIO_INPUT_SPDIF, - AUDIO_INPUT_TUNER_FM -}; - -#define CX231XX_AUDIO_BUFS 5 -#define CX231XX_NUM_AUDIO_PACKETS 16 -#define CX231XX_ISO_NUM_AUDIO_PACKETS 64 - -/* cx231xx extensions */ -#define CX231XX_AUDIO 0x10 -#define CX231XX_DVB 0x20 - -struct cx231xx_audio { - char name[50]; - char *transfer_buffer[CX231XX_AUDIO_BUFS]; - struct urb *urb[CX231XX_AUDIO_BUFS]; - struct usb_device *udev; - unsigned int capture_transfer_done; - struct snd_pcm_substream *capture_pcm_substream; - - unsigned int hwptr_done_capture; - struct snd_card *sndcard; - - int users, shutdown; - /* locks */ - spinlock_t slock; - - int alt; /* alternate */ - int max_pkt_size; /* max packet size of isoc transaction */ - int num_alt; /* Number of alternative settings */ - unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ - u16 end_point_addr; -}; - -struct cx231xx; - -struct cx231xx_fh { - struct cx231xx *dev; - unsigned int stream_on:1; /* Locks streams */ - int radio; - - struct videobuf_queue vb_vidq; - - enum v4l2_buf_type type; - - - -/*following is copyed from cx23885.h*/ - u32 resources; - - /* video overlay */ - struct v4l2_window win; - struct v4l2_clip *clips; - unsigned int nclips; - - /* video capture */ - struct cx23417_fmt *fmt; - unsigned int width, height; - - /* vbi capture */ - struct videobuf_queue vidq; - struct videobuf_queue vbiq; - - /* MPEG Encoder specifics ONLY */ - - atomic_t v4l_reading; -}; - -/*****************************************************************/ -/* set/get i2c */ -/* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */ -#define I2C_SPEED_1M 0x0 -#define I2C_SPEED_400K 0x1 -#define I2C_SPEED_100K 0x2 -#define I2C_SPEED_5M 0x3 - -/* 0-- STOP transaction */ -#define I2C_STOP 0x0 -/* 1-- do not transmit STOP at end of transaction */ -#define I2C_NOSTOP 0x1 -/* 1--allow slave to insert clock wait states */ -#define I2C_SYNC 0x1 - -struct cx231xx_i2c { - struct cx231xx *dev; - - int nr; - - /* i2c i/o */ - struct i2c_adapter i2c_adap; - struct i2c_client i2c_client; - u32 i2c_rc; - - /* different settings for each bus */ - u8 i2c_period; - u8 i2c_nostop; - u8 i2c_reserve; -}; - -struct cx231xx_i2c_xfer_data { - u8 dev_addr; - u8 direction; /* 1 - IN, 0 - OUT */ - u8 saddr_len; /* sub address len */ - u16 saddr_dat; /* sub addr data */ - u8 buf_size; /* buffer size */ - u8 *p_buffer; /* pointer to the buffer */ -}; - -struct VENDOR_REQUEST_IN { - u8 bRequest; - u16 wValue; - u16 wIndex; - u16 wLength; - u8 direction; - u8 bData; - u8 *pBuff; -}; - -struct cx231xx_tvnorm { - char *name; - v4l2_std_id id; - u32 cxiformat; - u32 cxoformat; -}; - -struct cx231xx_ctrl { - struct v4l2_queryctrl v; - u32 off; - u32 reg; - u32 mask; - u32 shift; -}; - -enum TRANSFER_TYPE { - Raw_Video = 0, - Audio, - Vbi, /* VANC */ - Sliced_cc, /* HANC */ - TS1_serial_mode, - TS2, - TS1_parallel_mode -} ; - -struct cx231xx_video_mode { - /* Isoc control struct */ - struct cx231xx_dmaqueue vidq; - struct cx231xx_isoc_ctl isoc_ctl; - struct cx231xx_bulk_ctl bulk_ctl; - /* locks */ - spinlock_t slock; - - /* usb transfer */ - int alt; /* alternate */ - int max_pkt_size; /* max packet size of isoc transaction */ - int num_alt; /* Number of alternative settings */ - unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ - u16 end_point_addr; -}; -/* -struct cx23885_dmaqueue { - struct list_head active; - struct list_head queued; - struct timer_list timeout; - struct btcx_riscmem stopper; - u32 count; -}; -*/ -struct cx231xx_tsport { - struct cx231xx *dev; - - int nr; - int sram_chno; - - struct videobuf_dvb_frontends frontends; - - /* dma queues */ - - u32 ts_packet_size; - u32 ts_packet_count; - - int width; - int height; - - /* locks */ - spinlock_t slock; - - /* registers */ - u32 reg_gpcnt; - u32 reg_gpcnt_ctl; - u32 reg_dma_ctl; - u32 reg_lngth; - u32 reg_hw_sop_ctrl; - u32 reg_gen_ctrl; - u32 reg_bd_pkt_status; - u32 reg_sop_status; - u32 reg_fifo_ovfl_stat; - u32 reg_vld_misc; - u32 reg_ts_clk_en; - u32 reg_ts_int_msk; - u32 reg_ts_int_stat; - u32 reg_src_sel; - - /* Default register vals */ - int pci_irqmask; - u32 dma_ctl_val; - u32 ts_int_msk_val; - u32 gen_ctrl_val; - u32 ts_clk_en_val; - u32 src_sel_val; - u32 vld_misc_val; - u32 hw_sop_ctrl_val; - - /* Allow a single tsport to have multiple frontends */ - u32 num_frontends; - void *port_priv; -}; - -/* main device struct */ -struct cx231xx { - /* generic device properties */ - char name[30]; /* name (including minor) of the device */ - int model; /* index in the device_data struct */ - int devno; /* marks the number of this device */ - - struct cx231xx_board board; - - /* For I2C IR support */ - struct IR_i2c_init_data init_data; - struct i2c_client *ir_i2c_client; - - unsigned int stream_on:1; /* Locks streams */ - unsigned int vbi_stream_on:1; /* Locks streams for VBI */ - unsigned int has_audio_class:1; - unsigned int has_alsa_audio:1; - - struct cx231xx_fmt *format; - - struct v4l2_device v4l2_dev; - struct v4l2_subdev *sd_cx25840; - struct v4l2_subdev *sd_tuner; - - struct work_struct wq_trigger; /* Trigger to start/stop audio for alsa module */ - atomic_t stream_started; /* stream should be running if true */ - - struct list_head devlist; - - int tuner_type; /* type of the tuner */ - int tuner_addr; /* tuner address */ - - /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */ - struct cx231xx_i2c i2c_bus[3]; - unsigned int xc_fw_load_done:1; - /* locks */ - struct mutex gpio_i2c_lock; - struct mutex i2c_lock; - - /* video for linux */ - int users; /* user count for exclusive use */ - struct video_device *vdev; /* video for linux device struct */ - v4l2_std_id norm; /* selected tv norm */ - int ctl_freq; /* selected frequency */ - unsigned int ctl_ainput; /* selected audio input */ - int mute; - int volume; - - /* frame properties */ - int width; /* current frame width */ - int height; /* current frame height */ - int interlaced; /* 1=interlace fileds, 0=just top fileds */ - - struct cx231xx_audio adev; - - /* states */ - enum cx231xx_dev_state state; - - struct work_struct request_module_wk; - - /* locks */ - struct mutex lock; - struct mutex ctrl_urb_lock; /* protects urb_buf */ - struct list_head inqueue, outqueue; - wait_queue_head_t open, wait_frame, wait_stream; - struct video_device *vbi_dev; - struct video_device *radio_dev; - - unsigned char eedata[256]; - - struct cx231xx_video_mode video_mode; - struct cx231xx_video_mode vbi_mode; - struct cx231xx_video_mode sliced_cc_mode; - struct cx231xx_video_mode ts1_mode; - - atomic_t devlist_count; - - struct usb_device *udev; /* the usb device */ - char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ - - /* helper funcs that call usb_control_msg */ - int (*cx231xx_read_ctrl_reg) (struct cx231xx *dev, u8 req, u16 reg, - char *buf, int len); - int (*cx231xx_write_ctrl_reg) (struct cx231xx *dev, u8 req, u16 reg, - char *buf, int len); - int (*cx231xx_send_usb_command) (struct cx231xx_i2c *i2c_bus, - struct cx231xx_i2c_xfer_data *req_data); - int (*cx231xx_gpio_i2c_read) (struct cx231xx *dev, u8 dev_addr, - u8 *buf, u8 len); - int (*cx231xx_gpio_i2c_write) (struct cx231xx *dev, u8 dev_addr, - u8 *buf, u8 len); - - int (*cx231xx_set_analog_freq) (struct cx231xx *dev, u32 freq); - int (*cx231xx_reset_analog_tuner) (struct cx231xx *dev); - - enum cx231xx_mode mode; - - struct cx231xx_dvb *dvb; - - /* Cx231xx supported PCB config's */ - struct pcb_config current_pcb_config; - u8 current_scenario_idx; - u8 interface_count; - u8 max_iad_interface_count; - - /* GPIO related register direction and values */ - u32 gpio_dir; - u32 gpio_val; - - /* Power Modes */ - int power_mode; - - /* afe parameters */ - enum AFE_MODE afe_mode; - u32 afe_ref_count; - - /* video related parameters */ - u32 video_input; - u32 active_mode; - u8 vbi_or_sliced_cc_mode; /* 0 - vbi ; 1 - sliced cc mode */ - enum cx231xx_std_mode std_mode; /* 0 - Air; 1 - cable */ - - /*mode: digital=1 or analog=0*/ - u8 mode_tv; - - u8 USE_ISO; - struct cx231xx_tvnorm encodernorm; - struct cx231xx_tsport ts1, ts2; - struct cx2341x_mpeg_params mpeg_params; - struct video_device *v4l_device; - atomic_t v4l_reader_count; - u32 freq; - unsigned int input; - u32 cx23417_mailbox; - u32 __iomem *lmmio; - u8 __iomem *bmmio; -}; - -extern struct list_head cx231xx_devlist; - -#define cx25840_call(cx231xx, o, f, args...) \ - v4l2_subdev_call(cx231xx->sd_cx25840, o, f, ##args) -#define tuner_call(cx231xx, o, f, args...) \ - v4l2_subdev_call(cx231xx->sd_tuner, o, f, ##args) -#define call_all(dev, o, f, args...) \ - v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args) - -struct cx231xx_ops { - struct list_head next; - char *name; - int id; - int (*init) (struct cx231xx *); - int (*fini) (struct cx231xx *); -}; - -/* call back functions in dvb module */ -int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq); -int cx231xx_reset_analog_tuner(struct cx231xx *dev); - -/* Provided by cx231xx-i2c.c */ -void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c); -int cx231xx_i2c_register(struct cx231xx_i2c *bus); -int cx231xx_i2c_unregister(struct cx231xx_i2c *bus); - -/* Internal block control functions */ -int cx231xx_read_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr, - u8 saddr_len, u32 *data, u8 data_len, int master); -int cx231xx_write_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr, - u8 saddr_len, u32 data, u8 data_len, int master); -int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, - u16 saddr, u8 saddr_len, u32 *data, u8 data_len); -int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, - u16 saddr, u8 saddr_len, u32 data, u8 data_len); -int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size, - u16 register_address, u8 bit_start, u8 bit_end, - u32 value); -int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr, - u16 saddr, u32 mask, u32 value); -u32 cx231xx_set_field(u32 field_mask, u32 data); - -/*verve r/w*/ -void initGPIO(struct cx231xx *dev); -void uninitGPIO(struct cx231xx *dev); -/* afe related functions */ -int cx231xx_afe_init_super_block(struct cx231xx *dev, u32 ref_count); -int cx231xx_afe_init_channels(struct cx231xx *dev); -int cx231xx_afe_setup_AFE_for_baseband(struct cx231xx *dev); -int cx231xx_afe_set_input_mux(struct cx231xx *dev, u32 input_mux); -int cx231xx_afe_set_mode(struct cx231xx *dev, enum AFE_MODE mode); -int cx231xx_afe_update_power_control(struct cx231xx *dev, - enum AV_MODE avmode); -int cx231xx_afe_adjust_ref_count(struct cx231xx *dev, u32 video_input); - -/* i2s block related functions */ -int cx231xx_i2s_blk_initialize(struct cx231xx *dev); -int cx231xx_i2s_blk_update_power_control(struct cx231xx *dev, - enum AV_MODE avmode); -int cx231xx_i2s_blk_set_audio_input(struct cx231xx *dev, u8 audio_input); - -/* DIF related functions */ -int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, - u32 function_mode, u32 standard); -void cx231xx_set_Colibri_For_LowIF(struct cx231xx *dev, u32 if_freq, - u8 spectral_invert, u32 mode); -u32 cx231xx_Get_Colibri_CarrierOffset(u32 mode, u32 standerd); -void cx231xx_set_DIF_bandpass(struct cx231xx *dev, u32 if_freq, - u8 spectral_invert, u32 mode); -void cx231xx_Setup_AFE_for_LowIF(struct cx231xx *dev); -void reset_s5h1432_demod(struct cx231xx *dev); -void cx231xx_dump_HH_reg(struct cx231xx *dev); -void update_HH_register_after_set_DIF(struct cx231xx *dev); -void cx231xx_dump_SC_reg(struct cx231xx *dev); - - - -int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard); -int cx231xx_tuner_pre_channel_change(struct cx231xx *dev); -int cx231xx_tuner_post_channel_change(struct cx231xx *dev); - -/* video parser functions */ -u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size, - u32 *p_bytes_used); -u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf, - u32 *p_bytes_used); -int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 *p_buffer, u32 bytes_to_copy); -void cx231xx_reset_video_buffer(struct cx231xx *dev, - struct cx231xx_dmaqueue *dma_q); -u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q); -u32 cx231xx_copy_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 *p_line, u32 length, int field_number); -u32 cx231xx_get_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, - u8 sav_eav, u8 *p_buffer, u32 buffer_size); -void cx231xx_swab(u16 *from, u16 *to, u16 len); - -/* Provided by cx231xx-core.c */ - -u32 cx231xx_request_buffers(struct cx231xx *dev, u32 count); -void cx231xx_queue_unusedframes(struct cx231xx *dev); -void cx231xx_release_buffers(struct cx231xx *dev); - -/* read from control pipe */ -int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, - char *buf, int len); - -/* write to control pipe */ -int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, - char *buf, int len); -int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode); - -int cx231xx_send_vendor_cmd(struct cx231xx *dev, - struct VENDOR_REQUEST_IN *ven_req); -int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, - struct cx231xx_i2c_xfer_data *req_data); - -/* Gpio related functions */ -int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val, - u8 len, u8 request, u8 direction); -int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val); -int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val); -int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value); -int cx231xx_set_gpio_direction(struct cx231xx *dev, int pin_number, - int pin_value); - -int cx231xx_gpio_i2c_start(struct cx231xx *dev); -int cx231xx_gpio_i2c_end(struct cx231xx *dev); -int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data); -int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf); -int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev); -int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev); -int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev); - -int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len); -int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len); - -/* audio related functions */ -int cx231xx_set_audio_decoder_input(struct cx231xx *dev, - enum AUDIO_INPUT audio_input); - -int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type); -int cx231xx_set_video_alternate(struct cx231xx *dev); -int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt); -int is_fw_load(struct cx231xx *dev); -int cx231xx_check_fw(struct cx231xx *dev); -int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, - int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct cx231xx *dev, - struct urb *urb)); -int cx231xx_init_bulk(struct cx231xx *dev, int max_packets, - int num_bufs, int max_pkt_size, - int (*bulk_copy) (struct cx231xx *dev, - struct urb *urb)); -void cx231xx_stop_TS1(struct cx231xx *dev); -void cx231xx_start_TS1(struct cx231xx *dev); -void cx231xx_uninit_isoc(struct cx231xx *dev); -void cx231xx_uninit_bulk(struct cx231xx *dev); -int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode); -int cx231xx_unmute_audio(struct cx231xx *dev); -int cx231xx_ep5_bulkout(struct cx231xx *dev, u8 *firmware, u16 size); -void cx231xx_disable656(struct cx231xx *dev); -void cx231xx_enable656(struct cx231xx *dev); -int cx231xx_demod_reset(struct cx231xx *dev); -int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio); - -/* Device list functions */ -void cx231xx_release_resources(struct cx231xx *dev); -void cx231xx_release_analog_resources(struct cx231xx *dev); -int cx231xx_register_analog_devices(struct cx231xx *dev); -void cx231xx_remove_from_devlist(struct cx231xx *dev); -void cx231xx_add_into_devlist(struct cx231xx *dev); -void cx231xx_init_extension(struct cx231xx *dev); -void cx231xx_close_extension(struct cx231xx *dev); - -/* hardware init functions */ -int cx231xx_dev_init(struct cx231xx *dev); -void cx231xx_dev_uninit(struct cx231xx *dev); -void cx231xx_config_i2c(struct cx231xx *dev); -int cx231xx_config(struct cx231xx *dev); - -/* Stream control functions */ -int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask); -int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask); - -int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type); - -/* Power control functions */ -int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode); -int cx231xx_power_suspend(struct cx231xx *dev); - -/* chip specific control functions */ -int cx231xx_init_ctrl_pin_status(struct cx231xx *dev); -int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev, - u8 analog_or_digital); -int cx231xx_enable_i2c_port_3(struct cx231xx *dev, bool is_port_3); - -/* video audio decoder related functions */ -void video_mux(struct cx231xx *dev, int index); -int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input); -int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input); -int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev); -int cx231xx_set_audio_input(struct cx231xx *dev, u8 input); - -/* Provided by cx231xx-video.c */ -int cx231xx_register_extension(struct cx231xx_ops *dev); -void cx231xx_unregister_extension(struct cx231xx_ops *dev); -void cx231xx_init_extension(struct cx231xx *dev); -void cx231xx_close_extension(struct cx231xx *dev); - -/* Provided by cx231xx-cards.c */ -extern void cx231xx_pre_card_setup(struct cx231xx *dev); -extern void cx231xx_card_setup(struct cx231xx *dev); -extern struct cx231xx_board cx231xx_boards[]; -extern struct usb_device_id cx231xx_id_table[]; -extern const unsigned int cx231xx_bcount; -int cx231xx_tuner_callback(void *ptr, int component, int command, int arg); - -/* cx23885-417.c */ -extern int cx231xx_417_register(struct cx231xx *dev); -extern void cx231xx_417_unregister(struct cx231xx *dev); - -/* cx23885-input.c */ - -#if defined(CONFIG_VIDEO_CX231XX_RC) -int cx231xx_ir_init(struct cx231xx *dev); -void cx231xx_ir_exit(struct cx231xx *dev); -#else -#define cx231xx_ir_init(dev) (0) -#define cx231xx_ir_exit(dev) (0) -#endif - - -/* printk macros */ - -#define cx231xx_err(fmt, arg...) do {\ - printk(KERN_ERR fmt , ##arg); } while (0) - -#define cx231xx_errdev(fmt, arg...) do {\ - printk(KERN_ERR "%s: "fmt,\ - dev->name , ##arg); } while (0) - -#define cx231xx_info(fmt, arg...) do {\ - printk(KERN_INFO "%s: "fmt,\ - dev->name , ##arg); } while (0) -#define cx231xx_warn(fmt, arg...) do {\ - printk(KERN_WARNING "%s: "fmt,\ - dev->name , ##arg); } while (0) - -static inline unsigned int norm_maxw(struct cx231xx *dev) -{ - if (dev->board.max_range_640_480) - return 640; - else - return 720; -} - -static inline unsigned int norm_maxh(struct cx231xx *dev) -{ - if (dev->board.max_range_640_480) - return 480; - else - return (dev->norm & V4L2_STD_625_50) ? 576 : 480; -} -#endif diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig deleted file mode 100644 index 928ef0d0429f..000000000000 --- a/drivers/media/video/em28xx/Kconfig +++ /dev/null @@ -1,58 +0,0 @@ -config VIDEO_EM28XX - tristate "Empia EM28xx USB video capture support" - depends on VIDEO_DEV && I2C - select VIDEO_TUNER - select VIDEO_TVEEPROM - select VIDEOBUF_VMALLOC - select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO - select VIDEO_MT9V011 if VIDEO_HELPER_CHIPS_AUTO - - ---help--- - This is a video4linux driver for Empia 28xx based TV cards. - - To compile this driver as a module, choose M here: the - module will be called em28xx - -config VIDEO_EM28XX_ALSA - depends on VIDEO_EM28XX && SND - select SND_PCM - tristate "Empia EM28xx ALSA audio module" - ---help--- - This is an ALSA driver for some Empia 28xx based TV cards. - - This is not required for em2800/em2820/em2821 boards. However, - newer em28xx devices uses Vendor Class for audio, instead of - implementing the USB Audio Class. For those chips, this module - will enable digital audio. - - To compile this driver as a module, choose M here: the - module will be called em28xx-alsa - -config VIDEO_EM28XX_DVB - tristate "DVB/ATSC Support for em28xx based TV cards" - depends on VIDEO_EM28XX && DVB_CORE - select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select DVB_TDA10023 if !DVB_FE_CUSTOMISE - select DVB_S921 if !DVB_FE_CUSTOMISE - select DVB_DRXD if !DVB_FE_CUSTOMISE - select DVB_CXD2820R if !DVB_FE_CUSTOMISE - select DVB_DRXK if !DVB_FE_CUSTOMISE - select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE - select DVB_TDA10071 if !DVB_FE_CUSTOMISE - select DVB_A8293 if !DVB_FE_CUSTOMISE - select VIDEOBUF_DVB - ---help--- - This adds support for DVB cards based on the - Empiatech em28xx chips. - -config VIDEO_EM28XX_RC - tristate "EM28XX Remote Controller support" - depends on RC_CORE - depends on VIDEO_EM28XX - depends on !(RC_CORE=m && VIDEO_EM28XX=y) - default VIDEO_EM28XX - ---help--- - Enables Remote Controller support on em28xx driver. diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile deleted file mode 100644 index 65c7c29e4161..000000000000 --- a/drivers/media/video/em28xx/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -em28xx-y := em28xx-video.o em28xx-i2c.o em28xx-cards.o -em28xx-y += em28xx-core.o em28xx-vbi.o - -em28xx-alsa-objs := em28xx-audio.o -em28xx-rc-objs := em28xx-input.o - -obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o -obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o -obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o -obj-$(CONFIG_VIDEO_EM28XX_RC) += em28xx-rc.o - -ccflags-y += -Idrivers/media/video -ccflags-y += -Idrivers/media/tuners -ccflags-y += -Idrivers/media/dvb-core -ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c deleted file mode 100644 index 2fdb66ee44ab..000000000000 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ /dev/null @@ -1,751 +0,0 @@ -/* - * Empiatech em28x1 audio extension - * - * Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com> - * - * Copyright (C) 2007-2011 Mauro Carvalho Chehab <mchehab@redhat.com> - * - Port to work with the in-kernel driver - * - Cleanups, fixes, alsa-controls, etc. - * - * This driver is based on my previous au600 usb pstn audio driver - * and inherits all the copyrights - * - * 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 <linux/kernel.h> -#include <linux/usb.h> -#include <linux/init.h> -#include <linux/sound.h> -#include <linux/spinlock.h> -#include <linux/soundcard.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/proc_fs.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/info.h> -#include <sound/initval.h> -#include <sound/control.h> -#include <sound/tlv.h> -#include <sound/ac97_codec.h> -#include <media/v4l2-common.h> -#include "em28xx.h" - -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "activates debug info"); - -#define dprintk(fmt, arg...) do { \ - if (debug) \ - printk(KERN_INFO "em28xx-audio %s: " fmt, \ - __func__, ##arg); \ - } while (0) - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; - -static int em28xx_deinit_isoc_audio(struct em28xx *dev) -{ - int i; - - dprintk("Stopping isoc\n"); - for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { - if (!irqs_disabled()) - usb_kill_urb(dev->adev.urb[i]); - else - usb_unlink_urb(dev->adev.urb[i]); - - usb_free_urb(dev->adev.urb[i]); - dev->adev.urb[i] = NULL; - - kfree(dev->adev.transfer_buffer[i]); - dev->adev.transfer_buffer[i] = NULL; - } - - return 0; -} - -static void em28xx_audio_isocirq(struct urb *urb) -{ - struct em28xx *dev = urb->context; - int i; - unsigned int oldptr; - int period_elapsed = 0; - int status; - unsigned char *cp; - unsigned int stride; - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - - switch (urb->status) { - case 0: /* success */ - case -ETIMEDOUT: /* NAK */ - break; - case -ECONNRESET: /* kill */ - case -ENOENT: - case -ESHUTDOWN: - return; - default: /* error */ - dprintk("urb completition error %d.\n", urb->status); - break; - } - - if (atomic_read(&dev->stream_started) == 0) - return; - - if (dev->adev.capture_pcm_substream) { - substream = dev->adev.capture_pcm_substream; - runtime = substream->runtime; - stride = runtime->frame_bits >> 3; - - for (i = 0; i < urb->number_of_packets; i++) { - int length = - urb->iso_frame_desc[i].actual_length / stride; - cp = (unsigned char *)urb->transfer_buffer + - urb->iso_frame_desc[i].offset; - - if (!length) - continue; - - oldptr = dev->adev.hwptr_done_capture; - if (oldptr + length >= runtime->buffer_size) { - unsigned int cnt = - runtime->buffer_size - oldptr; - memcpy(runtime->dma_area + oldptr * stride, cp, - cnt * stride); - memcpy(runtime->dma_area, cp + cnt * stride, - length * stride - cnt * stride); - } else { - memcpy(runtime->dma_area + oldptr * stride, cp, - length * stride); - } - - snd_pcm_stream_lock(substream); - - dev->adev.hwptr_done_capture += length; - if (dev->adev.hwptr_done_capture >= - runtime->buffer_size) - dev->adev.hwptr_done_capture -= - runtime->buffer_size; - - dev->adev.capture_transfer_done += length; - if (dev->adev.capture_transfer_done >= - runtime->period_size) { - dev->adev.capture_transfer_done -= - runtime->period_size; - period_elapsed = 1; - } - - snd_pcm_stream_unlock(substream); - } - if (period_elapsed) - snd_pcm_period_elapsed(substream); - } - urb->status = 0; - - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status < 0) { - em28xx_errdev("resubmit of audio urb failed (error=%i)\n", - status); - } - return; -} - -static int em28xx_init_audio_isoc(struct em28xx *dev) -{ - int i, errCode; - const int sb_size = EM28XX_NUM_AUDIO_PACKETS * - EM28XX_AUDIO_MAX_PACKET_SIZE; - - dprintk("Starting isoc transfers\n"); - - for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { - struct urb *urb; - int j, k; - - dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC); - if (!dev->adev.transfer_buffer[i]) - return -ENOMEM; - - memset(dev->adev.transfer_buffer[i], 0x80, sb_size); - urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); - if (!urb) { - em28xx_errdev("usb_alloc_urb failed!\n"); - for (j = 0; j < i; j++) { - usb_free_urb(dev->adev.urb[j]); - kfree(dev->adev.transfer_buffer[j]); - } - return -ENOMEM; - } - - urb->dev = dev->udev; - urb->context = dev; - urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO); - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = dev->adev.transfer_buffer[i]; - urb->interval = 1; - urb->complete = em28xx_audio_isocirq; - urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS; - urb->transfer_buffer_length = sb_size; - - for (j = k = 0; j < EM28XX_NUM_AUDIO_PACKETS; - j++, k += EM28XX_AUDIO_MAX_PACKET_SIZE) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = - EM28XX_AUDIO_MAX_PACKET_SIZE; - } - dev->adev.urb[i] = urb; - } - - for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { - errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); - if (errCode) { - em28xx_errdev("submit of audio urb failed\n"); - em28xx_deinit_isoc_audio(dev); - atomic_set(&dev->stream_started, 0); - return errCode; - } - - } - - return 0; -} - -static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, - size_t size) -{ - struct snd_pcm_runtime *runtime = subs->runtime; - - dprintk("Allocating vbuffer\n"); - if (runtime->dma_area) { - if (runtime->dma_bytes > size) - return 0; - - vfree(runtime->dma_area); - } - runtime->dma_area = vmalloc(size); - if (!runtime->dma_area) - return -ENOMEM; - - runtime->dma_bytes = size; - - return 0; -} - -static struct snd_pcm_hardware snd_em28xx_hw_capture = { - .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_MMAP_VALID, - - .formats = SNDRV_PCM_FMTBIT_S16_LE, - - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT, - - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */ - .period_bytes_min = 64, /* 12544/2, */ - .period_bytes_max = 12544, - .periods_min = 2, - .periods_max = 98, /* 12544, */ -}; - -static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) -{ - struct em28xx *dev = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int ret = 0; - - dprintk("opening device and trying to acquire exclusive lock\n"); - - if (!dev) { - em28xx_err("BUG: em28xx can't find device struct." - " Can't proceed with open\n"); - return -ENODEV; - } - - runtime->hw = snd_em28xx_hw_capture; - if ((dev->alt == 0 || dev->audio_ifnum) && dev->adev.users == 0) { - if (dev->audio_ifnum) - dev->alt = 1; - else - dev->alt = 7; - - dprintk("changing alternate number on interface %d to %d\n", - dev->audio_ifnum, dev->alt); - usb_set_interface(dev->udev, dev->audio_ifnum, dev->alt); - - /* Sets volume, mute, etc */ - dev->mute = 0; - mutex_lock(&dev->lock); - ret = em28xx_audio_analog_set(dev); - if (ret < 0) - goto err; - - dev->adev.users++; - mutex_unlock(&dev->lock); - } - - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - dev->adev.capture_pcm_substream = substream; - - return 0; -err: - mutex_unlock(&dev->lock); - - em28xx_err("Error while configuring em28xx mixer\n"); - return ret; -} - -static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream) -{ - struct em28xx *dev = snd_pcm_substream_chip(substream); - - dprintk("closing device\n"); - - dev->mute = 1; - mutex_lock(&dev->lock); - dev->adev.users--; - if (atomic_read(&dev->stream_started) > 0) { - atomic_set(&dev->stream_started, 0); - schedule_work(&dev->wq_trigger); - } - - em28xx_audio_analog_set(dev); - if (substream->runtime->dma_area) { - dprintk("freeing\n"); - vfree(substream->runtime->dma_area); - substream->runtime->dma_area = NULL; - } - mutex_unlock(&dev->lock); - - return 0; -} - -static int snd_em28xx_hw_capture_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - int ret; - - dprintk("Setting capture parameters\n"); - - ret = snd_pcm_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); - if (ret < 0) - return ret; -#if 0 - /* TODO: set up em28xx audio chip to deliver the correct audio format, - current default is 48000hz multiplexed => 96000hz mono - which shouldn't matter since analogue TV only supports mono */ - unsigned int channels, rate, format; - - format = params_format(hw_params); - rate = params_rate(hw_params); - channels = params_channels(hw_params); -#endif - - return 0; -} - -static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream) -{ - struct em28xx *dev = snd_pcm_substream_chip(substream); - - dprintk("Stop capture, if needed\n"); - - if (atomic_read(&dev->stream_started) > 0) { - atomic_set(&dev->stream_started, 0); - schedule_work(&dev->wq_trigger); - } - - return 0; -} - -static int snd_em28xx_prepare(struct snd_pcm_substream *substream) -{ - struct em28xx *dev = snd_pcm_substream_chip(substream); - - dev->adev.hwptr_done_capture = 0; - dev->adev.capture_transfer_done = 0; - - return 0; -} - -static void audio_trigger(struct work_struct *work) -{ - struct em28xx *dev = container_of(work, struct em28xx, wq_trigger); - - if (atomic_read(&dev->stream_started)) { - dprintk("starting capture"); - em28xx_init_audio_isoc(dev); - } else { - dprintk("stopping capture"); - em28xx_deinit_isoc_audio(dev); - } -} - -static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct em28xx *dev = snd_pcm_substream_chip(substream); - int retval = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ - case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ - case SNDRV_PCM_TRIGGER_START: - atomic_set(&dev->stream_started, 1); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ - case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ - case SNDRV_PCM_TRIGGER_STOP: - atomic_set(&dev->stream_started, 0); - break; - default: - retval = -EINVAL; - } - schedule_work(&dev->wq_trigger); - return retval; -} - -static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream - *substream) -{ - unsigned long flags; - struct em28xx *dev; - snd_pcm_uframes_t hwptr_done; - - dev = snd_pcm_substream_chip(substream); - spin_lock_irqsave(&dev->adev.slock, flags); - hwptr_done = dev->adev.hwptr_done_capture; - spin_unlock_irqrestore(&dev->adev.slock, flags); - - return hwptr_done; -} - -static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, - unsigned long offset) -{ - void *pageptr = subs->runtime->dma_area + offset; - - return vmalloc_to_page(pageptr); -} - -/* - * AC97 volume control support - */ -static int em28xx_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 2; - info->value.integer.min = 0; - info->value.integer.max = 0x1f; - - return 0; -} - -static int em28xx_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct em28xx *dev = snd_kcontrol_chip(kcontrol); - u16 val = (0x1f - (value->value.integer.value[0] & 0x1f)) | - (0x1f - (value->value.integer.value[1] & 0x1f)) << 8; - int rc; - - mutex_lock(&dev->lock); - rc = em28xx_read_ac97(dev, kcontrol->private_value); - if (rc < 0) - goto err; - - val |= rc & 0x8000; /* Preserve the mute flag */ - - rc = em28xx_write_ac97(dev, kcontrol->private_value, val); - if (rc < 0) - goto err; - - dprintk("%sleft vol %d, right vol %d (0x%04x) to ac97 volume control 0x%04x\n", - (val & 0x8000) ? "muted " : "", - 0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f), - val, (int)kcontrol->private_value); - -err: - mutex_unlock(&dev->lock); - return rc; -} - -static int em28xx_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct em28xx *dev = snd_kcontrol_chip(kcontrol); - int val; - - mutex_lock(&dev->lock); - val = em28xx_read_ac97(dev, kcontrol->private_value); - mutex_unlock(&dev->lock); - if (val < 0) - return val; - - dprintk("%sleft vol %d, right vol %d (0x%04x) from ac97 volume control 0x%04x\n", - (val & 0x8000) ? "muted " : "", - 0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f), - val, (int)kcontrol->private_value); - - value->value.integer.value[0] = 0x1f - (val & 0x1f); - value->value.integer.value[1] = 0x1f - ((val << 8) & 0x1f); - - return 0; -} - -static int em28xx_vol_put_mute(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct em28xx *dev = snd_kcontrol_chip(kcontrol); - u16 val = value->value.integer.value[0]; - int rc; - - mutex_lock(&dev->lock); - rc = em28xx_read_ac97(dev, kcontrol->private_value); - if (rc < 0) - goto err; - - if (val) - rc &= 0x1f1f; - else - rc |= 0x8000; - - rc = em28xx_write_ac97(dev, kcontrol->private_value, rc); - if (rc < 0) - goto err; - - dprintk("%sleft vol %d, right vol %d (0x%04x) to ac97 volume control 0x%04x\n", - (val & 0x8000) ? "muted " : "", - 0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f), - val, (int)kcontrol->private_value); - -err: - mutex_unlock(&dev->lock); - return rc; -} - -static int em28xx_vol_get_mute(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct em28xx *dev = snd_kcontrol_chip(kcontrol); - int val; - - mutex_lock(&dev->lock); - val = em28xx_read_ac97(dev, kcontrol->private_value); - mutex_unlock(&dev->lock); - if (val < 0) - return val; - - if (val & 0x8000) - value->value.integer.value[0] = 0; - else - value->value.integer.value[0] = 1; - - dprintk("%sleft vol %d, right vol %d (0x%04x) from ac97 volume control 0x%04x\n", - (val & 0x8000) ? "muted " : "", - 0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f), - val, (int)kcontrol->private_value); - - return 0; -} - -static const DECLARE_TLV_DB_SCALE(em28xx_db_scale, -3450, 150, 0); - -static int em28xx_cvol_new(struct snd_card *card, struct em28xx *dev, - char *name, int id) -{ - int err; - char ctl_name[44]; - struct snd_kcontrol *kctl; - struct snd_kcontrol_new tmp; - - memset (&tmp, 0, sizeof(tmp)); - tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER, - tmp.private_value = id, - tmp.name = ctl_name, - - /* Add Mute Control */ - sprintf(ctl_name, "%s Switch", name); - tmp.get = em28xx_vol_get_mute; - tmp.put = em28xx_vol_put_mute; - tmp.info = snd_ctl_boolean_mono_info; - kctl = snd_ctl_new1(&tmp, dev); - err = snd_ctl_add(card, kctl); - if (err < 0) - return err; - dprintk("Added control %s for ac97 volume control 0x%04x\n", - ctl_name, id); - - memset (&tmp, 0, sizeof(tmp)); - tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER, - tmp.private_value = id, - tmp.name = ctl_name, - - /* Add Volume Control */ - sprintf(ctl_name, "%s Volume", name); - tmp.get = em28xx_vol_get; - tmp.put = em28xx_vol_put; - tmp.info = em28xx_vol_info; - tmp.tlv.p = em28xx_db_scale, - kctl = snd_ctl_new1(&tmp, dev); - err = snd_ctl_add(card, kctl); - if (err < 0) - return err; - dprintk("Added control %s for ac97 volume control 0x%04x\n", - ctl_name, id); - - return 0; -} - -/* - * register/unregister code and data - */ -static struct snd_pcm_ops snd_em28xx_pcm_capture = { - .open = snd_em28xx_capture_open, - .close = snd_em28xx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_em28xx_hw_capture_params, - .hw_free = snd_em28xx_hw_capture_free, - .prepare = snd_em28xx_prepare, - .trigger = snd_em28xx_capture_trigger, - .pointer = snd_em28xx_capture_pointer, - .page = snd_pcm_get_vmalloc_page, -}; - -static int em28xx_audio_init(struct em28xx *dev) -{ - struct em28xx_audio *adev = &dev->adev; - struct snd_pcm *pcm; - struct snd_card *card; - static int devnr; - int err; - - if (!dev->has_alsa_audio || dev->audio_ifnum < 0) { - /* This device does not support the extension (in this case - the device is expecting the snd-usb-audio module or - doesn't have analog audio support at all) */ - return 0; - } - - printk(KERN_INFO "em28xx-audio.c: probing for em28xx Audio Vendor Class\n"); - printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " - "Rechberger\n"); - printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2007-2011 Mauro Carvalho Chehab\n"); - - err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0, - &card); - if (err < 0) - return err; - - spin_lock_init(&adev->slock); - err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm); - if (err < 0) { - snd_card_free(card); - return err; - } - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_em28xx_pcm_capture); - pcm->info_flags = 0; - pcm->private_data = dev; - strcpy(pcm->name, "Empia 28xx Capture"); - - snd_card_set_dev(card, &dev->udev->dev); - strcpy(card->driver, "Em28xx-Audio"); - strcpy(card->shortname, "Em28xx Audio"); - strcpy(card->longname, "Empia Em28xx Audio"); - - INIT_WORK(&dev->wq_trigger, audio_trigger); - - if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { - em28xx_cvol_new(card, dev, "Video", AC97_VIDEO); - em28xx_cvol_new(card, dev, "Line In", AC97_LINE); - em28xx_cvol_new(card, dev, "Phone", AC97_PHONE); - em28xx_cvol_new(card, dev, "Microphone", AC97_MIC); - em28xx_cvol_new(card, dev, "CD", AC97_CD); - em28xx_cvol_new(card, dev, "AUX", AC97_AUX); - em28xx_cvol_new(card, dev, "PCM", AC97_PCM); - - em28xx_cvol_new(card, dev, "Master", AC97_MASTER); - em28xx_cvol_new(card, dev, "Line", AC97_HEADPHONE); - em28xx_cvol_new(card, dev, "Mono", AC97_MASTER_MONO); - em28xx_cvol_new(card, dev, "LFE", AC97_CENTER_LFE_MASTER); - em28xx_cvol_new(card, dev, "Surround", AC97_SURROUND_MASTER); - } - - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - adev->sndcard = card; - adev->udev = dev->udev; - - return 0; -} - -static int em28xx_audio_fini(struct em28xx *dev) -{ - if (dev == NULL) - return 0; - - if (dev->has_alsa_audio != 1) { - /* This device does not support the extension (in this case - the device is expecting the snd-usb-audio module or - doesn't have analog audio support at all) */ - return 0; - } - - if (dev->adev.sndcard) { - snd_card_free(dev->adev.sndcard); - dev->adev.sndcard = NULL; - } - - return 0; -} - -static struct em28xx_ops audio_ops = { - .id = EM28XX_AUDIO, - .name = "Em28xx Audio Extension", - .init = em28xx_audio_init, - .fini = em28xx_audio_fini, -}; - -static int __init em28xx_alsa_register(void) -{ - return em28xx_register_extension(&audio_ops); -} - -static void __exit em28xx_alsa_unregister(void) -{ - em28xx_unregister_extension(&audio_ops); -} - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Markus Rechberger <mrechberger@gmail.com>"); -MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); -MODULE_DESCRIPTION("Em28xx Audio driver"); - -module_init(em28xx_alsa_register); -module_exit(em28xx_alsa_unregister); diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c deleted file mode 100644 index ca62b9981380..000000000000 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ /dev/null @@ -1,3417 +0,0 @@ -/* - em28xx-cards.c - driver for Empia EM2800/EM2820/2840 USB - video capture devices - - Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> - Markus Rechberger <mrechberger@gmail.com> - Mauro Carvalho Chehab <mchehab@infradead.org> - Sascha Sommer <saschasommer@freenet.de> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/usb.h> -#include <media/tuner.h> -#include <media/msp3400.h> -#include <media/saa7115.h> -#include <media/tvp5150.h> -#include <media/tvaudio.h> -#include <media/mt9v011.h> -#include <media/i2c-addr.h> -#include <media/tveeprom.h> -#include <media/v4l2-common.h> -#include <media/v4l2-chip-ident.h> - -#include "em28xx.h" - -#define DRIVER_NAME "em28xx" - -static int tuner = -1; -module_param(tuner, int, 0444); -MODULE_PARM_DESC(tuner, "tuner type"); - -static unsigned int disable_ir; -module_param(disable_ir, int, 0444); -MODULE_PARM_DESC(disable_ir, "disable infrared remote support"); - -static unsigned int disable_usb_speed_check; -module_param(disable_usb_speed_check, int, 0444); -MODULE_PARM_DESC(disable_usb_speed_check, - "override min bandwidth requirement of 480M bps"); - -static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; -module_param_array(card, int, NULL, 0444); -MODULE_PARM_DESC(card, "card type"); - -/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS - 1 */ -static unsigned long em28xx_devused; - -struct em28xx_hash_table { - unsigned long hash; - unsigned int model; - unsigned int tuner; -}; - -static void em28xx_pre_card_setup(struct em28xx *dev); - -/* - * Reset sequences for analog/digital modes - */ - -/* Reset for the most [analog] boards */ -static struct em28xx_reg_seq default_analog[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -/* Reset for the most [digital] boards */ -static struct em28xx_reg_seq default_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -/* Board Hauppauge WinTV HVR 900 analog */ -static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { - {EM28XX_R08_GPIO, 0x2d, ~EM_GPIO_4, 10}, - {0x05, 0xff, 0x10, 10}, - { -1, -1, -1, -1}, -}; - -/* Board Hauppauge WinTV HVR 900 digital */ -static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { - {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x04, 0x0f, 10}, - {EM2880_R04_GPO, 0x0c, 0x0f, 10}, - { -1, -1, -1, -1}, -}; - -/* Board Hauppauge WinTV HVR 900 (R2) digital */ -static struct em28xx_reg_seq hauppauge_wintv_hvr_900R2_digital[] = { - {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x0c, 0x0f, 10}, - { -1, -1, -1, -1}, -}; - -/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */ -static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = { - {EM28XX_R08_GPIO, 0x69, ~EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */ - -/* Board - EM2870 Kworld 355u - Analog - No input analog */ - -/* Board - EM2882 Kworld 315U digital */ -static struct em28xx_reg_seq em2882_kworld_315u_digital[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM28XX_R08_GPIO, 0xfe, 0xff, 10}, - {EM2880_R04_GPO, 0x04, 0xff, 10}, - {EM2880_R04_GPO, 0x0c, 0xff, 10}, - {EM28XX_R08_GPIO, 0x7e, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq em2882_kworld_315u_tuner_gpio[] = { - {EM2880_R04_GPO, 0x08, 0xff, 10}, - {EM2880_R04_GPO, 0x0c, 0xff, 10}, - {EM2880_R04_GPO, 0x08, 0xff, 10}, - {EM2880_R04_GPO, 0x0c, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq kworld_330u_analog[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x00, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq kworld_330u_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x08, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -/* Evga inDtube - GPIO0 - Enable digital power (s5h1409) - low to enable - GPIO1 - Enable analog power (tvp5150/emp202) - low to enable - GPIO4 - xc3028 reset - GOP3 - s5h1409 reset - */ -static struct em28xx_reg_seq evga_indtube_analog[] = { - {EM28XX_R08_GPIO, 0x79, 0xff, 60}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq evga_indtube_digital[] = { - {EM28XX_R08_GPIO, 0x7a, 0xff, 1}, - {EM2880_R04_GPO, 0x04, 0xff, 10}, - {EM2880_R04_GPO, 0x0c, 0xff, 1}, - { -1, -1, -1, -1}, -}; - -/* - * KWorld PlusTV 340U and UB435-Q (ATSC) GPIOs map: - * EM_GPIO_0 - currently unknown - * EM_GPIO_1 - LED disable/enable (1 = off, 0 = on) - * EM_GPIO_2 - currently unknown - * EM_GPIO_3 - currently unknown - * EM_GPIO_4 - TDA18271HD/C1 tuner (1 = active, 0 = in reset) - * EM_GPIO_5 - LGDT3304 ATSC/QAM demod (1 = active, 0 = in reset) - * EM_GPIO_6 - currently unknown - * EM_GPIO_7 - currently unknown - */ -static struct em28xx_reg_seq kworld_a340_digital[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -/* Pinnacle Hybrid Pro eb1a:2881 */ -static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = { - {EM28XX_R08_GPIO, 0xfd, ~EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq pinnacle_hybrid_pro_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x04, 0xff, 100},/* zl10353 reset */ - {EM2880_R04_GPO, 0x0c, 0xff, 1}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_analog[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x00, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x08, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -/* eb1a:2868 Reddo DVB-C USB TV Box - GPIO4 - CU1216L NIM - Other GPIOs seems to be don't care. */ -static struct em28xx_reg_seq reddo_dvb_c_usb_box[] = { - {EM28XX_R08_GPIO, 0xfe, 0xff, 10}, - {EM28XX_R08_GPIO, 0xde, 0xff, 10}, - {EM28XX_R08_GPIO, 0xfe, 0xff, 10}, - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM28XX_R08_GPIO, 0x7f, 0xff, 10}, - {EM28XX_R08_GPIO, 0x6f, 0xff, 10}, - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {-1, -1, -1, -1}, -}; - -/* Callback for the most boards */ -static struct em28xx_reg_seq default_tuner_gpio[] = { - {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, - {EM28XX_R08_GPIO, 0, EM_GPIO_4, 10}, - {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, - { -1, -1, -1, -1}, -}; - -/* Mute/unmute */ -static struct em28xx_reg_seq compro_unmute_tv_gpio[] = { - {EM28XX_R08_GPIO, 5, 7, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq compro_unmute_svid_gpio[] = { - {EM28XX_R08_GPIO, 4, 7, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq compro_mute_gpio[] = { - {EM28XX_R08_GPIO, 6, 7, 10}, - { -1, -1, -1, -1}, -}; - -/* Terratec AV350 */ -static struct em28xx_reg_seq terratec_av350_mute_gpio[] = { - {EM28XX_R08_GPIO, 0xff, 0x7f, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq silvercrest_reg_seq[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM28XX_R08_GPIO, 0x01, 0xf7, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq vc211a_enable[] = { - {EM28XX_R08_GPIO, 0xff, 0x07, 10}, - {EM28XX_R08_GPIO, 0xff, 0x0f, 10}, - {EM28XX_R08_GPIO, 0xff, 0x0b, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq dikom_dk300_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, - {EM2880_R04_GPO, 0x08, 0xff, 10}, - { -1, -1, -1, -1}, -}; - - -/* Reset for the most [digital] boards */ -static struct em28xx_reg_seq leadership_digital[] = { - {EM2874_R80_GPIO, 0x70, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq leadership_reset[] = { - {EM2874_R80_GPIO, 0xf0, 0xff, 10}, - {EM2874_R80_GPIO, 0xb0, 0xff, 10}, - {EM2874_R80_GPIO, 0xf0, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -/* 2013:024f PCTV nanoStick T2 290e - * GPIO_6 - demod reset - * GPIO_7 - LED - */ -static struct em28xx_reg_seq pctv_290e[] = { - {EM2874_R80_GPIO, 0x00, 0xff, 80}, - {EM2874_R80_GPIO, 0x40, 0xff, 80}, /* GPIO_6 = 1 */ - {EM2874_R80_GPIO, 0xc0, 0xff, 80}, /* GPIO_7 = 1 */ - {-1, -1, -1, -1}, -}; - -#if 0 -static struct em28xx_reg_seq terratec_h5_gpio[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, - {EM2874_R80_GPIO, 0xf2, 0xff, 50}, - {EM2874_R80_GPIO, 0xf6, 0xff, 50}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq terratec_h5_digital[] = { - {EM2874_R80_GPIO, 0xf6, 0xff, 10}, - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, - {EM2874_R80_GPIO, 0xa6, 0xff, 10}, - { -1, -1, -1, -1}, -}; -#endif - -/* 2013:024f PCTV DVB-S2 Stick 460e - * GPIO_0 - POWER_ON - * GPIO_1 - BOOST - * GPIO_2 - VUV_LNB (red LED) - * GPIO_3 - EXT_12V - * GPIO_4 - INT_DEM (DEMOD GPIO_0) - * GPIO_5 - INT_LNB - * GPIO_6 - RESET_DEM - * GPIO_7 - LED (green LED) - */ -static struct em28xx_reg_seq pctv_460e[] = { - {EM2874_R80_GPIO, 0x01, 0xff, 50}, - {0x0d, 0xff, 0xff, 50}, - {EM2874_R80_GPIO, 0x41, 0xff, 50}, /* GPIO_6=1 */ - {0x0d, 0x42, 0xff, 50}, - {EM2874_R80_GPIO, 0x61, 0xff, 50}, /* GPIO_5=1 */ - { -1, -1, -1, -1}, -}; - -#if 0 -static struct em28xx_reg_seq hauppauge_930c_gpio[] = { - {EM2874_R80_GPIO, 0x6f, 0xff, 10}, - {EM2874_R80_GPIO, 0x4f, 0xff, 10}, /* xc5000 reset */ - {EM2874_R80_GPIO, 0x6f, 0xff, 10}, - {EM2874_R80_GPIO, 0x4f, 0xff, 10}, - { -1, -1, -1, -1}, -}; - -static struct em28xx_reg_seq hauppauge_930c_digital[] = { - {EM2874_R80_GPIO, 0xf6, 0xff, 10}, - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, - {EM2874_R80_GPIO, 0xa6, 0xff, 10}, - { -1, -1, -1, -1}, -}; -#endif - -/* 1b80:e425 MaxMedia UB425-TC - * GPIO_6 - demod reset, 0=active - * GPIO_7 - LED, 0=active - */ -static struct em28xx_reg_seq maxmedia_ub425_tc[] = { - {EM2874_R80_GPIO, 0x83, 0xff, 100}, - {EM2874_R80_GPIO, 0xc3, 0xff, 100}, /* GPIO_6 = 1 */ - {EM2874_R80_GPIO, 0x43, 0xff, 000}, /* GPIO_7 = 0 */ - {-1, -1, -1, -1}, -}; - -/* 2304:0242 PCTV QuatroStick (510e) - * GPIO_2: decoder reset, 0=active - * GPIO_4: decoder suspend, 0=active - * GPIO_6: demod reset, 0=active - * GPIO_7: LED, 1=active - */ -static struct em28xx_reg_seq pctv_510e[] = { - {EM2874_R80_GPIO, 0x10, 0xff, 100}, - {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ - {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ - { -1, -1, -1, -1}, -}; - -/* 2013:0251 PCTV QuatroStick nano (520e) - * GPIO_2: decoder reset, 0=active - * GPIO_4: decoder suspend, 0=active - * GPIO_6: demod reset, 0=active - * GPIO_7: LED, 1=active - */ -static struct em28xx_reg_seq pctv_520e[] = { - {EM2874_R80_GPIO, 0x10, 0xff, 100}, - {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ - {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ - {EM2874_R80_GPIO, 0xd4, 0xff, 000}, /* GPIO_7 = 1 */ - { -1, -1, -1, -1}, -}; - -/* - * Board definitions - */ -struct em28xx_board em28xx_boards[] = { - [EM2750_BOARD_UNKNOWN] = { - .name = "EM2710/EM2750/EM2751 webcam grabber", - .xclk = EM28XX_XCLK_FREQUENCY_20MHZ, - .tuner_type = TUNER_ABSENT, - .is_webcam = 1, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = silvercrest_reg_seq, - } }, - }, - [EM2800_BOARD_UNKNOWN] = { - .name = "Unknown EM2800 video grabber", - .is_em2800 = 1, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .tuner_type = TUNER_ABSENT, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_UNKNOWN] = { - .name = "Unknown EM2750/28xx video grabber", - .tuner_type = TUNER_ABSENT, - .is_webcam = 1, /* To enable sensor probe */ - }, - [EM2750_BOARD_DLCW_130] = { - /* Beijing Huaqi Information Digital Technology Co., Ltd */ - .name = "Huaqi DLCW-130", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, - .tuner_type = TUNER_ABSENT, - .is_webcam = 1, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, - .amux = EM28XX_AMUX_VIDEO, - } }, - }, - [EM2820_BOARD_KWORLD_PVRTV2800RF] = { - .name = "Kworld PVR TV 2800 RF", - .tuner_type = TUNER_TEMIC_PAL, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_GADMEI_TVR200] = { - .name = "Gadmei TVR200", - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_TERRATEC_CINERGY_250] = { - .name = "Terratec Cinergy 250 USB", - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .has_ir_i2c = 1, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_PINNACLE_USB_2] = { - .name = "Pinnacle PCTV USB 2", - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .has_ir_i2c = 1, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_HAUPPAUGE_WINTV_USB_2] = { - .name = "Hauppauge WinTV USB 2", - .tuner_type = TUNER_PHILIPS_FM1236_MK3, - .tda9887_conf = TDA9887_PRESENT | - TDA9887_PORT1_ACTIVE | - TDA9887_PORT2_ACTIVE, - .decoder = EM28XX_TVP5150, - .has_msp34xx = 1, - .has_ir_i2c = 1, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = MSP_INPUT_DEFAULT, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, - MSP_DSP_IN_SCART, MSP_DSP_IN_SCART), - } }, - }, - [EM2820_BOARD_DLINK_USB_TV] = { - .name = "D-Link DUB-T210 TV Tuner", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_HERCULES_SMART_TV_USB2] = { - .name = "Hercules Smart TV USB 2.0", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_PINNACLE_USB_2_FM1216ME] = { - .name = "Pinnacle PCTV USB 2 (Philips FM1216ME)", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_GADMEI_UTV310] = { - .name = "Gadmei UTV310", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_TNF_5335MF, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE] = { - .name = "Leadtek Winfast USB II Deluxe", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .has_ir_i2c = 1, - .tvaudio_addr = 0x58, - .tda9887_conf = TDA9887_PRESENT | - TDA9887_PORT2_ACTIVE | - TDA9887_QSS, - .decoder = EM28XX_SAA711X, - .adecoder = EM28XX_TVAUDIO, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE4, - .amux = EM28XX_AMUX_AUX, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE5, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - .radio = { - .type = EM28XX_RADIO, - .amux = EM28XX_AMUX_AUX, - } - }, - [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = { - .name = "Videology 20K14XUSB USB2.0", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_ABSENT, - .is_webcam = 1, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, - .amux = EM28XX_AMUX_VIDEO, - } }, - }, - [EM2820_BOARD_SILVERCREST_WEBCAM] = { - .name = "Silvercrest Webcam 1.3mpix", - .tuner_type = TUNER_ABSENT, - .is_webcam = 1, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = silvercrest_reg_seq, - } }, - }, - [EM2821_BOARD_SUPERCOMP_USB_2] = { - .name = "Supercomp USB 2.0 TV", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_PHILIPS_FM1236_MK3, - .tda9887_conf = TDA9887_PRESENT | - TDA9887_PORT1_ACTIVE | - TDA9887_PORT2_ACTIVE, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2821_BOARD_USBGEAR_VD204] = { - .name = "Usbgear VD204v9", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_ABSENT, /* Capture only device */ - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2860_BOARD_NETGMBH_CAM] = { - /* Beijing Huaqi Information Digital Technology Co., Ltd */ - .name = "NetGMBH Cam", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_ABSENT, - .is_webcam = 1, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = 0, - .amux = EM28XX_AMUX_VIDEO, - } }, - }, - [EM2860_BOARD_TYPHOON_DVD_MAKER] = { - .name = "Typhoon DVD Maker", - .decoder = EM28XX_SAA711X, - .tuner_type = TUNER_ABSENT, /* Capture only device */ - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2860_BOARD_GADMEI_UTV330] = { - .name = "Gadmei UTV330", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_TNF_5335MF, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2861_BOARD_GADMEI_UTV330PLUS] = { - .name = "Gadmei UTV330+", - .tuner_type = TUNER_TNF_5335MF, - .tda9887_conf = TDA9887_PRESENT, - .ir_codes = RC_MAP_GADMEI_RM008Z, - .decoder = EM28XX_SAA711X, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2860_BOARD_TERRATEC_HYBRID_XS] = { - .name = "Terratec Cinergy A Hybrid XS", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2861_BOARD_KWORLD_PVRTV_300U] = { - .name = "KWorld PVRTV 300U", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2861_BOARD_YAKUMO_MOVIE_MIXER] = { - .name = "Yakumo MovieMixer", - .tuner_type = TUNER_ABSENT, /* Capture only device */ - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2860_BOARD_TVP5150_REFERENCE_DESIGN] = { - .name = "EM2860/TVP5150 Reference Design", - .tuner_type = TUNER_ABSENT, /* Capture only device */ - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2861_BOARD_PLEXTOR_PX_TV100U] = { - .name = "Plextor ConvertX PX-TV100U", - .tuner_type = TUNER_TNF_5335MF, - .xclk = EM28XX_XCLK_I2S_MSB_TIMING | - EM28XX_XCLK_FREQUENCY_12MHZ, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_TVP5150, - .has_msp34xx = 1, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = pinnacle_hybrid_pro_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = pinnacle_hybrid_pro_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = pinnacle_hybrid_pro_analog, - } }, - }, - - /* Those boards with em2870 are DVB Only*/ - - [EM2870_BOARD_TERRATEC_XS] = { - .name = "Terratec Cinergy T XS", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - }, - [EM2870_BOARD_TERRATEC_XS_MT2060] = { - .name = "Terratec Cinergy T XS (MT2060)", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_ABSENT, /* MT2060 */ - }, - [EM2870_BOARD_KWORLD_350U] = { - .name = "Kworld 350 U DVB-T", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - }, - [EM2870_BOARD_KWORLD_355U] = { - .name = "Kworld 355 U DVB-T", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_ABSENT, - .tuner_gpio = default_tuner_gpio, - .has_dvb = 1, - .dvb_gpio = default_digital, - }, - [EM2870_BOARD_PINNACLE_PCTV_DVB] = { - .name = "Pinnacle PCTV DVB-T", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_ABSENT, /* MT2060 */ - /* djh - I have serious doubts this is right... */ - .xclk = EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_10MHZ, - }, - [EM2870_BOARD_COMPRO_VIDEOMATE] = { - .name = "Compro, VideoMate U3", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_ABSENT, /* MT2060 */ - }, - - [EM2880_BOARD_TERRATEC_HYBRID_XS_FR] = { - .name = "Terratec Hybrid XS Secam", - .has_msp34xx = 1, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .has_dvb = 1, - .dvb_gpio = terratec_cinergy_USB_XS_FR_digital, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = terratec_cinergy_USB_XS_FR_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = terratec_cinergy_USB_XS_FR_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = terratec_cinergy_USB_XS_FR_analog, - } }, - }, - [EM2884_BOARD_TERRATEC_H5] = { - .name = "Terratec Cinergy H5", - .has_dvb = 1, -#if 0 - .tuner_type = TUNER_PHILIPS_TDA8290, - .tuner_addr = 0x41, - .dvb_gpio = terratec_h5_digital, /* FIXME: probably wrong */ - .tuner_gpio = terratec_h5_gpio, -#else - .tuner_type = TUNER_ABSENT, -#endif - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_400_KHZ, - }, - [EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C] = { - .name = "Hauppauge WinTV HVR 930C", - .has_dvb = 1, -#if 0 /* FIXME: Add analog support */ - .tuner_type = TUNER_XC5000, - .tuner_addr = 0x41, - .dvb_gpio = hauppauge_930c_digital, - .tuner_gpio = hauppauge_930c_gpio, -#else - .tuner_type = TUNER_ABSENT, -#endif - .ir_codes = RC_MAP_HAUPPAUGE, - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_400_KHZ, - }, - [EM2884_BOARD_CINERGY_HTC_STICK] = { - .name = "Terratec Cinergy HTC Stick", - .has_dvb = 1, - .ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS, - .tuner_type = TUNER_ABSENT, - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_400_KHZ, - }, - [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = { - .name = "Hauppauge WinTV HVR 900", - .tda9887_conf = TDA9887_PRESENT, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = RC_MAP_HAUPPAUGE, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2] = { - .name = "Hauppauge WinTV HVR 900 (R2)", - .tda9887_conf = TDA9887_PRESENT, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900R2_digital, - .ir_codes = RC_MAP_HAUPPAUGE, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850] = { - .name = "Hauppauge WinTV HVR 850", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = RC_MAP_HAUPPAUGE, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950] = { - .name = "Hauppauge WinTV HVR 950", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = RC_MAP_HAUPPAUGE, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2880_BOARD_PINNACLE_PCTV_HD_PRO] = { - .name = "Pinnacle PCTV HD Pro Stick", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = RC_MAP_PINNACLE_PCTV_HD, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600] = { - .name = "AMD ATI TV Wonder HD 600", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = RC_MAP_ATI_TV_WONDER_HD_600, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2880_BOARD_TERRATEC_HYBRID_XS] = { - .name = "Terratec Hybrid XS", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .has_dvb = 1, - .dvb_gpio = default_digital, - .ir_codes = RC_MAP_TERRATEC_CINERGY_XS, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = default_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, - } }, - }, - /* maybe there's a reason behind it why Terratec sells the Hybrid XS - as Prodigy XS with a different PID, let's keep it separated for now - maybe we'll need it lateron */ - [EM2880_BOARD_TERRATEC_PRODIGY_XS] = { - .name = "Terratec Prodigy XS", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2820_BOARD_MSI_VOX_USB_2] = { - .name = "MSI VOX USB 2.0", - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .tda9887_conf = TDA9887_PRESENT | - TDA9887_PORT1_ACTIVE | - TDA9887_PORT2_ACTIVE, - .max_range_640_480 = 1, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE4, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2800_BOARD_TERRATEC_CINERGY_200] = { - .name = "Terratec Cinergy 200 USB", - .is_em2800 = 1, - .has_ir_i2c = 1, - .tuner_type = TUNER_LG_TALN, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2800_BOARD_GRABBEEX_USB2800] = { - .name = "eMPIA Technology, Inc. GrabBeeX+ Video Encoder", - .is_em2800 = 1, - .decoder = EM28XX_SAA711X, - .tuner_type = TUNER_ABSENT, /* capture only board */ - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2800_BOARD_VC211A] = { - .name = "Actionmaster/LinXcel/Digitus VC211A", - .is_em2800 = 1, - .tuner_type = TUNER_ABSENT, /* Capture-only board */ - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = vc211a_enable, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = vc211a_enable, - } }, - }, - [EM2800_BOARD_LEADTEK_WINFAST_USBII] = { - .name = "Leadtek Winfast USB II", - .is_em2800 = 1, - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2800_BOARD_KWORLD_USB2800] = { - .name = "Kworld USB2800", - .is_em2800 = 1, - .tuner_type = TUNER_PHILIPS_FCV1236D, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_PINNACLE_DVC_90] = { - .name = "Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker " - "/ Kworld DVD Maker 2 / Plextor ConvertX PX-AV100U", - .tuner_type = TUNER_ABSENT, /* capture only board */ - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2800_BOARD_VGEAR_POCKETTV] = { - .name = "V-Gear PocketTV", - .is_em2800 = 1, - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2] = { - .name = "Pixelview PlayTV Box 4 USB 2.0", - .tda9887_conf = TDA9887_PRESENT, - .tuner_type = TUNER_YMEC_TVF_5533MF, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - .aout = EM28XX_AOUT_MONO | /* I2S */ - EM28XX_AOUT_MASTER, /* Line out pin */ - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_PROLINK_PLAYTV_USB2] = { - .name = "SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0", - .has_snapshot_button = 1, - .tda9887_conf = TDA9887_PRESENT, - .tuner_type = TUNER_YMEC_TVF_5533MF, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - .aout = EM28XX_AOUT_MONO | /* I2S */ - EM28XX_AOUT_MASTER, /* Line out pin */ - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2860_BOARD_SAA711X_REFERENCE_DESIGN] = { - .name = "EM2860/SAA711X Reference Design", - .has_snapshot_button = 1, - .tuner_type = TUNER_ABSENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - } }, - }, - - [EM2874_BOARD_LEADERSHIP_ISDBT] = { - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ, - .xclk = EM28XX_XCLK_FREQUENCY_10MHZ, - .name = "EM2874 Leadership ISDBT", - .tuner_type = TUNER_ABSENT, - .tuner_gpio = leadership_reset, - .dvb_gpio = leadership_digital, - .has_dvb = 1, - }, - - [EM2880_BOARD_MSI_DIGIVOX_AD] = { - .name = "MSI DigiVox A/D", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = em2880_msi_digivox_ad_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = em2880_msi_digivox_ad_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = em2880_msi_digivox_ad_analog, - } }, - }, - [EM2880_BOARD_MSI_DIGIVOX_AD_II] = { - .name = "MSI DigiVox A/D II", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = em2880_msi_digivox_ad_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = em2880_msi_digivox_ad_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = em2880_msi_digivox_ad_analog, - } }, - }, - [EM2880_BOARD_KWORLD_DVB_305U] = { - .name = "KWorld DVB-T 305U", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2880_BOARD_KWORLD_DVB_310U] = { - .name = "KWorld DVB-T 310U", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .has_dvb = 1, - .dvb_gpio = default_digital, - .mts_firmware = 1, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = default_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, - }, { /* S-video has not been tested yet */ - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, - } }, - }, - [EM2882_BOARD_KWORLD_ATSC_315U] = { - .name = "KWorld ATSC 315U HDTV TV Box", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_THOMSON_DTT761X, - .tuner_gpio = em2882_kworld_315u_tuner_gpio, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_SAA711X, - .has_dvb = 1, - .dvb_gpio = em2882_kworld_315u_digital, - .ir_codes = RC_MAP_KWORLD_315U, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, - .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE, - /* Analog mode - still not ready */ - /*.input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = SAA7115_COMPOSITE2, - .amux = EM28XX_AMUX_VIDEO, - .gpio = em2882_kworld_315u_analog, - .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = em2882_kworld_315u_analog1, - .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = em2882_kworld_315u_analog1, - .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, - } }, */ - }, - [EM2880_BOARD_EMPIRE_DUAL_TV] = { - .name = "Empire dual TV", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .has_dvb = 1, - .dvb_gpio = default_digital, - .mts_firmware = 1, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = default_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, - } }, - }, - [EM2881_BOARD_DNT_DA2_HYBRID] = { - .name = "DNT DA2 Hybrid", - .valid = EM28XX_BOARD_NOT_VALIDATED, - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = default_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = default_analog, - } }, - }, - [EM2881_BOARD_PINNACLE_HYBRID_PRO] = { - .name = "Pinnacle Hybrid Pro", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .has_dvb = 1, - .dvb_gpio = pinnacle_hybrid_pro_digital, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = pinnacle_hybrid_pro_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = pinnacle_hybrid_pro_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = pinnacle_hybrid_pro_analog, - } }, - }, - [EM2882_BOARD_PINNACLE_HYBRID_PRO_330E] = { - .name = "Pinnacle Hybrid Pro (330e)", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900R2_digital, - .ir_codes = RC_MAP_PINNACLE_PCTV_HD, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2882_BOARD_KWORLD_VS_DVBT] = { - .name = "Kworld VS-DVB-T 323UR", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = kworld_330u_digital, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ - .ir_codes = RC_MAP_KWORLD_315U, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2882_BOARD_TERRATEC_HYBRID_XS] = { - .name = "Terratec Cinnergy Hybrid T USB XS (em2882)", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, - .decoder = EM28XX_TVP5150, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = RC_MAP_TERRATEC_CINERGY_XS, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, - } }, - }, - [EM2882_BOARD_DIKOM_DK300] = { - .name = "Dikom DK300", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = dikom_dk300_digital, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = default_analog, - } }, - }, - [EM2883_BOARD_KWORLD_HYBRID_330U] = { - .name = "Kworld PlusTV HD Hybrid 330", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = kworld_330u_digital, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, - .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_EEPROM_ON_BOARD | - EM28XX_I2C_EEPROM_KEY_VALID, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = kworld_330u_analog, - .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = kworld_330u_analog, - .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = kworld_330u_analog, - } }, - }, - [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = { - .name = "Compro VideoMate ForYou/Stereo", - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .tvaudio_addr = 0xb0, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_TVP5150, - .adecoder = EM28XX_TVAUDIO, - .mute_gpio = compro_mute_gpio, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = compro_unmute_tv_gpio, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = compro_unmute_svid_gpio, - } }, - }, - [EM2860_BOARD_KAIOMY_TVNPC_U2] = { - .name = "Kaiomy TVnPC U2", - .vchannels = 3, - .tuner_type = TUNER_XC2028, - .tuner_addr = 0x61, - .mts_firmware = 1, - .decoder = EM28XX_TVP5150, - .tuner_gpio = default_tuner_gpio, - .ir_codes = RC_MAP_KAIOMY, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - } }, - .radio = { - .type = EM28XX_RADIO, - .amux = EM28XX_AMUX_LINE_IN, - } - }, - [EM2860_BOARD_EASYCAP] = { - .name = "Easy Cap Capture DC-60", - .vchannels = 2, - .tuner_type = TUNER_ABSENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2820_BOARD_IODATA_GVMVP_SZ] = { - .name = "IO-DATA GV-MVP/SZ", - .tuner_type = TUNER_PHILIPS_FM1236_MK3, - .tuner_gpio = default_tuner_gpio, - .tda9887_conf = TDA9887_PRESENT, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - }, { /* Composite has not been tested yet */ - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_VIDEO, - }, { /* S-video has not been tested yet */ - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_VIDEO, - } }, - }, - [EM2860_BOARD_TERRATEC_GRABBY] = { - .name = "Terratec Grabby", - .vchannels = 2, - .tuner_type = TUNER_ABSENT, - .decoder = EM28XX_SAA711X, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - [EM2860_BOARD_TERRATEC_AV350] = { - .name = "Terratec AV350", - .vchannels = 2, - .tuner_type = TUNER_ABSENT, - .decoder = EM28XX_TVP5150, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, - .mute_gpio = terratec_av350_mute_gpio, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AUDIO_SRC_LINE, - .gpio = terratec_av350_unmute_gpio, - - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AUDIO_SRC_LINE, - .gpio = terratec_av350_unmute_gpio, - } }, - }, - - [EM2860_BOARD_ELGATO_VIDEO_CAPTURE] = { - .name = "Elgato Video Capture", - .decoder = EM28XX_SAA711X, - .tuner_type = TUNER_ABSENT, /* Capture only device */ - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - - [EM2882_BOARD_EVGA_INDTUBE] = { - .name = "Evga inDtube", - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .decoder = EM28XX_TVP5150, - .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = evga_indtube_digital, - .ir_codes = RC_MAP_EVGA_INDTUBE, - .input = { { - .type = EM28XX_VMUX_TELEVISION, - .vmux = TVP5150_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO, - .gpio = evga_indtube_analog, - }, { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = evga_indtube_analog, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AMUX_LINE_IN, - .gpio = evga_indtube_analog, - } }, - }, - /* eb1a:2868 Empia EM2870 + Philips CU1216L NIM (Philips TDA10023 + - Infineon TUA6034) */ - [EM2870_BOARD_REDDO_DVB_C_USB_BOX] = { - .name = "Reddo DVB-C USB TV Box", - .tuner_type = TUNER_ABSENT, - .tuner_gpio = reddo_dvb_c_usb_box, - .has_dvb = 1, - }, - /* 1b80:a340 - Empia EM2870, NXP TDA18271HD and LG DT3304, sold - * initially as the KWorld PlusTV 340U, then as the UB435-Q. - * Early variants have a TDA18271HD/C1, later ones a TDA18271HD/C2 */ - [EM2870_BOARD_KWORLD_A340] = { - .name = "KWorld PlusTV 340U or UB435-Q (ATSC)", - .tuner_type = TUNER_ABSENT, /* Digital-only TDA18271HD */ - .has_dvb = 1, - .dvb_gpio = kworld_a340_digital, - .tuner_gpio = default_tuner_gpio, - }, - /* 2013:024f PCTV nanoStick T2 290e. - * Empia EM28174, Sony CXD2820R and NXP TDA18271HD/C2 */ - [EM28174_BOARD_PCTV_290E] = { - .name = "PCTV nanoStick T2 290e", - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ, - .tuner_type = TUNER_ABSENT, - .tuner_gpio = pctv_290e, - .has_dvb = 1, - .ir_codes = RC_MAP_PINNACLE_PCTV_HD, - }, - /* 2013:024f PCTV DVB-S2 Stick 460e - * Empia EM28174, NXP TDA10071, Conexant CX24118A and Allegro A8293 */ - [EM28174_BOARD_PCTV_460E] = { - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ, - .name = "PCTV DVB-S2 Stick (460e)", - .tuner_type = TUNER_ABSENT, - .tuner_gpio = pctv_460e, - .has_dvb = 1, - .ir_codes = RC_MAP_PINNACLE_PCTV_HD, - }, - /* eb1a:5006 Honestech VIDBOX NW03 - * Empia EM2860, Philips SAA7113, Empia EMP202, No Tuner */ - [EM2860_BOARD_HT_VIDBOX_NW03] = { - .name = "Honestech Vidbox NW03", - .tuner_type = TUNER_ABSENT, - .decoder = EM28XX_SAA711X, - .input = { { - .type = EM28XX_VMUX_COMPOSITE1, - .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_LINE_IN, - }, { - .type = EM28XX_VMUX_SVIDEO, - .vmux = SAA7115_SVIDEO3, /* S-VIDEO needs confirming */ - .amux = EM28XX_AMUX_LINE_IN, - } }, - }, - /* 1b80:e425 MaxMedia UB425-TC - * Empia EM2874B + Micronas DRX 3913KA2 + NXP TDA18271HDC2 */ - [EM2874_BOARD_MAXMEDIA_UB425_TC] = { - .name = "MaxMedia UB425-TC", - .tuner_type = TUNER_ABSENT, - .tuner_gpio = maxmedia_ub425_tc, - .has_dvb = 1, - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_400_KHZ, - }, - /* 2304:0242 PCTV QuatroStick (510e) - * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */ - [EM2884_BOARD_PCTV_510E] = { - .name = "PCTV QuatroStick (510e)", - .tuner_type = TUNER_ABSENT, - .tuner_gpio = pctv_510e, - .has_dvb = 1, - .ir_codes = RC_MAP_PINNACLE_PCTV_HD, - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_400_KHZ, - }, - /* 2013:0251 PCTV QuatroStick nano (520e) - * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */ - [EM2884_BOARD_PCTV_520E] = { - .name = "PCTV QuatroStick nano (520e)", - .tuner_type = TUNER_ABSENT, - .tuner_gpio = pctv_520e, - .has_dvb = 1, - .ir_codes = RC_MAP_PINNACLE_PCTV_HD, - .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | - EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_400_KHZ, - }, -}; -const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); - -/* table of devices that work with this driver */ -struct usb_device_id em28xx_id_table[] = { - { USB_DEVICE(0xeb1a, 0x2750), - .driver_info = EM2750_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2751), - .driver_info = EM2750_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2800), - .driver_info = EM2800_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2710), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2820), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2821), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2860), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2861), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2862), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2863), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2870), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2881), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2883), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2868), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0x2875), - .driver_info = EM2820_BOARD_UNKNOWN }, - { USB_DEVICE(0xeb1a, 0xe300), - .driver_info = EM2861_BOARD_KWORLD_PVRTV_300U }, - { USB_DEVICE(0xeb1a, 0xe303), - .driver_info = EM2860_BOARD_KAIOMY_TVNPC_U2 }, - { USB_DEVICE(0xeb1a, 0xe305), - .driver_info = EM2880_BOARD_KWORLD_DVB_305U }, - { USB_DEVICE(0xeb1a, 0xe310), - .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD }, - { USB_DEVICE(0xeb1a, 0xa313), - .driver_info = EM2882_BOARD_KWORLD_ATSC_315U }, - { USB_DEVICE(0xeb1a, 0xa316), - .driver_info = EM2883_BOARD_KWORLD_HYBRID_330U }, - { USB_DEVICE(0xeb1a, 0xe320), - .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD_II }, - { USB_DEVICE(0xeb1a, 0xe323), - .driver_info = EM2882_BOARD_KWORLD_VS_DVBT }, - { USB_DEVICE(0xeb1a, 0xe350), - .driver_info = EM2870_BOARD_KWORLD_350U }, - { USB_DEVICE(0xeb1a, 0xe355), - .driver_info = EM2870_BOARD_KWORLD_355U }, - { USB_DEVICE(0xeb1a, 0x2801), - .driver_info = EM2800_BOARD_GRABBEEX_USB2800 }, - { USB_DEVICE(0xeb1a, 0xe357), - .driver_info = EM2870_BOARD_KWORLD_355U }, - { USB_DEVICE(0xeb1a, 0xe359), - .driver_info = EM2870_BOARD_KWORLD_355U }, - { USB_DEVICE(0x1b80, 0xe302), - .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kaiser Baas Video to DVD maker */ - { USB_DEVICE(0x1b80, 0xe304), - .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kworld DVD Maker 2 */ - { USB_DEVICE(0x0ccd, 0x0036), - .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 }, - { USB_DEVICE(0x0ccd, 0x004c), - .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS_FR }, - { USB_DEVICE(0x0ccd, 0x004f), - .driver_info = EM2860_BOARD_TERRATEC_HYBRID_XS }, - { USB_DEVICE(0x0ccd, 0x005e), - .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS }, - { USB_DEVICE(0x0ccd, 0x0042), - .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS }, - { USB_DEVICE(0x0ccd, 0x0043), - .driver_info = EM2870_BOARD_TERRATEC_XS }, - { USB_DEVICE(0x0ccd, 0x008e), /* Cinergy HTC USB XS Rev. 1 */ - .driver_info = EM2884_BOARD_TERRATEC_H5 }, - { USB_DEVICE(0x0ccd, 0x00ac), /* Cinergy HTC USB XS Rev. 2 */ - .driver_info = EM2884_BOARD_TERRATEC_H5 }, - { USB_DEVICE(0x0ccd, 0x10a2), /* H5 Rev. 1 */ - .driver_info = EM2884_BOARD_TERRATEC_H5 }, - { USB_DEVICE(0x0ccd, 0x10ad), /* H5 Rev. 2 */ - .driver_info = EM2884_BOARD_TERRATEC_H5 }, - { USB_DEVICE(0x0ccd, 0x0084), - .driver_info = EM2860_BOARD_TERRATEC_AV350 }, - { USB_DEVICE(0x0ccd, 0x0096), - .driver_info = EM2860_BOARD_TERRATEC_GRABBY }, - { USB_DEVICE(0x0ccd, 0x10AF), - .driver_info = EM2860_BOARD_TERRATEC_GRABBY }, - { USB_DEVICE(0x0ccd, 0x00b2), - .driver_info = EM2884_BOARD_CINERGY_HTC_STICK }, - { USB_DEVICE(0x0fd9, 0x0033), - .driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE}, - { USB_DEVICE(0x185b, 0x2870), - .driver_info = EM2870_BOARD_COMPRO_VIDEOMATE }, - { USB_DEVICE(0x185b, 0x2041), - .driver_info = EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU }, - { USB_DEVICE(0x2040, 0x4200), - .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, - { USB_DEVICE(0x2040, 0x4201), - .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 }, - { USB_DEVICE(0x2040, 0x6500), - .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, - { USB_DEVICE(0x2040, 0x6502), - .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 }, - { USB_DEVICE(0x2040, 0x6513), /* HCW HVR-980 */ - .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 }, - { USB_DEVICE(0x2040, 0x6517), /* HP HVR-950 */ - .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 }, - { USB_DEVICE(0x2040, 0x651b), /* RP HVR-950 */ - .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 }, - { USB_DEVICE(0x2040, 0x651f), - .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 }, - { USB_DEVICE(0x0438, 0xb002), - .driver_info = EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 }, - { USB_DEVICE(0x2001, 0xf112), - .driver_info = EM2820_BOARD_DLINK_USB_TV }, - { USB_DEVICE(0x2304, 0x0207), - .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, - { USB_DEVICE(0x2304, 0x0208), - .driver_info = EM2820_BOARD_PINNACLE_USB_2 }, - { USB_DEVICE(0x2304, 0x021a), - .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, - { USB_DEVICE(0x2304, 0x0226), - .driver_info = EM2882_BOARD_PINNACLE_HYBRID_PRO_330E }, - { USB_DEVICE(0x2304, 0x0227), - .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO }, - { USB_DEVICE(0x0413, 0x6023), - .driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII }, - { USB_DEVICE(0x093b, 0xa003), - .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, - { USB_DEVICE(0x093b, 0xa005), - .driver_info = EM2861_BOARD_PLEXTOR_PX_TV100U }, - { USB_DEVICE(0x04bb, 0x0515), - .driver_info = EM2820_BOARD_IODATA_GVMVP_SZ }, - { USB_DEVICE(0xeb1a, 0x50a6), - .driver_info = EM2860_BOARD_GADMEI_UTV330 }, - { USB_DEVICE(0x1b80, 0xa340), - .driver_info = EM2870_BOARD_KWORLD_A340 }, - { USB_DEVICE(0x2013, 0x024f), - .driver_info = EM28174_BOARD_PCTV_290E }, - { USB_DEVICE(0x2013, 0x024c), - .driver_info = EM28174_BOARD_PCTV_460E }, - { USB_DEVICE(0x2040, 0x1605), - .driver_info = EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C }, - { USB_DEVICE(0xeb1a, 0x5006), - .driver_info = EM2860_BOARD_HT_VIDBOX_NW03 }, - { USB_DEVICE(0x1b80, 0xe309), /* Sveon STV40 */ - .driver_info = EM2860_BOARD_EASYCAP }, - { USB_DEVICE(0x1b80, 0xe425), - .driver_info = EM2874_BOARD_MAXMEDIA_UB425_TC }, - { USB_DEVICE(0x2304, 0x0242), - .driver_info = EM2884_BOARD_PCTV_510E }, - { USB_DEVICE(0x2013, 0x0251), - .driver_info = EM2884_BOARD_PCTV_520E }, - { }, -}; -MODULE_DEVICE_TABLE(usb, em28xx_id_table); - -/* - * EEPROM hash table for devices with generic USB IDs - */ -static struct em28xx_hash_table em28xx_eeprom_hash[] = { - /* P/N: SA 60002070465 Tuner: TVF7533-MF */ - {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF}, - {0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF}, - {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028}, - {0x166a0441, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028}, - {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028}, - {0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028}, - {0x63f653bd, EM2870_BOARD_REDDO_DVB_C_USB_BOX, TUNER_ABSENT}, - {0x4e913442, EM2882_BOARD_DIKOM_DK300, TUNER_XC2028}, -}; - -/* I2C devicelist hash table for devices with generic USB IDs */ -static struct em28xx_hash_table em28xx_i2c_hash[] = { - {0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC}, - {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC}, - {0x1ba50080, EM2860_BOARD_SAA711X_REFERENCE_DESIGN, TUNER_ABSENT}, - {0x77800080, EM2860_BOARD_TVP5150_REFERENCE_DESIGN, TUNER_ABSENT}, - {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC}, - {0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF}, - {0x6b800080, EM2874_BOARD_LEADERSHIP_ISDBT, TUNER_ABSENT}, -}; - -/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */ -static unsigned short saa711x_addrs[] = { - 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */ - 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */ - I2C_CLIENT_END }; - -static unsigned short tvp5150_addrs[] = { - 0xb8 >> 1, - 0xba >> 1, - I2C_CLIENT_END -}; - -static unsigned short msp3400_addrs[] = { - 0x80 >> 1, - 0x88 >> 1, - I2C_CLIENT_END -}; - -int em28xx_tuner_callback(void *ptr, int component, int command, int arg) -{ - int rc = 0; - struct em28xx *dev = ptr; - - if (dev->tuner_type != TUNER_XC2028 && dev->tuner_type != TUNER_XC5000) - return 0; - - if (command != XC2028_TUNER_RESET && command != XC5000_TUNER_RESET) - return 0; - - rc = em28xx_gpio_set(dev, dev->board.tuner_gpio); - - return rc; -} -EXPORT_SYMBOL_GPL(em28xx_tuner_callback); - -static inline void em28xx_set_model(struct em28xx *dev) -{ - memcpy(&dev->board, &em28xx_boards[dev->model], sizeof(dev->board)); - - /* Those are the default values for the majority of boards - Use those values if not specified otherwise at boards entry - */ - if (!dev->board.xclk) - dev->board.xclk = EM28XX_XCLK_IR_RC5_MODE | - EM28XX_XCLK_FREQUENCY_12MHZ; - - if (!dev->board.i2c_speed) - dev->board.i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | - EM28XX_I2C_FREQ_100_KHZ; -} - - -/* FIXME: Should be replaced by a proper mt9m111 driver */ -static int em28xx_initialize_mt9m111(struct em28xx *dev) -{ - int i; - unsigned char regs[][3] = { - { 0x0d, 0x00, 0x01, }, /* reset and use defaults */ - { 0x0d, 0x00, 0x00, }, - { 0x0a, 0x00, 0x21, }, - { 0x21, 0x04, 0x00, }, /* full readout speed, no row/col skipping */ - }; - - for (i = 0; i < ARRAY_SIZE(regs); i++) - i2c_master_send(&dev->i2c_client, ®s[i][0], 3); - - return 0; -} - - -/* FIXME: Should be replaced by a proper mt9m001 driver */ -static int em28xx_initialize_mt9m001(struct em28xx *dev) -{ - int i; - unsigned char regs[][3] = { - { 0x0d, 0x00, 0x01, }, - { 0x0d, 0x00, 0x00, }, - { 0x04, 0x05, 0x00, }, /* hres = 1280 */ - { 0x03, 0x04, 0x00, }, /* vres = 1024 */ - { 0x20, 0x11, 0x00, }, - { 0x06, 0x00, 0x10, }, - { 0x2b, 0x00, 0x24, }, - { 0x2e, 0x00, 0x24, }, - { 0x35, 0x00, 0x24, }, - { 0x2d, 0x00, 0x20, }, - { 0x2c, 0x00, 0x20, }, - { 0x09, 0x0a, 0xd4, }, - { 0x35, 0x00, 0x57, }, - }; - - for (i = 0; i < ARRAY_SIZE(regs); i++) - i2c_master_send(&dev->i2c_client, ®s[i][0], 3); - - return 0; -} - -/* HINT method: webcam I2C chips - * - * This method works for webcams with Micron sensors - */ -static int em28xx_hint_sensor(struct em28xx *dev) -{ - int rc; - char *sensor_name; - unsigned char cmd; - __be16 version_be; - u16 version; - - /* Micron sensor detection */ - dev->i2c_client.addr = 0xba >> 1; - cmd = 0; - i2c_master_send(&dev->i2c_client, &cmd, 1); - rc = i2c_master_recv(&dev->i2c_client, (char *)&version_be, 2); - if (rc != 2) - return -EINVAL; - - version = be16_to_cpu(version_be); - switch (version) { - case 0x8232: /* mt9v011 640x480 1.3 Mpix sensor */ - case 0x8243: /* mt9v011 rev B 640x480 1.3 Mpix sensor */ - dev->model = EM2820_BOARD_SILVERCREST_WEBCAM; - em28xx_set_model(dev); - - sensor_name = "mt9v011"; - dev->em28xx_sensor = EM28XX_MT9V011; - dev->sensor_xres = 640; - dev->sensor_yres = 480; - /* - * FIXME: mt9v011 uses I2S speed as xtal clk - at least with - * the Silvercrest cam I have here for testing - for higher - * resolutions, a high clock cause horizontal artifacts, so we - * need to use a lower xclk frequency. - * Yet, it would be possible to adjust xclk depending on the - * desired resolution, since this affects directly the - * frame rate. - */ - dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ; - dev->sensor_xtal = 4300000; - - /* probably means GRGB 16 bit bayer */ - dev->vinmode = 0x0d; - dev->vinctl = 0x00; - - break; - - case 0x143a: /* MT9M111 as found in the ECS G200 */ - dev->model = EM2750_BOARD_UNKNOWN; - em28xx_set_model(dev); - - sensor_name = "mt9m111"; - dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ; - dev->em28xx_sensor = EM28XX_MT9M111; - em28xx_initialize_mt9m111(dev); - dev->sensor_xres = 640; - dev->sensor_yres = 512; - - dev->vinmode = 0x0a; - dev->vinctl = 0x00; - - break; - - case 0x8431: - dev->model = EM2750_BOARD_UNKNOWN; - em28xx_set_model(dev); - - sensor_name = "mt9m001"; - dev->em28xx_sensor = EM28XX_MT9M001; - em28xx_initialize_mt9m001(dev); - dev->sensor_xres = 1280; - dev->sensor_yres = 1024; - - /* probably means BGGR 16 bit bayer */ - dev->vinmode = 0x0c; - dev->vinctl = 0x00; - - break; - default: - printk("Unknown Micron Sensor 0x%04x\n", version); - return -EINVAL; - } - - /* Setup webcam defaults */ - em28xx_pre_card_setup(dev); - - em28xx_errdev("Sensor is %s, using model %s entry.\n", - sensor_name, em28xx_boards[dev->model].name); - - return 0; -} - -/* Since em28xx_pre_card_setup() requires a proper dev->model, - * this won't work for boards with generic PCI IDs - */ -static void em28xx_pre_card_setup(struct em28xx *dev) -{ - /* Set the initial XCLK and I2C clock values based on the board - definition */ - em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f); - if (!dev->board.is_em2800) - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); - msleep(50); - - /* request some modules */ - switch (dev->model) { - case EM2861_BOARD_PLEXTOR_PX_TV100U: - /* Sets the msp34xx I2S speed */ - dev->i2s_speed = 2048000; - break; - case EM2861_BOARD_KWORLD_PVRTV_300U: - case EM2880_BOARD_KWORLD_DVB_305U: - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x6d); - msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x7d); - msleep(10); - break; - case EM2870_BOARD_COMPRO_VIDEOMATE: - /* TODO: someone can do some cleanup here... - not everything's needed */ - em28xx_write_reg(dev, EM2880_R04_GPO, 0x00); - msleep(10); - em28xx_write_reg(dev, EM2880_R04_GPO, 0x01); - msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); - mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfc); - mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xdc); - mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfc); - mdelay(70); - break; - case EM2870_BOARD_TERRATEC_XS_MT2060: - /* this device needs some gpio writes to get the DVB-T - demod work */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); - mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xde); - mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); - mdelay(70); - break; - case EM2870_BOARD_PINNACLE_PCTV_DVB: - /* this device needs some gpio writes to get the - DVB-T demod work */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); - mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xde); - mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); - mdelay(70); - break; - case EM2820_BOARD_GADMEI_UTV310: - case EM2820_BOARD_MSI_VOX_USB_2: - /* enables audio for that devices */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); - break; - - case EM2882_BOARD_KWORLD_ATSC_315U: - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); - msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); - msleep(10); - em28xx_write_reg(dev, EM2880_R04_GPO, 0x00); - msleep(10); - em28xx_write_reg(dev, EM2880_R04_GPO, 0x08); - msleep(10); - break; - - case EM2860_BOARD_KAIOMY_TVNPC_U2: - em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x07", 1); - em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1); - em28xx_write_regs(dev, 0x0d, "\x42", 1); - em28xx_write_regs(dev, 0x08, "\xfd", 1); - msleep(10); - em28xx_write_regs(dev, 0x08, "\xff", 1); - msleep(10); - em28xx_write_regs(dev, 0x08, "\x7f", 1); - msleep(10); - em28xx_write_regs(dev, 0x08, "\x6b", 1); - - break; - case EM2860_BOARD_EASYCAP: - em28xx_write_regs(dev, 0x08, "\xf8", 1); - break; - - case EM2820_BOARD_IODATA_GVMVP_SZ: - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); - msleep(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); - msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); - msleep(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); - msleep(70); - break; - } - - em28xx_gpio_set(dev, dev->board.tuner_gpio); - em28xx_set_mode(dev, EM28XX_ANALOG_MODE); - - /* Unlock device */ - em28xx_set_mode(dev, EM28XX_SUSPEND); -} - -static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) -{ - memset(ctl, 0, sizeof(*ctl)); - - ctl->fname = XC2028_DEFAULT_FIRMWARE; - ctl->max_len = 64; - ctl->mts = em28xx_boards[dev->model].mts_firmware; - - switch (dev->model) { - case EM2880_BOARD_EMPIRE_DUAL_TV: - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: - case EM2882_BOARD_TERRATEC_HYBRID_XS: - ctl->demod = XC3028_FE_ZARLINK456; - break; - case EM2880_BOARD_TERRATEC_HYBRID_XS: - case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: - case EM2881_BOARD_PINNACLE_HYBRID_PRO: - ctl->demod = XC3028_FE_ZARLINK456; - break; - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: - case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E: - ctl->demod = XC3028_FE_DEFAULT; - break; - case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: - ctl->demod = XC3028_FE_DEFAULT; - ctl->fname = XC3028L_DEFAULT_FIRMWARE; - break; - case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: - case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: - case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: - /* FIXME: Better to specify the needed IF */ - ctl->demod = XC3028_FE_DEFAULT; - break; - case EM2883_BOARD_KWORLD_HYBRID_330U: - case EM2882_BOARD_DIKOM_DK300: - case EM2882_BOARD_KWORLD_VS_DVBT: - ctl->demod = XC3028_FE_CHINA; - ctl->fname = XC2028_DEFAULT_FIRMWARE; - break; - case EM2882_BOARD_EVGA_INDTUBE: - ctl->demod = XC3028_FE_CHINA; - ctl->fname = XC3028L_DEFAULT_FIRMWARE; - break; - default: - ctl->demod = XC3028_FE_OREN538; - } -} - -static void em28xx_tuner_setup(struct em28xx *dev) -{ - struct tuner_setup tun_setup; - struct v4l2_frequency f; - - if (dev->tuner_type == TUNER_ABSENT) - return; - - memset(&tun_setup, 0, sizeof(tun_setup)); - - tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; - tun_setup.tuner_callback = em28xx_tuner_callback; - - if (dev->board.radio.type) { - tun_setup.type = dev->board.radio.type; - tun_setup.addr = dev->board.radio_addr; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup); - } - - if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) { - tun_setup.type = dev->tuner_type; - tun_setup.addr = dev->tuner_addr; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup); - } - - if (dev->tda9887_conf) { - struct v4l2_priv_tun_config tda9887_cfg; - - tda9887_cfg.tuner = TUNER_TDA9887; - tda9887_cfg.priv = &dev->tda9887_conf; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &tda9887_cfg); - } - - if (dev->tuner_type == TUNER_XC2028) { - struct v4l2_priv_tun_config xc2028_cfg; - struct xc2028_ctrl ctl; - - memset(&xc2028_cfg, 0, sizeof(xc2028_cfg)); - memset(&ctl, 0, sizeof(ctl)); - - em28xx_setup_xc3028(dev, &ctl); - - xc2028_cfg.tuner = TUNER_XC2028; - xc2028_cfg.priv = &ctl; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &xc2028_cfg); - } - - /* configure tuner */ - f.tuner = 0; - f.type = V4L2_TUNER_ANALOG_TV; - f.frequency = 9076; /* just a magic number */ - dev->ctl_freq = f.frequency; - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); -} - -static int em28xx_hint_board(struct em28xx *dev) -{ - int i; - - /* HINT method: EEPROM - * - * This method works only for boards with eeprom. - * Uses a hash of all eeprom bytes. The hash should be - * unique for a vendor/tuner pair. - * There are a high chance that tuners for different - * video standards produce different hashes. - */ - for (i = 0; i < ARRAY_SIZE(em28xx_eeprom_hash); i++) { - if (dev->hash == em28xx_eeprom_hash[i].hash) { - dev->model = em28xx_eeprom_hash[i].model; - dev->tuner_type = em28xx_eeprom_hash[i].tuner; - - em28xx_errdev("Your board has no unique USB ID.\n"); - em28xx_errdev("A hint were successfully done, " - "based on eeprom hash.\n"); - em28xx_errdev("This method is not 100%% failproof.\n"); - em28xx_errdev("If the board were missdetected, " - "please email this log to:\n"); - em28xx_errdev("\tV4L Mailing List " - " <linux-media@vger.kernel.org>\n"); - em28xx_errdev("Board detected as %s\n", - em28xx_boards[dev->model].name); - - return 0; - } - } - - /* HINT method: I2C attached devices - * - * This method works for all boards. - * Uses a hash of i2c scanned devices. - * Devices with the same i2c attached chips will - * be considered equal. - * This method is less precise than the eeprom one. - */ - - /* user did not request i2c scanning => do it now */ - if (!dev->i2c_hash) - em28xx_do_i2c_scan(dev); - - for (i = 0; i < ARRAY_SIZE(em28xx_i2c_hash); i++) { - if (dev->i2c_hash == em28xx_i2c_hash[i].hash) { - dev->model = em28xx_i2c_hash[i].model; - dev->tuner_type = em28xx_i2c_hash[i].tuner; - em28xx_errdev("Your board has no unique USB ID.\n"); - em28xx_errdev("A hint were successfully done, " - "based on i2c devicelist hash.\n"); - em28xx_errdev("This method is not 100%% failproof.\n"); - em28xx_errdev("If the board were missdetected, " - "please email this log to:\n"); - em28xx_errdev("\tV4L Mailing List " - " <linux-media@vger.kernel.org>\n"); - em28xx_errdev("Board detected as %s\n", - em28xx_boards[dev->model].name); - - return 0; - } - } - - em28xx_errdev("Your board has no unique USB ID and thus need a " - "hint to be detected.\n"); - em28xx_errdev("You may try to use card=<n> insmod option to " - "workaround that.\n"); - em28xx_errdev("Please send an email with this log to:\n"); - em28xx_errdev("\tV4L Mailing List <linux-media@vger.kernel.org>\n"); - em28xx_errdev("Board eeprom hash is 0x%08lx\n", dev->hash); - em28xx_errdev("Board i2c devicelist hash is 0x%08lx\n", dev->i2c_hash); - - em28xx_errdev("Here is a list of valid choices for the card=<n>" - " insmod option:\n"); - for (i = 0; i < em28xx_bcount; i++) { - em28xx_errdev(" card=%d -> %s\n", - i, em28xx_boards[i].name); - } - return -1; -} - -static void em28xx_card_setup(struct em28xx *dev) -{ - /* - * If the device can be a webcam, seek for a sensor. - * If sensor is not found, then it isn't a webcam. - */ - if (dev->board.is_webcam) { - if (em28xx_hint_sensor(dev) < 0) - dev->board.is_webcam = 0; - else - dev->progressive = 1; - } - - if (!dev->board.is_webcam) { - switch (dev->model) { - case EM2820_BOARD_UNKNOWN: - case EM2800_BOARD_UNKNOWN: - /* - * The K-WORLD DVB-T 310U is detected as an MSI Digivox AD. - * - * This occurs because they share identical USB vendor and - * product IDs. - * - * What we do here is look up the EEPROM hash of the K-WORLD - * and if it is found then we decide that we do not have - * a DIGIVOX and reset the device to the K-WORLD instead. - * - * This solution is only valid if they do not share eeprom - * hash identities which has not been determined as yet. - */ - if (em28xx_hint_board(dev) < 0) - em28xx_errdev("Board not discovered\n"); - else { - em28xx_set_model(dev); - em28xx_pre_card_setup(dev); - } - break; - default: - em28xx_set_model(dev); - } - } - - em28xx_info("Identified as %s (card=%d)\n", - dev->board.name, dev->model); - - dev->tuner_type = em28xx_boards[dev->model].tuner_type; - if (em28xx_boards[dev->model].tuner_addr) - dev->tuner_addr = em28xx_boards[dev->model].tuner_addr; - - if (em28xx_boards[dev->model].tda9887_conf) - dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf; - - /* request some modules */ - switch (dev->model) { - case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: - case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: - case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: - { - struct tveeprom tv; -#if defined(CONFIG_MODULES) && defined(MODULE) - request_module("tveeprom"); -#endif - /* Call first TVeeprom */ - - dev->i2c_client.addr = 0xa0 >> 1; - tveeprom_hauppauge_analog(&dev->i2c_client, &tv, dev->eedata); - - dev->tuner_type = tv.tuner_type; - - if (tv.audio_processor == V4L2_IDENT_MSPX4XX) { - dev->i2s_speed = 2048000; - dev->board.has_msp34xx = 1; - } - break; - } - case EM2882_BOARD_KWORLD_ATSC_315U: - em28xx_write_reg(dev, 0x0d, 0x42); - msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); - msleep(10); - break; - case EM2820_BOARD_KWORLD_PVRTV2800RF: - /* GPIO enables sound on KWORLD PVR TV 2800RF */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf9); - break; - case EM2820_BOARD_UNKNOWN: - case EM2800_BOARD_UNKNOWN: - /* - * The K-WORLD DVB-T 310U is detected as an MSI Digivox AD. - * - * This occurs because they share identical USB vendor and - * product IDs. - * - * What we do here is look up the EEPROM hash of the K-WORLD - * and if it is found then we decide that we do not have - * a DIGIVOX and reset the device to the K-WORLD instead. - * - * This solution is only valid if they do not share eeprom - * hash identities which has not been determined as yet. - */ - case EM2880_BOARD_MSI_DIGIVOX_AD: - if (!em28xx_hint_board(dev)) - em28xx_set_model(dev); - - /* In cases where we had to use a board hint, the call to - em28xx_set_mode() in em28xx_pre_card_setup() was a no-op, - so make the call now so the analog GPIOs are set properly - before probing the i2c bus. */ - em28xx_gpio_set(dev, dev->board.tuner_gpio); - em28xx_set_mode(dev, EM28XX_ANALOG_MODE); - break; - -/* - * The Dikom DK300 is detected as an Kworld VS-DVB-T 323UR. - * - * This occurs because they share identical USB vendor and - * product IDs. - * - * What we do here is look up the EEPROM hash of the Dikom - * and if it is found then we decide that we do not have - * a Kworld and reset the device to the Dikom instead. - * - * This solution is only valid if they do not share eeprom - * hash identities which has not been determined as yet. - */ - case EM2882_BOARD_KWORLD_VS_DVBT: - if (!em28xx_hint_board(dev)) - em28xx_set_model(dev); - - /* In cases where we had to use a board hint, the call to - em28xx_set_mode() in em28xx_pre_card_setup() was a no-op, - so make the call now so the analog GPIOs are set properly - before probing the i2c bus. */ - em28xx_gpio_set(dev, dev->board.tuner_gpio); - em28xx_set_mode(dev, EM28XX_ANALOG_MODE); - break; - } - - if (dev->board.valid == EM28XX_BOARD_NOT_VALIDATED) { - em28xx_errdev("\n\n"); - em28xx_errdev("The support for this board weren't " - "valid yet.\n"); - em28xx_errdev("Please send a report of having this working\n"); - em28xx_errdev("not to V4L mailing list (and/or to other " - "addresses)\n\n"); - } - - /* Allow override tuner type by a module parameter */ - if (tuner >= 0) - dev->tuner_type = tuner; - - /* request some modules */ - if (dev->board.has_msp34xx) - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "msp3400", 0, msp3400_addrs); - - if (dev->board.decoder == EM28XX_SAA711X) - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "saa7115_auto", 0, saa711x_addrs); - - if (dev->board.decoder == EM28XX_TVP5150) - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tvp5150", 0, tvp5150_addrs); - - if (dev->em28xx_sensor == EM28XX_MT9V011) { - struct mt9v011_platform_data pdata; - struct i2c_board_info mt9v011_info = { - .type = "mt9v011", - .addr = 0xba >> 1, - .platform_data = &pdata, - }; - - pdata.xtal = dev->sensor_xtal; - v4l2_i2c_new_subdev_board(&dev->v4l2_dev, &dev->i2c_adap, - &mt9v011_info, NULL); - } - - - if (dev->board.adecoder == EM28XX_TVAUDIO) - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tvaudio", dev->board.tvaudio_addr, NULL); - - if (dev->board.tuner_type != TUNER_ABSENT) { - int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); - - if (dev->board.radio.type) - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tuner", dev->board.radio_addr, NULL); - - if (has_demod) - v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, "tuner", - 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); - if (dev->tuner_addr == 0) { - enum v4l2_i2c_tuner_type type = - has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; - struct v4l2_subdev *sd; - - sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, "tuner", - 0, v4l2_i2c_tuner_addrs(type)); - - if (sd) - dev->tuner_addr = v4l2_i2c_subdev_addr(sd); - } else { - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tuner", dev->tuner_addr, NULL); - } - } - - em28xx_tuner_setup(dev); -} - - -#if defined(CONFIG_MODULES) && defined(MODULE) -static void request_module_async(struct work_struct *work) -{ - struct em28xx *dev = container_of(work, - struct em28xx, request_module_wk); - - if (dev->has_audio_class) - request_module("snd-usb-audio"); - else if (dev->has_alsa_audio) - request_module("em28xx-alsa"); - - if (dev->board.has_dvb) - request_module("em28xx-dvb"); - if (dev->board.ir_codes && !disable_ir) - request_module("em28xx-rc"); -} - -static void request_modules(struct em28xx *dev) -{ - INIT_WORK(&dev->request_module_wk, request_module_async); - schedule_work(&dev->request_module_wk); -} - -static void flush_request_modules(struct em28xx *dev) -{ - flush_work_sync(&dev->request_module_wk); -} -#else -#define request_modules(dev) -#define flush_request_modules(dev) -#endif /* CONFIG_MODULES */ - -/* - * em28xx_release_resources() - * unregisters the v4l2,i2c and usb devices - * called when the device gets disconnected or at module unload -*/ -void em28xx_release_resources(struct em28xx *dev) -{ - /*FIXME: I2C IR should be disconnected */ - - em28xx_release_analog_resources(dev); - - em28xx_i2c_unregister(dev); - - v4l2_device_unregister(&dev->v4l2_dev); - - usb_put_dev(dev->udev); - - /* Mark device as unused */ - clear_bit(dev->devno, &em28xx_devused); -}; - -/* - * em28xx_init_dev() - * allocates and inits the device structs, registers i2c bus and v4l device - */ -static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, - struct usb_interface *interface, - int minor) -{ - int retval; - - dev->udev = udev; - mutex_init(&dev->ctrl_urb_lock); - spin_lock_init(&dev->slock); - - dev->em28xx_write_regs = em28xx_write_regs; - dev->em28xx_read_reg = em28xx_read_reg; - dev->em28xx_read_reg_req_len = em28xx_read_reg_req_len; - dev->em28xx_write_regs_req = em28xx_write_regs_req; - dev->em28xx_read_reg_req = em28xx_read_reg_req; - dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800; - - em28xx_set_model(dev); - - /* Set the default GPO/GPIO for legacy devices */ - dev->reg_gpo_num = EM2880_R04_GPO; - dev->reg_gpio_num = EM28XX_R08_GPIO; - - dev->wait_after_write = 5; - - /* Based on the Chip ID, set the device configuration */ - retval = em28xx_read_reg(dev, EM28XX_R0A_CHIPID); - if (retval > 0) { - dev->chip_id = retval; - - switch (dev->chip_id) { - case CHIP_ID_EM2800: - em28xx_info("chip ID is em2800\n"); - break; - case CHIP_ID_EM2710: - em28xx_info("chip ID is em2710\n"); - break; - case CHIP_ID_EM2750: - em28xx_info("chip ID is em2750\n"); - break; - case CHIP_ID_EM2820: - em28xx_info("chip ID is em2820 (or em2710)\n"); - break; - case CHIP_ID_EM2840: - em28xx_info("chip ID is em2840\n"); - break; - case CHIP_ID_EM2860: - em28xx_info("chip ID is em2860\n"); - break; - case CHIP_ID_EM2870: - em28xx_info("chip ID is em2870\n"); - dev->wait_after_write = 0; - break; - case CHIP_ID_EM2874: - em28xx_info("chip ID is em2874\n"); - dev->reg_gpio_num = EM2874_R80_GPIO; - dev->wait_after_write = 0; - break; - case CHIP_ID_EM28174: - em28xx_info("chip ID is em28174\n"); - dev->reg_gpio_num = EM2874_R80_GPIO; - dev->wait_after_write = 0; - break; - case CHIP_ID_EM2883: - em28xx_info("chip ID is em2882/em2883\n"); - dev->wait_after_write = 0; - break; - case CHIP_ID_EM2884: - em28xx_info("chip ID is em2884\n"); - dev->reg_gpio_num = EM2874_R80_GPIO; - dev->wait_after_write = 0; - break; - default: - em28xx_info("em28xx chip ID = %d\n", dev->chip_id); - } - } - - if (dev->is_audio_only) { - retval = em28xx_audio_setup(dev); - if (retval) - return -ENODEV; - em28xx_init_extension(dev); - - return 0; - } - - /* Prepopulate cached GPO register content */ - retval = em28xx_read_reg(dev, dev->reg_gpo_num); - if (retval >= 0) - dev->reg_gpo = retval; - - em28xx_pre_card_setup(dev); - - if (!dev->board.is_em2800) { - /* Resets I2C speed */ - retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); - if (retval < 0) { - em28xx_errdev("%s: em28xx_write_reg failed!" - " retval [%d]\n", - __func__, retval); - return retval; - } - } - - retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); - if (retval < 0) { - em28xx_errdev("Call to v4l2_device_register() failed!\n"); - return retval; - } - - /* register i2c bus */ - retval = em28xx_i2c_register(dev); - if (retval < 0) { - em28xx_errdev("%s: em28xx_i2c_register - error [%d]!\n", - __func__, retval); - goto unregister_dev; - } - - /* - * Default format, used for tvp5150 or saa711x output formats - */ - dev->vinmode = 0x10; - dev->vinctl = EM28XX_VINCTRL_INTERLACED | - EM28XX_VINCTRL_CCIR656_ENABLE; - - /* Do board specific init and eeprom reading */ - em28xx_card_setup(dev); - - /* Configure audio */ - retval = em28xx_audio_setup(dev); - if (retval < 0) { - em28xx_errdev("%s: Error while setting audio - error [%d]!\n", - __func__, retval); - goto fail; - } - - /* wake i2c devices */ - em28xx_wake_i2c(dev); - - /* init video dma queues */ - INIT_LIST_HEAD(&dev->vidq.active); - INIT_LIST_HEAD(&dev->vbiq.active); - - if (dev->board.has_msp34xx) { - /* Send a reset to other chips via gpio */ - retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); - if (retval < 0) { - em28xx_errdev("%s: em28xx_write_reg - " - "msp34xx(1) failed! error [%d]\n", - __func__, retval); - goto fail; - } - msleep(3); - - retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); - if (retval < 0) { - em28xx_errdev("%s: em28xx_write_reg - " - "msp34xx(2) failed! error [%d]\n", - __func__, retval); - goto fail; - } - msleep(3); - } - - retval = em28xx_register_analog_devices(dev); - if (retval < 0) { - goto fail; - } - - /* Save some power by putting tuner to sleep */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); - - return 0; - -fail: - em28xx_i2c_unregister(dev); - -unregister_dev: - v4l2_device_unregister(&dev->v4l2_dev); - - return retval; -} - -/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */ -#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) - -/* - * em28xx_usb_probe() - * checks for supported devices - */ -static int em28xx_usb_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_device *udev; - struct em28xx *dev = NULL; - int retval; - bool has_audio = false, has_video = false, has_dvb = false; - int i, nr; - const int ifnum = interface->altsetting[0].desc.bInterfaceNumber; - char *speed; - - udev = usb_get_dev(interface_to_usbdev(interface)); - - /* Check to see next free device and mark as used */ - do { - nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS); - if (nr >= EM28XX_MAXBOARDS) { - /* No free device slots */ - printk(DRIVER_NAME ": Supports only %i em28xx boards.\n", - EM28XX_MAXBOARDS); - retval = -ENOMEM; - goto err_no_slot; - } - } while (test_and_set_bit(nr, &em28xx_devused)); - - /* Don't register audio interfaces */ - if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { - em28xx_err(DRIVER_NAME " audio device (%04x:%04x): " - "interface %i, class %i\n", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), - ifnum, - interface->altsetting[0].desc.bInterfaceClass); - - retval = -ENODEV; - goto err; - } - - /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - em28xx_err(DRIVER_NAME ": out of memory!\n"); - retval = -ENOMEM; - goto err; - } - - /* compute alternate max packet sizes */ - dev->alt_max_pkt_size = kmalloc(sizeof(dev->alt_max_pkt_size[0]) * - interface->num_altsetting, GFP_KERNEL); - if (dev->alt_max_pkt_size == NULL) { - em28xx_errdev("out of memory!\n"); - kfree(dev); - retval = -ENOMEM; - goto err; - } - - /* Get endpoints */ - for (i = 0; i < interface->num_altsetting; i++) { - int ep; - - for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) { - const struct usb_endpoint_descriptor *e; - int sizedescr, size; - - e = &interface->altsetting[i].endpoint[ep].desc; - - sizedescr = le16_to_cpu(e->wMaxPacketSize); - size = sizedescr & 0x7ff; - - if (udev->speed == USB_SPEED_HIGH) - size = size * hb_mult(sizedescr); - - if (usb_endpoint_xfer_isoc(e) && - usb_endpoint_dir_in(e)) { - switch (e->bEndpointAddress) { - case EM28XX_EP_AUDIO: - has_audio = true; - break; - case EM28XX_EP_ANALOG: - has_video = true; - dev->alt_max_pkt_size[i] = size; - break; - case EM28XX_EP_DIGITAL: - has_dvb = true; - if (size > dev->dvb_max_pkt_size) { - dev->dvb_max_pkt_size = size; - dev->dvb_alt = i; - } - break; - } - } - } - } - - if (!(has_audio || has_video || has_dvb)) { - retval = -ENODEV; - goto err_free; - } - - switch (udev->speed) { - case USB_SPEED_LOW: - speed = "1.5"; - break; - case USB_SPEED_UNKNOWN: - case USB_SPEED_FULL: - speed = "12"; - break; - case USB_SPEED_HIGH: - speed = "480"; - break; - default: - speed = "unknown"; - } - - printk(KERN_INFO DRIVER_NAME - ": New device %s %s @ %s Mbps " - "(%04x:%04x, interface %d, class %d)\n", - udev->manufacturer ? udev->manufacturer : "", - udev->product ? udev->product : "", - speed, - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), - ifnum, - interface->altsetting->desc.bInterfaceNumber); - - if (has_audio) - printk(KERN_INFO DRIVER_NAME - ": Audio Vendor Class interface %i found\n", - ifnum); - if (has_video) - printk(KERN_INFO DRIVER_NAME - ": Video interface %i found\n", - ifnum); - if (has_dvb) - printk(KERN_INFO DRIVER_NAME - ": DVB interface %i found\n", - ifnum); - - /* - * Make sure we have 480 Mbps of bandwidth, otherwise things like - * video stream wouldn't likely work, since 12 Mbps is generally - * not enough even for most Digital TV streams. - */ - if (udev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) { - printk(DRIVER_NAME ": Device initialization failed.\n"); - printk(DRIVER_NAME ": Device must be connected to a high-speed" - " USB 2.0 port.\n"); - retval = -ENODEV; - goto err_free; - } - - snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr); - dev->devno = nr; - dev->model = id->driver_info; - dev->alt = -1; - dev->is_audio_only = has_audio && !(has_video || has_dvb); - dev->has_alsa_audio = has_audio; - dev->audio_ifnum = ifnum; - - /* Checks if audio is provided by some interface */ - for (i = 0; i < udev->config->desc.bNumInterfaces; i++) { - struct usb_interface *uif = udev->config->interface[i]; - if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { - dev->has_audio_class = 1; - break; - } - } - - dev->num_alt = interface->num_altsetting; - - if ((card[nr] >= 0) && (card[nr] < em28xx_bcount)) - dev->model = card[nr]; - - /* save our data pointer in this interface device */ - usb_set_intfdata(interface, dev); - - /* allocate device struct */ - mutex_init(&dev->lock); - mutex_lock(&dev->lock); - retval = em28xx_init_dev(dev, udev, interface, nr); - if (retval) { - goto unlock_and_free; - } - - if (has_dvb) { - /* pre-allocate DVB isoc transfer buffers */ - retval = em28xx_alloc_isoc(dev, EM28XX_DIGITAL_MODE, - EM28XX_DVB_MAX_PACKETS, - EM28XX_DVB_NUM_BUFS, - dev->dvb_max_pkt_size); - if (retval) { - goto unlock_and_free; - } - } - - request_modules(dev); - - /* Should be the last thing to do, to avoid newer udev's to - open the device before fully initializing it - */ - mutex_unlock(&dev->lock); - - /* - * These extensions can be modules. If the modules are already - * loaded then we can initialise the device now, otherwise we - * will initialise it when the modules load instead. - */ - em28xx_init_extension(dev); - - return 0; - -unlock_and_free: - mutex_unlock(&dev->lock); - -err_free: - kfree(dev->alt_max_pkt_size); - kfree(dev); - -err: - clear_bit(nr, &em28xx_devused); - -err_no_slot: - usb_put_dev(udev); - return retval; -} - -/* - * em28xx_usb_disconnect() - * called when the device gets disconnected - * video device will be unregistered on v4l2_close in case it is still open - */ -static void em28xx_usb_disconnect(struct usb_interface *interface) -{ - struct em28xx *dev; - - dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - if (!dev) - return; - - if (dev->is_audio_only) { - mutex_lock(&dev->lock); - em28xx_close_extension(dev); - mutex_unlock(&dev->lock); - return; - } - - em28xx_info("disconnecting %s\n", dev->vdev->name); - - flush_request_modules(dev); - - /* wait until all current v4l2 io is finished then deallocate - resources */ - mutex_lock(&dev->lock); - - v4l2_device_disconnect(&dev->v4l2_dev); - - if (dev->users) { - em28xx_warn - ("device %s is open! Deregistration and memory " - "deallocation are deferred on close.\n", - video_device_node_name(dev->vdev)); - - dev->state |= DEV_MISCONFIGURED; - em28xx_uninit_isoc(dev, dev->mode); - dev->state |= DEV_DISCONNECTED; - } else { - dev->state |= DEV_DISCONNECTED; - em28xx_release_resources(dev); - } - - /* free DVB isoc buffers */ - em28xx_uninit_isoc(dev, EM28XX_DIGITAL_MODE); - - mutex_unlock(&dev->lock); - - em28xx_close_extension(dev); - - if (!dev->users) { - kfree(dev->alt_max_pkt_size); - kfree(dev); - } -} - -static struct usb_driver em28xx_usb_driver = { - .name = "em28xx", - .probe = em28xx_usb_probe, - .disconnect = em28xx_usb_disconnect, - .id_table = em28xx_id_table, -}; - -module_usb_driver(em28xx_usb_driver); diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c deleted file mode 100644 index bed07a6c33f8..000000000000 --- a/drivers/media/video/em28xx/em28xx-core.c +++ /dev/null @@ -1,1260 +0,0 @@ -/* - em28xx-core.c - driver for Empia EM2800/EM2820/2840 USB video capture devices - - Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> - Markus Rechberger <mrechberger@gmail.com> - Mauro Carvalho Chehab <mchehab@infradead.org> - Sascha Sommer <saschasommer@freenet.de> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/init.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/vmalloc.h> -#include <sound/ac97_codec.h> -#include <media/v4l2-common.h> - -#include "em28xx.h" - -/* #define ENABLE_DEBUG_ISOC_FRAMES */ - -static unsigned int core_debug; -module_param(core_debug, int, 0644); -MODULE_PARM_DESC(core_debug, "enable debug messages [core]"); - -#define em28xx_coredbg(fmt, arg...) do {\ - if (core_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __func__ , ##arg); } while (0) - -static unsigned int reg_debug; -module_param(reg_debug, int, 0644); -MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]"); - -#define em28xx_regdbg(fmt, arg...) do {\ - if (reg_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __func__ , ##arg); } while (0) - -static int alt; -module_param(alt, int, 0644); -MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); - -static unsigned int disable_vbi; -module_param(disable_vbi, int, 0644); -MODULE_PARM_DESC(disable_vbi, "disable vbi support"); - -/* FIXME */ -#define em28xx_isocdbg(fmt, arg...) do {\ - if (core_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __func__ , ##arg); } while (0) - -/* - * em28xx_read_reg_req() - * reads data from the usb device specifying bRequest - */ -int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, - char *buf, int len) -{ - int ret; - int pipe = usb_rcvctrlpipe(dev->udev, 0); - - if (dev->state & DEV_DISCONNECTED) - return -ENODEV; - - if (len > URB_MAX_CTRL_SIZE) - return -EINVAL; - - if (reg_debug) { - printk(KERN_DEBUG "(pipe 0x%08x): " - "IN: %02x %02x %02x %02x %02x %02x %02x %02x ", - pipe, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - req, 0, 0, - reg & 0xff, reg >> 8, - len & 0xff, len >> 8); - } - - mutex_lock(&dev->ctrl_urb_lock); - ret = usb_control_msg(dev->udev, pipe, req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0000, reg, dev->urb_buf, len, HZ); - if (ret < 0) { - if (reg_debug) - printk(" failed!\n"); - mutex_unlock(&dev->ctrl_urb_lock); - return ret; - } - - if (len) - memcpy(buf, dev->urb_buf, len); - - mutex_unlock(&dev->ctrl_urb_lock); - - if (reg_debug) { - int byte; - - printk("<<<"); - for (byte = 0; byte < len; byte++) - printk(" %02x", (unsigned char)buf[byte]); - printk("\n"); - } - - return ret; -} - -/* - * em28xx_read_reg_req() - * reads data from the usb device specifying bRequest - */ -int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) -{ - int ret; - u8 val; - - ret = em28xx_read_reg_req_len(dev, req, reg, &val, 1); - if (ret < 0) - return ret; - - return val; -} - -int em28xx_read_reg(struct em28xx *dev, u16 reg) -{ - return em28xx_read_reg_req(dev, USB_REQ_GET_STATUS, reg); -} -EXPORT_SYMBOL_GPL(em28xx_read_reg); - -/* - * em28xx_write_regs_req() - * sends data to the usb device, specifying bRequest - */ -int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, - int len) -{ - int ret; - int pipe = usb_sndctrlpipe(dev->udev, 0); - - if (dev->state & DEV_DISCONNECTED) - return -ENODEV; - - if ((len < 1) || (len > URB_MAX_CTRL_SIZE)) - return -EINVAL; - - if (reg_debug) { - int byte; - - printk(KERN_DEBUG "(pipe 0x%08x): " - "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>", - pipe, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - req, 0, 0, - reg & 0xff, reg >> 8, - len & 0xff, len >> 8); - - for (byte = 0; byte < len; byte++) - printk(" %02x", (unsigned char)buf[byte]); - printk("\n"); - } - - mutex_lock(&dev->ctrl_urb_lock); - memcpy(dev->urb_buf, buf, len); - ret = usb_control_msg(dev->udev, pipe, req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0000, reg, dev->urb_buf, len, HZ); - mutex_unlock(&dev->ctrl_urb_lock); - - if (dev->wait_after_write) - msleep(dev->wait_after_write); - - return ret; -} - -int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len) -{ - int rc; - - rc = em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len); - - /* Stores GPO/GPIO values at the cache, if changed - Only write values should be stored, since input on a GPIO - register will return the input bits. - Not sure what happens on reading GPO register. - */ - if (rc >= 0) { - if (reg == dev->reg_gpo_num) - dev->reg_gpo = buf[0]; - else if (reg == dev->reg_gpio_num) - dev->reg_gpio = buf[0]; - } - - return rc; -} -EXPORT_SYMBOL_GPL(em28xx_write_regs); - -/* Write a single register */ -int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val) -{ - return em28xx_write_regs(dev, reg, &val, 1); -} -EXPORT_SYMBOL_GPL(em28xx_write_reg); - -/* - * em28xx_write_reg_bits() - * sets only some bits (specified by bitmask) of a register, by first reading - * the actual value - */ -int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, - u8 bitmask) -{ - int oldval; - u8 newval; - - /* Uses cache for gpo/gpio registers */ - if (reg == dev->reg_gpo_num) - oldval = dev->reg_gpo; - else if (reg == dev->reg_gpio_num) - oldval = dev->reg_gpio; - else - oldval = em28xx_read_reg(dev, reg); - - if (oldval < 0) - return oldval; - - newval = (((u8) oldval) & ~bitmask) | (val & bitmask); - - return em28xx_write_regs(dev, reg, &newval, 1); -} -EXPORT_SYMBOL_GPL(em28xx_write_reg_bits); - -/* - * em28xx_is_ac97_ready() - * Checks if ac97 is ready - */ -static int em28xx_is_ac97_ready(struct em28xx *dev) -{ - int ret, i; - - /* Wait up to 50 ms for AC97 command to complete */ - for (i = 0; i < 10; i++, msleep(5)) { - ret = em28xx_read_reg(dev, EM28XX_R43_AC97BUSY); - if (ret < 0) - return ret; - - if (!(ret & 0x01)) - return 0; - } - - em28xx_warn("AC97 command still being executed: not handled properly!\n"); - return -EBUSY; -} - -/* - * em28xx_read_ac97() - * write a 16 bit value to the specified AC97 address (LSB first!) - */ -int em28xx_read_ac97(struct em28xx *dev, u8 reg) -{ - int ret; - u8 addr = (reg & 0x7f) | 0x80; - u16 val; - - ret = em28xx_is_ac97_ready(dev); - if (ret < 0) - return ret; - - ret = em28xx_write_regs(dev, EM28XX_R42_AC97ADDR, &addr, 1); - if (ret < 0) - return ret; - - ret = dev->em28xx_read_reg_req_len(dev, 0, EM28XX_R40_AC97LSB, - (u8 *)&val, sizeof(val)); - - if (ret < 0) - return ret; - return le16_to_cpu(val); -} -EXPORT_SYMBOL_GPL(em28xx_read_ac97); - -/* - * em28xx_write_ac97() - * write a 16 bit value to the specified AC97 address (LSB first!) - */ -int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val) -{ - int ret; - u8 addr = reg & 0x7f; - __le16 value; - - value = cpu_to_le16(val); - - ret = em28xx_is_ac97_ready(dev); - if (ret < 0) - return ret; - - ret = em28xx_write_regs(dev, EM28XX_R40_AC97LSB, (u8 *) &value, 2); - if (ret < 0) - return ret; - - ret = em28xx_write_regs(dev, EM28XX_R42_AC97ADDR, &addr, 1); - if (ret < 0) - return ret; - - return 0; -} -EXPORT_SYMBOL_GPL(em28xx_write_ac97); - -struct em28xx_vol_itable { - enum em28xx_amux mux; - u8 reg; -}; - -static struct em28xx_vol_itable inputs[] = { - { EM28XX_AMUX_VIDEO, AC97_VIDEO }, - { EM28XX_AMUX_LINE_IN, AC97_LINE }, - { EM28XX_AMUX_PHONE, AC97_PHONE }, - { EM28XX_AMUX_MIC, AC97_MIC }, - { EM28XX_AMUX_CD, AC97_CD }, - { EM28XX_AMUX_AUX, AC97_AUX }, - { EM28XX_AMUX_PCM_OUT, AC97_PCM }, -}; - -static int set_ac97_input(struct em28xx *dev) -{ - int ret, i; - enum em28xx_amux amux = dev->ctl_ainput; - - /* EM28XX_AMUX_VIDEO2 is a special case used to indicate that - em28xx should point to LINE IN, while AC97 should use VIDEO - */ - if (amux == EM28XX_AMUX_VIDEO2) - amux = EM28XX_AMUX_VIDEO; - - /* Mute all entres but the one that were selected */ - for (i = 0; i < ARRAY_SIZE(inputs); i++) { - if (amux == inputs[i].mux) - ret = em28xx_write_ac97(dev, inputs[i].reg, 0x0808); - else - ret = em28xx_write_ac97(dev, inputs[i].reg, 0x8000); - - if (ret < 0) - em28xx_warn("couldn't setup AC97 register %d\n", - inputs[i].reg); - } - return 0; -} - -static int em28xx_set_audio_source(struct em28xx *dev) -{ - int ret; - u8 input; - - if (dev->board.is_em2800) { - if (dev->ctl_ainput == EM28XX_AMUX_VIDEO) - input = EM2800_AUDIO_SRC_TUNER; - else - input = EM2800_AUDIO_SRC_LINE; - - ret = em28xx_write_regs(dev, EM2800_R08_AUDIOSRC, &input, 1); - if (ret < 0) - return ret; - } - - if (dev->board.has_msp34xx) - input = EM28XX_AUDIO_SRC_TUNER; - else { - switch (dev->ctl_ainput) { - case EM28XX_AMUX_VIDEO: - input = EM28XX_AUDIO_SRC_TUNER; - break; - default: - input = EM28XX_AUDIO_SRC_LINE; - break; - } - } - - if (dev->board.mute_gpio && dev->mute) - em28xx_gpio_set(dev, dev->board.mute_gpio); - else - em28xx_gpio_set(dev, INPUT(dev->ctl_input)->gpio); - - ret = em28xx_write_reg_bits(dev, EM28XX_R0E_AUDIOSRC, input, 0xc0); - if (ret < 0) - return ret; - msleep(5); - - switch (dev->audio_mode.ac97) { - case EM28XX_NO_AC97: - break; - default: - ret = set_ac97_input(dev); - } - - return ret; -} - -struct em28xx_vol_otable { - enum em28xx_aout mux; - u8 reg; -}; - -static const struct em28xx_vol_otable outputs[] = { - { EM28XX_AOUT_MASTER, AC97_MASTER }, - { EM28XX_AOUT_LINE, AC97_HEADPHONE }, - { EM28XX_AOUT_MONO, AC97_MASTER_MONO }, - { EM28XX_AOUT_LFE, AC97_CENTER_LFE_MASTER }, - { EM28XX_AOUT_SURR, AC97_SURROUND_MASTER }, -}; - -int em28xx_audio_analog_set(struct em28xx *dev) -{ - int ret, i; - u8 xclk; - - if (!dev->audio_mode.has_audio) - return 0; - - /* It is assumed that all devices use master volume for output. - It would be possible to use also line output. - */ - if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { - /* Mute all outputs */ - for (i = 0; i < ARRAY_SIZE(outputs); i++) { - ret = em28xx_write_ac97(dev, outputs[i].reg, 0x8000); - if (ret < 0) - em28xx_warn("couldn't setup AC97 register %d\n", - outputs[i].reg); - } - } - - xclk = dev->board.xclk & 0x7f; - if (!dev->mute) - xclk |= EM28XX_XCLK_AUDIO_UNMUTE; - - ret = em28xx_write_reg(dev, EM28XX_R0F_XCLK, xclk); - if (ret < 0) - return ret; - msleep(10); - - /* Selects the proper audio input */ - ret = em28xx_set_audio_source(dev); - - /* Sets volume */ - if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { - int vol; - - em28xx_write_ac97(dev, AC97_POWERDOWN, 0x4200); - em28xx_write_ac97(dev, AC97_EXTENDED_STATUS, 0x0031); - em28xx_write_ac97(dev, AC97_PCM_LR_ADC_RATE, 0xbb80); - - /* LSB: left channel - both channels with the same level */ - vol = (0x1f - dev->volume) | ((0x1f - dev->volume) << 8); - - /* Mute device, if needed */ - if (dev->mute) - vol |= 0x8000; - - /* Sets volume */ - for (i = 0; i < ARRAY_SIZE(outputs); i++) { - if (dev->ctl_aoutput & outputs[i].mux) - ret = em28xx_write_ac97(dev, outputs[i].reg, - vol); - if (ret < 0) - em28xx_warn("couldn't setup AC97 register %d\n", - outputs[i].reg); - } - - if (dev->ctl_aoutput & EM28XX_AOUT_PCM_IN) { - int sel = ac97_return_record_select(dev->ctl_aoutput); - - /* Use the same input for both left and right - channels */ - sel |= (sel << 8); - - em28xx_write_ac97(dev, AC97_REC_SEL, sel); - } - } - - return ret; -} -EXPORT_SYMBOL_GPL(em28xx_audio_analog_set); - -int em28xx_audio_setup(struct em28xx *dev) -{ - int vid1, vid2, feat, cfg; - u32 vid; - - if (dev->chip_id == CHIP_ID_EM2870 || dev->chip_id == CHIP_ID_EM2874 - || dev->chip_id == CHIP_ID_EM28174) { - /* Digital only device - don't load any alsa module */ - dev->audio_mode.has_audio = false; - dev->has_audio_class = false; - dev->has_alsa_audio = false; - return 0; - } - - dev->audio_mode.has_audio = true; - - /* See how this device is configured */ - cfg = em28xx_read_reg(dev, EM28XX_R00_CHIPCFG); - em28xx_info("Config register raw data: 0x%02x\n", cfg); - if (cfg < 0) { - /* Register read error? */ - cfg = EM28XX_CHIPCFG_AC97; /* Be conservative */ - } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == 0x00) { - /* The device doesn't have vendor audio at all */ - dev->has_alsa_audio = false; - dev->audio_mode.has_audio = false; - return 0; - } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == - EM28XX_CHIPCFG_I2S_3_SAMPRATES) { - em28xx_info("I2S Audio (3 sample rates)\n"); - dev->audio_mode.i2s_3rates = 1; - } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == - EM28XX_CHIPCFG_I2S_5_SAMPRATES) { - em28xx_info("I2S Audio (5 sample rates)\n"); - dev->audio_mode.i2s_5rates = 1; - } - - if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) != EM28XX_CHIPCFG_AC97) { - /* Skip the code that does AC97 vendor detection */ - dev->audio_mode.ac97 = EM28XX_NO_AC97; - goto init_audio; - } - - dev->audio_mode.ac97 = EM28XX_AC97_OTHER; - - vid1 = em28xx_read_ac97(dev, AC97_VENDOR_ID1); - if (vid1 < 0) { - /* - * Device likely doesn't support AC97 - * Note: (some) em2800 devices without eeprom reports 0x91 on - * CHIPCFG register, even not having an AC97 chip - */ - em28xx_warn("AC97 chip type couldn't be determined\n"); - dev->audio_mode.ac97 = EM28XX_NO_AC97; - dev->has_alsa_audio = false; - dev->audio_mode.has_audio = false; - goto init_audio; - } - - vid2 = em28xx_read_ac97(dev, AC97_VENDOR_ID2); - if (vid2 < 0) - goto init_audio; - - vid = vid1 << 16 | vid2; - - dev->audio_mode.ac97_vendor_id = vid; - em28xx_warn("AC97 vendor ID = 0x%08x\n", vid); - - feat = em28xx_read_ac97(dev, AC97_RESET); - if (feat < 0) - goto init_audio; - - dev->audio_mode.ac97_feat = feat; - em28xx_warn("AC97 features = 0x%04x\n", feat); - - /* Try to identify what audio processor we have */ - if (((vid == 0xffffffff) || (vid == 0x83847650)) && (feat == 0x6a90)) - dev->audio_mode.ac97 = EM28XX_AC97_EM202; - else if ((vid >> 8) == 0x838476) - dev->audio_mode.ac97 = EM28XX_AC97_SIGMATEL; - -init_audio: - /* Reports detected AC97 processor */ - switch (dev->audio_mode.ac97) { - case EM28XX_NO_AC97: - em28xx_info("No AC97 audio processor\n"); - break; - case EM28XX_AC97_EM202: - em28xx_info("Empia 202 AC97 audio processor detected\n"); - break; - case EM28XX_AC97_SIGMATEL: - em28xx_info("Sigmatel audio processor detected(stac 97%02x)\n", - dev->audio_mode.ac97_vendor_id & 0xff); - break; - case EM28XX_AC97_OTHER: - em28xx_warn("Unknown AC97 audio processor detected!\n"); - break; - default: - break; - } - - return em28xx_audio_analog_set(dev); -} -EXPORT_SYMBOL_GPL(em28xx_audio_setup); - -int em28xx_colorlevels_set_default(struct em28xx *dev) -{ - em28xx_write_reg(dev, EM28XX_R20_YGAIN, 0x10); /* contrast */ - em28xx_write_reg(dev, EM28XX_R21_YOFFSET, 0x00); /* brightness */ - em28xx_write_reg(dev, EM28XX_R22_UVGAIN, 0x10); /* saturation */ - em28xx_write_reg(dev, EM28XX_R23_UOFFSET, 0x00); - em28xx_write_reg(dev, EM28XX_R24_VOFFSET, 0x00); - em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, 0x00); - - em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20); - em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20); - em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20); - em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20); - em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00); - em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00); - return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00); -} - -int em28xx_capture_start(struct em28xx *dev, int start) -{ - int rc; - - if (dev->chip_id == CHIP_ID_EM2874 || - dev->chip_id == CHIP_ID_EM2884 || - dev->chip_id == CHIP_ID_EM28174) { - /* The Transport Stream Enable Register moved in em2874 */ - if (!start) { - rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE, - 0x00, - EM2874_TS1_CAPTURE_ENABLE); - return rc; - } - - /* Enable Transport Stream */ - rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE, - EM2874_TS1_CAPTURE_ENABLE, - EM2874_TS1_CAPTURE_ENABLE); - return rc; - } - - - /* FIXME: which is the best order? */ - /* video registers are sampled by VREF */ - rc = em28xx_write_reg_bits(dev, EM28XX_R0C_USBSUSP, - start ? 0x10 : 0x00, 0x10); - if (rc < 0) - return rc; - - if (!start) { - /* disable video capture */ - rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x27); - return rc; - } - - if (dev->board.is_webcam) - rc = em28xx_write_reg(dev, 0x13, 0x0c); - - /* enable video capture */ - rc = em28xx_write_reg(dev, 0x48, 0x00); - - if (dev->mode == EM28XX_ANALOG_MODE) - rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67); - else - rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37); - - msleep(6); - - return rc; -} - -int em28xx_vbi_supported(struct em28xx *dev) -{ - /* Modprobe option to manually disable */ - if (disable_vbi == 1) - return 0; - - if (dev->chip_id == CHIP_ID_EM2860 || - dev->chip_id == CHIP_ID_EM2883) - return 1; - - /* Version of em28xx that does not support VBI */ - return 0; -} - -int em28xx_set_outfmt(struct em28xx *dev) -{ - int ret; - u8 vinctrl; - - ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, - dev->format->reg | 0x20, 0xff); - if (ret < 0) - return ret; - - ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode); - if (ret < 0) - return ret; - - vinctrl = dev->vinctl; - if (em28xx_vbi_supported(dev) == 1) { - vinctrl |= EM28XX_VINCTRL_VBI_RAW; - em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00); - em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, dev->vbi_width/4); - em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, dev->vbi_height); - if (dev->norm & V4L2_STD_525_60) { - /* NTSC */ - em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09); - } else if (dev->norm & V4L2_STD_625_50) { - /* PAL */ - em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07); - } - } - - return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl); -} - -static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, - u8 ymin, u8 ymax) -{ - em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n", - xmin, ymin, xmax, ymax); - - em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1); - em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1); - em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1); - return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1); -} - -static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart, - u16 width, u16 height) -{ - u8 cwidth = width; - u8 cheight = height; - u8 overflow = (height >> 7 & 0x02) | (width >> 8 & 0x01); - - em28xx_coredbg("em28xx Area Set: (%d,%d)\n", - (width | (overflow & 2) << 7), - (height | (overflow & 1) << 8)); - - em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1); - em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1); - em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1); - em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1); - return em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1); -} - -static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) -{ - u8 mode; - /* the em2800 scaler only supports scaling down to 50% */ - - if (dev->board.is_em2800) { - mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); - } else { - u8 buf[2]; - - buf[0] = h; - buf[1] = h >> 8; - em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2); - - buf[0] = v; - buf[1] = v >> 8; - em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2); - /* it seems that both H and V scalers must be active - to work correctly */ - mode = (h || v) ? 0x30 : 0x00; - } - return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30); -} - -/* FIXME: this only function read values from dev */ -int em28xx_resolution_set(struct em28xx *dev) -{ - int width, height; - width = norm_maxw(dev); - height = norm_maxh(dev); - - /* Properly setup VBI */ - dev->vbi_width = 720; - if (dev->norm & V4L2_STD_525_60) - dev->vbi_height = 12; - else - dev->vbi_height = 18; - - em28xx_set_outfmt(dev); - - em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); - - /* If we don't set the start position to 2 in VBI mode, we end up - with line 20/21 being YUYV encoded instead of being in 8-bit - greyscale. The core of the issue is that line 21 (and line 23 for - PAL WSS) are inside of active video region, and as a result they - get the pixelformatting associated with that area. So by cropping - it out, we end up with the same format as the rest of the VBI - region */ - if (em28xx_vbi_supported(dev) == 1) - em28xx_capture_area_set(dev, 0, 2, width >> 2, height >> 2); - else - em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); - - return em28xx_scaler_set(dev, dev->hscale, dev->vscale); -} - -int em28xx_set_alternate(struct em28xx *dev) -{ - int errCode, prev_alt = dev->alt; - int i; - unsigned int min_pkt_size = dev->width * 2 + 4; - - /* - * alt = 0 is used only for control messages, so, only values - * greater than 0 can be used for streaming. - */ - if (alt && alt < dev->num_alt) { - em28xx_coredbg("alternate forced to %d\n", dev->alt); - dev->alt = alt; - goto set_alt; - } - - /* When image size is bigger than a certain value, - the frame size should be increased, otherwise, only - green screen will be received. - */ - if (dev->width * 2 * dev->height > 720 * 240 * 2) - min_pkt_size *= 2; - - for (i = 0; i < dev->num_alt; i++) { - /* stop when the selected alt setting offers enough bandwidth */ - if (dev->alt_max_pkt_size[i] >= min_pkt_size) { - dev->alt = i; - break; - /* otherwise make sure that we end up with the maximum bandwidth - because the min_pkt_size equation might be wrong... - */ - } else if (dev->alt_max_pkt_size[i] > - dev->alt_max_pkt_size[dev->alt]) - dev->alt = i; - } - -set_alt: - if (dev->alt != prev_alt) { - em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n", - min_pkt_size, dev->alt); - dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt]; - em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n", - dev->alt, dev->max_pkt_size); - errCode = usb_set_interface(dev->udev, 0, dev->alt); - if (errCode < 0) { - em28xx_errdev("cannot change alternate number to %d (error=%i)\n", - dev->alt, errCode); - return errCode; - } - } - return 0; -} - -int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio) -{ - int rc = 0; - - if (!gpio) - return rc; - - if (dev->mode != EM28XX_SUSPEND) { - em28xx_write_reg(dev, 0x48, 0x00); - if (dev->mode == EM28XX_ANALOG_MODE) - em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67); - else - em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37); - msleep(6); - } - - /* Send GPIO reset sequences specified at board entry */ - while (gpio->sleep >= 0) { - if (gpio->reg >= 0) { - rc = em28xx_write_reg_bits(dev, - gpio->reg, - gpio->val, - gpio->mask); - if (rc < 0) - return rc; - } - if (gpio->sleep > 0) - msleep(gpio->sleep); - - gpio++; - } - return rc; -} -EXPORT_SYMBOL_GPL(em28xx_gpio_set); - -int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode) -{ - if (dev->mode == set_mode) - return 0; - - if (set_mode == EM28XX_SUSPEND) { - dev->mode = set_mode; - - /* FIXME: add suspend support for ac97 */ - - return em28xx_gpio_set(dev, dev->board.suspend_gpio); - } - - dev->mode = set_mode; - - if (dev->mode == EM28XX_DIGITAL_MODE) - return em28xx_gpio_set(dev, dev->board.dvb_gpio); - else - return em28xx_gpio_set(dev, INPUT(dev->ctl_input)->gpio); -} -EXPORT_SYMBOL_GPL(em28xx_set_mode); - -/* ------------------------------------------------------------------ - URB control - ------------------------------------------------------------------*/ - -/* - * IRQ callback, called by URB callback - */ -static void em28xx_irq_callback(struct urb *urb) -{ - struct em28xx *dev = urb->context; - int i; - - switch (urb->status) { - case 0: /* success */ - case -ETIMEDOUT: /* NAK */ - break; - case -ECONNRESET: /* kill */ - case -ENOENT: - case -ESHUTDOWN: - return; - default: /* error */ - em28xx_isocdbg("urb completition error %d.\n", urb->status); - break; - } - - /* Copy data from URB */ - spin_lock(&dev->slock); - dev->isoc_ctl.isoc_copy(dev, urb); - spin_unlock(&dev->slock); - - /* Reset urb buffers */ - for (i = 0; i < urb->number_of_packets; i++) { - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = 0; - } - urb->status = 0; - - urb->status = usb_submit_urb(urb, GFP_ATOMIC); - if (urb->status) { - em28xx_isocdbg("urb resubmit failed (error=%i)\n", - urb->status); - } -} - -/* - * Stop and Deallocate URBs - */ -void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode) -{ - struct urb *urb; - struct em28xx_usb_isoc_bufs *isoc_bufs; - int i; - - em28xx_isocdbg("em28xx: called em28xx_uninit_isoc in mode %d\n", mode); - - if (mode == EM28XX_DIGITAL_MODE) - isoc_bufs = &dev->isoc_ctl.digital_bufs; - else - isoc_bufs = &dev->isoc_ctl.analog_bufs; - - for (i = 0; i < isoc_bufs->num_bufs; i++) { - urb = isoc_bufs->urb[i]; - if (urb) { - if (!irqs_disabled()) - usb_kill_urb(urb); - else - usb_unlink_urb(urb); - - if (isoc_bufs->transfer_buffer[i]) { - usb_free_coherent(dev->udev, - urb->transfer_buffer_length, - isoc_bufs->transfer_buffer[i], - urb->transfer_dma); - } - usb_free_urb(urb); - isoc_bufs->urb[i] = NULL; - } - isoc_bufs->transfer_buffer[i] = NULL; - } - - kfree(isoc_bufs->urb); - kfree(isoc_bufs->transfer_buffer); - - isoc_bufs->urb = NULL; - isoc_bufs->transfer_buffer = NULL; - isoc_bufs->num_bufs = 0; - - em28xx_capture_start(dev, 0); -} -EXPORT_SYMBOL_GPL(em28xx_uninit_isoc); - -/* - * Stop URBs - */ -void em28xx_stop_urbs(struct em28xx *dev) -{ - int i; - struct urb *urb; - struct em28xx_usb_isoc_bufs *isoc_bufs = &dev->isoc_ctl.digital_bufs; - - em28xx_isocdbg("em28xx: called em28xx_stop_urbs\n"); - - for (i = 0; i < isoc_bufs->num_bufs; i++) { - urb = isoc_bufs->urb[i]; - if (urb) { - if (!irqs_disabled()) - usb_kill_urb(urb); - else - usb_unlink_urb(urb); - } - } - - em28xx_capture_start(dev, 0); -} -EXPORT_SYMBOL_GPL(em28xx_stop_urbs); - -/* - * Allocate URBs - */ -int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode, - int max_packets, int num_bufs, int max_pkt_size) -{ - struct em28xx_usb_isoc_bufs *isoc_bufs; - int i; - int sb_size, pipe; - struct urb *urb; - int j, k; - - em28xx_isocdbg("em28xx: called em28xx_alloc_isoc in mode %d\n", mode); - - if (mode == EM28XX_DIGITAL_MODE) - isoc_bufs = &dev->isoc_ctl.digital_bufs; - else - isoc_bufs = &dev->isoc_ctl.analog_bufs; - - /* De-allocates all pending stuff */ - em28xx_uninit_isoc(dev, mode); - - isoc_bufs->num_bufs = num_bufs; - - isoc_bufs->urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); - if (!isoc_bufs->urb) { - em28xx_errdev("cannot alloc memory for usb buffers\n"); - return -ENOMEM; - } - - isoc_bufs->transfer_buffer = kzalloc(sizeof(void *)*num_bufs, - GFP_KERNEL); - if (!isoc_bufs->transfer_buffer) { - em28xx_errdev("cannot allocate memory for usb transfer\n"); - kfree(isoc_bufs->urb); - return -ENOMEM; - } - - isoc_bufs->max_pkt_size = max_pkt_size; - isoc_bufs->num_packets = max_packets; - dev->isoc_ctl.vid_buf = NULL; - dev->isoc_ctl.vbi_buf = NULL; - - sb_size = isoc_bufs->num_packets * isoc_bufs->max_pkt_size; - - /* allocate urbs and transfer buffers */ - for (i = 0; i < isoc_bufs->num_bufs; i++) { - urb = usb_alloc_urb(isoc_bufs->num_packets, GFP_KERNEL); - if (!urb) { - em28xx_err("cannot alloc isoc_ctl.urb %i\n", i); - em28xx_uninit_isoc(dev, mode); - return -ENOMEM; - } - isoc_bufs->urb[i] = urb; - - isoc_bufs->transfer_buffer[i] = usb_alloc_coherent(dev->udev, - sb_size, GFP_KERNEL, &urb->transfer_dma); - if (!isoc_bufs->transfer_buffer[i]) { - em28xx_err("unable to allocate %i bytes for transfer" - " buffer %i%s\n", - sb_size, i, - in_interrupt() ? " while in int" : ""); - em28xx_uninit_isoc(dev, mode); - return -ENOMEM; - } - memset(isoc_bufs->transfer_buffer[i], 0, sb_size); - - /* FIXME: this is a hack - should be - 'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK' - should also be using 'desc.bInterval' - */ - pipe = usb_rcvisocpipe(dev->udev, - mode == EM28XX_ANALOG_MODE ? - EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL); - - usb_fill_int_urb(urb, dev->udev, pipe, - isoc_bufs->transfer_buffer[i], sb_size, - em28xx_irq_callback, dev, 1); - - urb->number_of_packets = isoc_bufs->num_packets; - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - - k = 0; - for (j = 0; j < isoc_bufs->num_packets; j++) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = - isoc_bufs->max_pkt_size; - k += isoc_bufs->max_pkt_size; - } - } - - return 0; -} -EXPORT_SYMBOL_GPL(em28xx_alloc_isoc); - -/* - * Allocate URBs and start IRQ - */ -int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode, - int max_packets, int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct em28xx *dev, struct urb *urb)) -{ - struct em28xx_dmaqueue *dma_q = &dev->vidq; - struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; - struct em28xx_usb_isoc_bufs *isoc_bufs; - int i; - int rc; - int alloc; - - em28xx_isocdbg("em28xx: called em28xx_init_isoc in mode %d\n", mode); - - dev->isoc_ctl.isoc_copy = isoc_copy; - - if (mode == EM28XX_DIGITAL_MODE) { - isoc_bufs = &dev->isoc_ctl.digital_bufs; - /* no need to free/alloc isoc buffers in digital mode */ - alloc = 0; - } else { - isoc_bufs = &dev->isoc_ctl.analog_bufs; - alloc = 1; - } - - if (alloc) { - rc = em28xx_alloc_isoc(dev, mode, max_packets, - num_bufs, max_pkt_size); - if (rc) - return rc; - } - - init_waitqueue_head(&dma_q->wq); - init_waitqueue_head(&vbi_dma_q->wq); - - em28xx_capture_start(dev, 1); - - /* submit urbs and enables IRQ */ - for (i = 0; i < isoc_bufs->num_bufs; i++) { - rc = usb_submit_urb(isoc_bufs->urb[i], GFP_ATOMIC); - if (rc) { - em28xx_err("submit of urb %i failed (error=%i)\n", i, - rc); - em28xx_uninit_isoc(dev, mode); - return rc; - } - } - - return 0; -} -EXPORT_SYMBOL_GPL(em28xx_init_isoc); - -/* - * em28xx_wake_i2c() - * configure i2c attached devices - */ -void em28xx_wake_i2c(struct em28xx *dev) -{ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0); - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, - INPUT(dev->ctl_input)->vmux, 0, 0); - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); -} - -/* - * Device control list - */ - -static LIST_HEAD(em28xx_devlist); -static DEFINE_MUTEX(em28xx_devlist_mutex); - -/* - * Extension interface - */ - -static LIST_HEAD(em28xx_extension_devlist); - -int em28xx_register_extension(struct em28xx_ops *ops) -{ - struct em28xx *dev = NULL; - - mutex_lock(&em28xx_devlist_mutex); - list_add_tail(&ops->next, &em28xx_extension_devlist); - list_for_each_entry(dev, &em28xx_devlist, devlist) { - ops->init(dev); - } - mutex_unlock(&em28xx_devlist_mutex); - printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); - return 0; -} -EXPORT_SYMBOL(em28xx_register_extension); - -void em28xx_unregister_extension(struct em28xx_ops *ops) -{ - struct em28xx *dev = NULL; - - mutex_lock(&em28xx_devlist_mutex); - list_for_each_entry(dev, &em28xx_devlist, devlist) { - ops->fini(dev); - } - list_del(&ops->next); - mutex_unlock(&em28xx_devlist_mutex); - printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); -} -EXPORT_SYMBOL(em28xx_unregister_extension); - -void em28xx_init_extension(struct em28xx *dev) -{ - const struct em28xx_ops *ops = NULL; - - mutex_lock(&em28xx_devlist_mutex); - list_add_tail(&dev->devlist, &em28xx_devlist); - list_for_each_entry(ops, &em28xx_extension_devlist, next) { - if (ops->init) - ops->init(dev); - } - mutex_unlock(&em28xx_devlist_mutex); -} - -void em28xx_close_extension(struct em28xx *dev) -{ - const struct em28xx_ops *ops = NULL; - - mutex_lock(&em28xx_devlist_mutex); - list_for_each_entry(ops, &em28xx_extension_devlist, next) { - if (ops->fini) - ops->fini(dev); - } - list_del(&dev->devlist); - mutex_unlock(&em28xx_devlist_mutex); -} diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c deleted file mode 100644 index a16531fa937a..000000000000 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ /dev/null @@ -1,1197 +0,0 @@ -/* - DVB device driver for em28xx - - (c) 2008-2011 Mauro Carvalho Chehab <mchehab@infradead.org> - - (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com> - - Fixes for the driver to properly work with HVR-950 - - Fixes for the driver to properly work with Pinnacle PCTV HD Pro Stick - - Fixes for the driver to properly work with AMD ATI TV Wonder HD 600 - - (c) 2008 Aidan Thornton <makosoft@googlemail.com> - - Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by: - (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au> - (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] - - 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. - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/usb.h> - -#include "em28xx.h" -#include <media/v4l2-common.h> -#include <media/videobuf-vmalloc.h> -#include <media/tuner.h> -#include "tuner-simple.h" - -#include "lgdt330x.h" -#include "lgdt3305.h" -#include "zl10353.h" -#include "s5h1409.h" -#include "mt352.h" -#include "mt352_priv.h" /* FIXME */ -#include "tda1002x.h" -#include "tda18271.h" -#include "s921.h" -#include "drxd.h" -#include "cxd2820r.h" -#include "tda18271c2dd.h" -#include "drxk.h" -#include "tda10071.h" -#include "a8293.h" -#include "qt1010.h" - -MODULE_DESCRIPTION("driver for em28xx based DVB cards"); -MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); -MODULE_LICENSE("GPL"); - -static unsigned int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "enable debug messages [dvb]"); - -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - -#define dprintk(level, fmt, arg...) do { \ -if (debug >= level) \ - printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \ -} while (0) - -struct em28xx_dvb { - struct dvb_frontend *fe[2]; - - /* feed count management */ - struct mutex lock; - int nfeeds; - - /* general boilerplate stuff */ - struct dvb_adapter adapter; - struct dvb_demux demux; - struct dmxdev dmxdev; - struct dmx_frontend fe_hw; - struct dmx_frontend fe_mem; - struct dvb_net net; - - /* Due to DRX-K - probably need changes */ - int (*gate_ctrl)(struct dvb_frontend *, int); - struct semaphore pll_mutex; - bool dont_attach_fe1; -}; - - -static inline void print_err_status(struct em28xx *dev, - int packet, int status) -{ - char *errmsg = "Unknown"; - - switch (status) { - case -ENOENT: - errmsg = "unlinked synchronuously"; - break; - case -ECONNRESET: - errmsg = "unlinked asynchronuously"; - break; - case -ENOSR: - errmsg = "Buffer error (overrun)"; - break; - case -EPIPE: - errmsg = "Stalled (device not responding)"; - break; - case -EOVERFLOW: - errmsg = "Babble (bad cable?)"; - break; - case -EPROTO: - errmsg = "Bit-stuff error (bad cable?)"; - break; - case -EILSEQ: - errmsg = "CRC/Timeout (could be anything)"; - break; - case -ETIME: - errmsg = "Device does not respond"; - break; - } - if (packet < 0) { - dprintk(1, "URB status %d [%s].\n", status, errmsg); - } else { - dprintk(1, "URB packet %d, status %d [%s].\n", - packet, status, errmsg); - } -} - -static inline int em28xx_dvb_isoc_copy(struct em28xx *dev, struct urb *urb) -{ - int i; - - if (!dev) - return 0; - - if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) - return 0; - - if (urb->status < 0) { - print_err_status(dev, -1, urb->status); - if (urb->status == -ENOENT) - return 0; - } - - for (i = 0; i < urb->number_of_packets; i++) { - int status = urb->iso_frame_desc[i].status; - - if (status < 0) { - print_err_status(dev, i, status); - if (urb->iso_frame_desc[i].status != -EPROTO) - continue; - } - - dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer + - urb->iso_frame_desc[i].offset, - urb->iso_frame_desc[i].actual_length); - } - - return 0; -} - -static int em28xx_start_streaming(struct em28xx_dvb *dvb) -{ - int rc; - struct em28xx *dev = dvb->adapter.priv; - int max_dvb_packet_size; - - usb_set_interface(dev->udev, 0, dev->dvb_alt); - rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); - if (rc < 0) - return rc; - - max_dvb_packet_size = dev->dvb_max_pkt_size; - if (max_dvb_packet_size < 0) - return max_dvb_packet_size; - dprintk(1, "Using %d buffers each with %d x %d bytes\n", - EM28XX_DVB_NUM_BUFS, - EM28XX_DVB_MAX_PACKETS, - max_dvb_packet_size); - - return em28xx_init_isoc(dev, EM28XX_DIGITAL_MODE, - EM28XX_DVB_MAX_PACKETS, EM28XX_DVB_NUM_BUFS, - max_dvb_packet_size, em28xx_dvb_isoc_copy); -} - -static int em28xx_stop_streaming(struct em28xx_dvb *dvb) -{ - struct em28xx *dev = dvb->adapter.priv; - - em28xx_stop_urbs(dev); - - em28xx_set_mode(dev, EM28XX_SUSPEND); - - return 0; -} - -static int em28xx_start_feed(struct dvb_demux_feed *feed) -{ - struct dvb_demux *demux = feed->demux; - struct em28xx_dvb *dvb = demux->priv; - int rc, ret; - - if (!demux->dmx.frontend) - return -EINVAL; - - mutex_lock(&dvb->lock); - dvb->nfeeds++; - rc = dvb->nfeeds; - - if (dvb->nfeeds == 1) { - ret = em28xx_start_streaming(dvb); - if (ret < 0) - rc = ret; - } - - mutex_unlock(&dvb->lock); - return rc; -} - -static int em28xx_stop_feed(struct dvb_demux_feed *feed) -{ - struct dvb_demux *demux = feed->demux; - struct em28xx_dvb *dvb = demux->priv; - int err = 0; - - mutex_lock(&dvb->lock); - dvb->nfeeds--; - - if (0 == dvb->nfeeds) - err = em28xx_stop_streaming(dvb); - - mutex_unlock(&dvb->lock); - return err; -} - - - -/* ------------------------------------------------------------------ */ -static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) -{ - struct em28xx *dev = fe->dvb->priv; - - if (acquire) - return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); - else - return em28xx_set_mode(dev, EM28XX_SUSPEND); -} - -/* ------------------------------------------------------------------ */ - -static struct lgdt330x_config em2880_lgdt3303_dev = { - .demod_address = 0x0e, - .demod_chip = LGDT3303, -}; - -static struct lgdt3305_config em2870_lgdt3304_dev = { - .i2c_addr = 0x0e, - .demod_chip = LGDT3304, - .spectral_inversion = 1, - .deny_i2c_rptr = 1, - .mpeg_mode = LGDT3305_MPEG_PARALLEL, - .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, - .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, - .vsb_if_khz = 3250, - .qam_if_khz = 4000, -}; - -static struct s921_config sharp_isdbt = { - .demod_address = 0x30 >> 1 -}; - -static struct zl10353_config em28xx_zl10353_with_xc3028 = { - .demod_address = (0x1e >> 1), - .no_tuner = 1, - .parallel_ts = 1, - .if2 = 45600, -}; - -static struct s5h1409_config em28xx_s5h1409_with_xc3028 = { - .demod_address = 0x32 >> 1, - .output_mode = S5H1409_PARALLEL_OUTPUT, - .gpio = S5H1409_GPIO_OFF, - .inversion = S5H1409_INVERSION_OFF, - .status_mode = S5H1409_DEMODLOCKING, - .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK -}; - -static struct tda18271_std_map kworld_a340_std_map = { - .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 0, - .if_lvl = 1, .rfagc_top = 0x37, }, - .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 1, - .if_lvl = 1, .rfagc_top = 0x37, }, -}; - -static struct tda18271_config kworld_a340_config = { - .std_map = &kworld_a340_std_map, -}; - -static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = { - .demod_address = (0x1e >> 1), - .no_tuner = 1, - .disable_i2c_gate_ctrl = 1, - .parallel_ts = 1, - .if2 = 45600, -}; - -static struct drxd_config em28xx_drxd = { - .demod_address = 0x70, - .demod_revision = 0xa2, - .pll_type = DRXD_PLL_NONE, - .clock = 12000, - .insert_rs_byte = 1, - .IF = 42800000, - .disable_i2c_gate_ctrl = 1, -}; - -static struct drxk_config terratec_h5_drxk = { - .adr = 0x29, - .single_master = 1, - .no_i2c_bridge = 1, - .microcode_name = "dvb-usb-terratec-h5-drxk.fw", - .qam_demod_parameter_count = 2, -}; - -static struct drxk_config hauppauge_930c_drxk = { - .adr = 0x29, - .single_master = 1, - .no_i2c_bridge = 1, - .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw", - .chunk_size = 56, - .qam_demod_parameter_count = 2, -}; - -struct drxk_config terratec_htc_stick_drxk = { - .adr = 0x29, - .single_master = 1, - .no_i2c_bridge = 1, - .microcode_name = "dvb-usb-terratec-htc-stick-drxk.fw", - .chunk_size = 54, - .qam_demod_parameter_count = 2, - /* Required for the antenna_gpio to disable LNA. */ - .antenna_dvbt = true, - /* The windows driver uses the same. This will disable LNA. */ - .antenna_gpio = 0x6, -}; - -static struct drxk_config maxmedia_ub425_tc_drxk = { - .adr = 0x29, - .single_master = 1, - .no_i2c_bridge = 1, -}; - -static struct drxk_config pctv_520e_drxk = { - .adr = 0x29, - .single_master = 1, - .microcode_name = "dvb-demod-drxk-pctv.fw", - .qam_demod_parameter_count = 2, - .chunk_size = 58, - .antenna_dvbt = true, /* disable LNA */ - .antenna_gpio = (1 << 2), /* disable LNA */ -}; - -static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) -{ - struct em28xx_dvb *dvb = fe->sec_priv; - int status; - - if (!dvb) - return -EINVAL; - - if (enable) { - down(&dvb->pll_mutex); - status = dvb->gate_ctrl(fe, 1); - } else { - status = dvb->gate_ctrl(fe, 0); - up(&dvb->pll_mutex); - } - return status; -} - -static void hauppauge_hvr930c_init(struct em28xx *dev) -{ - int i; - - struct em28xx_reg_seq hauppauge_hvr930c_init[] = { - {EM2874_R80_GPIO, 0xff, 0xff, 0x65}, - {EM2874_R80_GPIO, 0xfb, 0xff, 0x32}, - {EM2874_R80_GPIO, 0xff, 0xff, 0xb8}, - { -1, -1, -1, -1}, - }; - struct em28xx_reg_seq hauppauge_hvr930c_end[] = { - {EM2874_R80_GPIO, 0xef, 0xff, 0x01}, - {EM2874_R80_GPIO, 0xaf, 0xff, 0x65}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x76}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x01}, - {EM2874_R80_GPIO, 0xcf, 0xff, 0x0b}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x40}, - - {EM2874_R80_GPIO, 0xcf, 0xff, 0x65}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x65}, - {EM2874_R80_GPIO, 0xcf, 0xff, 0x0b}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x65}, - - { -1, -1, -1, -1}, - }; - - struct { - unsigned char r[4]; - int len; - } regs[] = { - {{ 0x06, 0x02, 0x00, 0x31 }, 4}, - {{ 0x01, 0x02 }, 2}, - {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, - {{ 0x01, 0x00 }, 2}, - {{ 0x01, 0x00, 0xff, 0xaf }, 4}, - {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, - {{ 0x01, 0x00 }, 2}, - {{ 0x01, 0x00, 0x73, 0xaf }, 4}, - {{ 0x04, 0x00 }, 2}, - {{ 0x00, 0x04 }, 2}, - {{ 0x00, 0x04, 0x00, 0x0a }, 4}, - {{ 0x04, 0x14 }, 2}, - {{ 0x04, 0x14, 0x00, 0x00 }, 4}, - }; - - em28xx_gpio_set(dev, hauppauge_hvr930c_init); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); - msleep(10); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); - msleep(10); - - dev->i2c_client.addr = 0x82 >> 1; - - for (i = 0; i < ARRAY_SIZE(regs); i++) - i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); - em28xx_gpio_set(dev, hauppauge_hvr930c_end); - - msleep(100); - - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); - msleep(30); - - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45); - msleep(10); - -} - -static void terratec_h5_init(struct em28xx *dev) -{ - int i; - struct em28xx_reg_seq terratec_h5_init[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, - {EM2874_R80_GPIO, 0xf2, 0xff, 50}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, - { -1, -1, -1, -1}, - }; - struct em28xx_reg_seq terratec_h5_end[] = { - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, - {EM2874_R80_GPIO, 0xa6, 0xff, 50}, - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, - { -1, -1, -1, -1}, - }; - struct { - unsigned char r[4]; - int len; - } regs[] = { - {{ 0x06, 0x02, 0x00, 0x31 }, 4}, - {{ 0x01, 0x02 }, 2}, - {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, - {{ 0x01, 0x00 }, 2}, - {{ 0x01, 0x00, 0xff, 0xaf }, 4}, - {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, - {{ 0x01, 0x00 }, 2}, - {{ 0x01, 0x00, 0x73, 0xaf }, 4}, - {{ 0x04, 0x00 }, 2}, - {{ 0x00, 0x04 }, 2}, - {{ 0x00, 0x04, 0x00, 0x0a }, 4}, - {{ 0x04, 0x14 }, 2}, - {{ 0x04, 0x14, 0x00, 0x00 }, 4}, - }; - - em28xx_gpio_set(dev, terratec_h5_init); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); - msleep(10); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45); - msleep(10); - - dev->i2c_client.addr = 0x82 >> 1; - - for (i = 0; i < ARRAY_SIZE(regs); i++) - i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); - em28xx_gpio_set(dev, terratec_h5_end); -}; - -static void terratec_htc_stick_init(struct em28xx *dev) -{ - int i; - - /* - * GPIO configuration: - * 0xff: unknown (does not affect DVB-T). - * 0xf6: DRX-K (demodulator). - * 0xe6: unknown (does not affect DVB-T). - * 0xb6: unknown (does not affect DVB-T). - */ - struct em28xx_reg_seq terratec_htc_stick_init[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, - {EM2874_R80_GPIO, 0xe6, 0xff, 50}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, - { -1, -1, -1, -1}, - }; - struct em28xx_reg_seq terratec_htc_stick_end[] = { - {EM2874_R80_GPIO, 0xb6, 0xff, 100}, - {EM2874_R80_GPIO, 0xf6, 0xff, 50}, - { -1, -1, -1, -1}, - }; - - /* Init the analog decoder? */ - struct { - unsigned char r[4]; - int len; - } regs[] = { - {{ 0x06, 0x02, 0x00, 0x31 }, 4}, - {{ 0x01, 0x02 }, 2}, - {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, - {{ 0x01, 0x00 }, 2}, - {{ 0x01, 0x00, 0xff, 0xaf }, 4}, - }; - - em28xx_gpio_set(dev, terratec_htc_stick_init); - - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); - msleep(10); - em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); - msleep(10); - - dev->i2c_client.addr = 0x82 >> 1; - - for (i = 0; i < ARRAY_SIZE(regs); i++) - i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); - - em28xx_gpio_set(dev, terratec_htc_stick_end); -}; - -static void pctv_520e_init(struct em28xx *dev) -{ - /* - * Init AVF4910B analog decoder. Looks like I2C traffic to - * digital demodulator and tuner are routed via AVF4910B. - */ - int i; - struct { - unsigned char r[4]; - int len; - } regs[] = { - {{ 0x06, 0x02, 0x00, 0x31 }, 4}, - {{ 0x01, 0x02 }, 2}, - {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, - {{ 0x01, 0x00 }, 2}, - {{ 0x01, 0x00, 0xff, 0xaf }, 4}, - {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, - {{ 0x01, 0x00 }, 2}, - {{ 0x01, 0x00, 0x73, 0xaf }, 4}, - }; - - dev->i2c_client.addr = 0x82 >> 1; /* 0x41 */ - - for (i = 0; i < ARRAY_SIZE(regs); i++) - i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); -}; - -static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe) -{ - /* Values extracted from a USB trace of the Terratec Windows driver */ - static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x2c }; - static u8 reset[] = { RESET, 0x80 }; - static u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 }; - static u8 agc_cfg[] = { AGC_TARGET, 0x28, 0xa0 }; - static u8 input_freq_cfg[] = { INPUT_FREQ_1, 0x31, 0xb8 }; - static u8 rs_err_cfg[] = { RS_ERR_PER_1, 0x00, 0x4d }; - static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; - static u8 trl_nom_cfg[] = { TRL_NOMINAL_RATE_1, 0x64, 0x00 }; - static u8 tps_given_cfg[] = { TPS_GIVEN_1, 0x40, 0x80, 0x50 }; - static u8 tuner_go[] = { TUNER_GO, 0x01}; - - mt352_write(fe, clock_config, sizeof(clock_config)); - udelay(200); - mt352_write(fe, reset, sizeof(reset)); - mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); - mt352_write(fe, agc_cfg, sizeof(agc_cfg)); - mt352_write(fe, input_freq_cfg, sizeof(input_freq_cfg)); - mt352_write(fe, rs_err_cfg, sizeof(rs_err_cfg)); - mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); - mt352_write(fe, trl_nom_cfg, sizeof(trl_nom_cfg)); - mt352_write(fe, tps_given_cfg, sizeof(tps_given_cfg)); - mt352_write(fe, tuner_go, sizeof(tuner_go)); - return 0; -} - -static struct mt352_config terratec_xs_mt352_cfg = { - .demod_address = (0x1e >> 1), - .no_tuner = 1, - .if2 = 45600, - .demod_init = em28xx_mt352_terratec_xs_init, -}; - -static struct tda10023_config em28xx_tda10023_config = { - .demod_address = 0x0c, - .invert = 1, -}; - -static struct cxd2820r_config em28xx_cxd2820r_config = { - .i2c_address = (0xd8 >> 1), - .ts_mode = CXD2820R_TS_SERIAL, - - /* enable LNA for DVB-T, DVB-T2 and DVB-C */ - .gpio_dvbt[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, - .gpio_dvbt2[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, - .gpio_dvbc[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, -}; - -static struct tda18271_config em28xx_cxd2820r_tda18271_config = { - .output_opt = TDA18271_OUTPUT_LT_OFF, - .gate = TDA18271_GATE_DIGITAL, -}; - -static const struct tda10071_config em28xx_tda10071_config = { - .i2c_address = 0x55, /* (0xaa >> 1) */ - .i2c_wr_max = 64, - .ts_mode = TDA10071_TS_SERIAL, - .spec_inv = 0, - .xtal = 40444000, /* 40.444 MHz */ - .pll_multiplier = 20, -}; - -static const struct a8293_config em28xx_a8293_config = { - .i2c_addr = 0x08, /* (0x10 >> 1) */ -}; - -static struct zl10353_config em28xx_zl10353_no_i2c_gate_dev = { - .demod_address = (0x1e >> 1), - .disable_i2c_gate_ctrl = 1, - .no_tuner = 1, - .parallel_ts = 1, -}; -static struct qt1010_config em28xx_qt1010_config = { - .i2c_address = 0x62 - -}; - -/* ------------------------------------------------------------------ */ - -static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev) -{ - struct dvb_frontend *fe; - struct xc2028_config cfg; - - memset(&cfg, 0, sizeof(cfg)); - cfg.i2c_adap = &dev->i2c_adap; - cfg.i2c_addr = addr; - - if (!dev->dvb->fe[0]) { - em28xx_errdev("/2: dvb frontend not attached. " - "Can't attach xc3028\n"); - return -EINVAL; - } - - fe = dvb_attach(xc2028_attach, dev->dvb->fe[0], &cfg); - if (!fe) { - em28xx_errdev("/2: xc3028 attach failed\n"); - dvb_frontend_detach(dev->dvb->fe[0]); - dev->dvb->fe[0] = NULL; - return -EINVAL; - } - - em28xx_info("%s/2: xc3028 attached\n", dev->name); - - return 0; -} - -/* ------------------------------------------------------------------ */ - -static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module, - struct em28xx *dev, struct device *device) -{ - int result; - - mutex_init(&dvb->lock); - - /* register adapter */ - result = dvb_register_adapter(&dvb->adapter, dev->name, module, device, - adapter_nr); - if (result < 0) { - printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", - dev->name, result); - goto fail_adapter; - } - - /* Ensure all frontends negotiate bus access */ - dvb->fe[0]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; - if (dvb->fe[1]) - dvb->fe[1]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; - - dvb->adapter.priv = dev; - - /* register frontend */ - result = dvb_register_frontend(&dvb->adapter, dvb->fe[0]); - if (result < 0) { - printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", - dev->name, result); - goto fail_frontend0; - } - - /* register 2nd frontend */ - if (dvb->fe[1]) { - result = dvb_register_frontend(&dvb->adapter, dvb->fe[1]); - if (result < 0) { - printk(KERN_WARNING "%s: 2nd dvb_register_frontend failed (errno = %d)\n", - dev->name, result); - goto fail_frontend1; - } - } - - /* register demux stuff */ - dvb->demux.dmx.capabilities = - DMX_TS_FILTERING | DMX_SECTION_FILTERING | - DMX_MEMORY_BASED_FILTERING; - dvb->demux.priv = dvb; - dvb->demux.filternum = 256; - dvb->demux.feednum = 256; - dvb->demux.start_feed = em28xx_start_feed; - dvb->demux.stop_feed = em28xx_stop_feed; - - result = dvb_dmx_init(&dvb->demux); - if (result < 0) { - printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n", - dev->name, result); - goto fail_dmx; - } - - dvb->dmxdev.filternum = 256; - dvb->dmxdev.demux = &dvb->demux.dmx; - dvb->dmxdev.capabilities = 0; - result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); - if (result < 0) { - printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", - dev->name, result); - goto fail_dmxdev; - } - - dvb->fe_hw.source = DMX_FRONTEND_0; - result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); - if (result < 0) { - printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", - dev->name, result); - goto fail_fe_hw; - } - - dvb->fe_mem.source = DMX_MEMORY_FE; - result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); - if (result < 0) { - printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", - dev->name, result); - goto fail_fe_mem; - } - - result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); - if (result < 0) { - printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n", - dev->name, result); - goto fail_fe_conn; - } - - /* register network adapter */ - dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); - return 0; - -fail_fe_conn: - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); -fail_fe_mem: - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); -fail_fe_hw: - dvb_dmxdev_release(&dvb->dmxdev); -fail_dmxdev: - dvb_dmx_release(&dvb->demux); -fail_dmx: - if (dvb->fe[1]) - dvb_unregister_frontend(dvb->fe[1]); - dvb_unregister_frontend(dvb->fe[0]); -fail_frontend1: - if (dvb->fe[1]) - dvb_frontend_detach(dvb->fe[1]); -fail_frontend0: - dvb_frontend_detach(dvb->fe[0]); - dvb_unregister_adapter(&dvb->adapter); -fail_adapter: - return result; -} - -static void em28xx_unregister_dvb(struct em28xx_dvb *dvb) -{ - dvb_net_release(&dvb->net); - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); - dvb_dmxdev_release(&dvb->dmxdev); - dvb_dmx_release(&dvb->demux); - if (dvb->fe[1]) - dvb_unregister_frontend(dvb->fe[1]); - dvb_unregister_frontend(dvb->fe[0]); - if (dvb->fe[1] && !dvb->dont_attach_fe1) - dvb_frontend_detach(dvb->fe[1]); - dvb_frontend_detach(dvb->fe[0]); - dvb_unregister_adapter(&dvb->adapter); -} - -static int em28xx_dvb_init(struct em28xx *dev) -{ - int result = 0, mfe_shared = 0; - struct em28xx_dvb *dvb; - - if (!dev->board.has_dvb) { - /* This device does not support the extension */ - printk(KERN_INFO "em28xx_dvb: This device does not support the extension\n"); - return 0; - } - - dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); - - if (dvb == NULL) { - em28xx_info("em28xx_dvb: memory allocation failed\n"); - return -ENOMEM; - } - dev->dvb = dvb; - dvb->fe[0] = dvb->fe[1] = NULL; - - mutex_lock(&dev->lock); - em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); - /* init frontend */ - switch (dev->model) { - case EM2874_BOARD_LEADERSHIP_ISDBT: - dvb->fe[0] = dvb_attach(s921_attach, - &sharp_isdbt, &dev->i2c_adap); - - if (!dvb->fe[0]) { - result = -EINVAL; - goto out_free; - } - - break; - case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: - case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: - case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: - case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: - dvb->fe[0] = dvb_attach(lgdt330x_attach, - &em2880_lgdt3303_dev, - &dev->i2c_adap); - if (em28xx_attach_xc3028(0x61, dev) < 0) { - result = -EINVAL; - goto out_free; - } - break; - case EM2880_BOARD_KWORLD_DVB_310U: - dvb->fe[0] = dvb_attach(zl10353_attach, - &em28xx_zl10353_with_xc3028, - &dev->i2c_adap); - if (em28xx_attach_xc3028(0x61, dev) < 0) { - result = -EINVAL; - goto out_free; - } - break; - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: - case EM2882_BOARD_TERRATEC_HYBRID_XS: - case EM2880_BOARD_EMPIRE_DUAL_TV: - dvb->fe[0] = dvb_attach(zl10353_attach, - &em28xx_zl10353_xc3028_no_i2c_gate, - &dev->i2c_adap); - if (em28xx_attach_xc3028(0x61, dev) < 0) { - result = -EINVAL; - goto out_free; - } - break; - case EM2880_BOARD_TERRATEC_HYBRID_XS: - case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: - case EM2881_BOARD_PINNACLE_HYBRID_PRO: - case EM2882_BOARD_DIKOM_DK300: - case EM2882_BOARD_KWORLD_VS_DVBT: - dvb->fe[0] = dvb_attach(zl10353_attach, - &em28xx_zl10353_xc3028_no_i2c_gate, - &dev->i2c_adap); - if (dvb->fe[0] == NULL) { - /* This board could have either a zl10353 or a mt352. - If the chip id isn't for zl10353, try mt352 */ - dvb->fe[0] = dvb_attach(mt352_attach, - &terratec_xs_mt352_cfg, - &dev->i2c_adap); - } - - if (em28xx_attach_xc3028(0x61, dev) < 0) { - result = -EINVAL; - goto out_free; - } - break; - case EM2870_BOARD_KWORLD_355U: - dvb->fe[0] = dvb_attach(zl10353_attach, - &em28xx_zl10353_no_i2c_gate_dev, - &dev->i2c_adap); - if (dvb->fe[0] != NULL) - dvb_attach(qt1010_attach, dvb->fe[0], - &dev->i2c_adap, &em28xx_qt1010_config); - break; - case EM2883_BOARD_KWORLD_HYBRID_330U: - case EM2882_BOARD_EVGA_INDTUBE: - dvb->fe[0] = dvb_attach(s5h1409_attach, - &em28xx_s5h1409_with_xc3028, - &dev->i2c_adap); - if (em28xx_attach_xc3028(0x61, dev) < 0) { - result = -EINVAL; - goto out_free; - } - break; - case EM2882_BOARD_KWORLD_ATSC_315U: - dvb->fe[0] = dvb_attach(lgdt330x_attach, - &em2880_lgdt3303_dev, - &dev->i2c_adap); - if (dvb->fe[0] != NULL) { - if (!dvb_attach(simple_tuner_attach, dvb->fe[0], - &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) { - result = -EINVAL; - goto out_free; - } - } - break; - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: - case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E: - dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL, - &dev->i2c_adap, &dev->udev->dev); - if (em28xx_attach_xc3028(0x61, dev) < 0) { - result = -EINVAL; - goto out_free; - } - break; - case EM2870_BOARD_REDDO_DVB_C_USB_BOX: - /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */ - dvb->fe[0] = dvb_attach(tda10023_attach, - &em28xx_tda10023_config, - &dev->i2c_adap, 0x48); - if (dvb->fe[0]) { - if (!dvb_attach(simple_tuner_attach, dvb->fe[0], - &dev->i2c_adap, 0x60, TUNER_PHILIPS_CU1216L)) { - result = -EINVAL; - goto out_free; - } - } - break; - case EM2870_BOARD_KWORLD_A340: - dvb->fe[0] = dvb_attach(lgdt3305_attach, - &em2870_lgdt3304_dev, - &dev->i2c_adap); - if (dvb->fe[0] != NULL) - dvb_attach(tda18271_attach, dvb->fe[0], 0x60, - &dev->i2c_adap, &kworld_a340_config); - break; - case EM28174_BOARD_PCTV_290E: - dvb->fe[0] = dvb_attach(cxd2820r_attach, - &em28xx_cxd2820r_config, - &dev->i2c_adap); - if (dvb->fe[0]) { - /* FE 0 attach tuner */ - if (!dvb_attach(tda18271_attach, - dvb->fe[0], - 0x60, - &dev->i2c_adap, - &em28xx_cxd2820r_tda18271_config)) { - - dvb_frontend_detach(dvb->fe[0]); - result = -EINVAL; - goto out_free; - } - } - break; - case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C: - { - struct xc5000_config cfg; - hauppauge_hvr930c_init(dev); - - dvb->fe[0] = dvb_attach(drxk_attach, - &hauppauge_930c_drxk, &dev->i2c_adap); - if (!dvb->fe[0]) { - result = -EINVAL; - goto out_free; - } - /* FIXME: do we need a pll semaphore? */ - dvb->fe[0]->sec_priv = dvb; - sema_init(&dvb->pll_mutex, 1); - dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl; - dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; - - /* Attach xc5000 */ - memset(&cfg, 0, sizeof(cfg)); - cfg.i2c_address = 0x61; - cfg.if_khz = 4000; - - if (dvb->fe[0]->ops.i2c_gate_ctrl) - dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1); - if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap, - &cfg)) { - result = -EINVAL; - goto out_free; - } - if (dvb->fe[0]->ops.i2c_gate_ctrl) - dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); - - break; - } - case EM2884_BOARD_TERRATEC_H5: - terratec_h5_init(dev); - - dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap); - if (!dvb->fe[0]) { - result = -EINVAL; - goto out_free; - } - /* FIXME: do we need a pll semaphore? */ - dvb->fe[0]->sec_priv = dvb; - sema_init(&dvb->pll_mutex, 1); - dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl; - dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; - - /* Attach tda18271 to DVB-C frontend */ - if (dvb->fe[0]->ops.i2c_gate_ctrl) - dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1); - if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], &dev->i2c_adap, 0x60)) { - result = -EINVAL; - goto out_free; - } - if (dvb->fe[0]->ops.i2c_gate_ctrl) - dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); - - break; - case EM28174_BOARD_PCTV_460E: - /* attach demod */ - dvb->fe[0] = dvb_attach(tda10071_attach, - &em28xx_tda10071_config, &dev->i2c_adap); - - /* attach SEC */ - if (dvb->fe[0]) - dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap, - &em28xx_a8293_config); - break; - case EM2874_BOARD_MAXMEDIA_UB425_TC: - /* attach demodulator */ - dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk, - &dev->i2c_adap); - - if (dvb->fe[0]) { - /* disable I2C-gate */ - dvb->fe[0]->ops.i2c_gate_ctrl = NULL; - - /* attach tuner */ - if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], - &dev->i2c_adap, 0x60)) { - dvb_frontend_detach(dvb->fe[0]); - result = -EINVAL; - goto out_free; - } - } - - /* TODO: we need drx-3913k firmware in order to support DVB-T */ - em28xx_info("MaxMedia UB425-TC: only DVB-C supported by that " \ - "driver version\n"); - - break; - case EM2884_BOARD_PCTV_510E: - case EM2884_BOARD_PCTV_520E: - pctv_520e_init(dev); - - /* attach demodulator */ - dvb->fe[0] = dvb_attach(drxk_attach, &pctv_520e_drxk, - &dev->i2c_adap); - - if (dvb->fe[0]) { - /* attach tuner */ - if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, - &dev->i2c_adap, - &em28xx_cxd2820r_tda18271_config)) { - dvb_frontend_detach(dvb->fe[0]); - result = -EINVAL; - goto out_free; - } - } - break; - case EM2884_BOARD_CINERGY_HTC_STICK: - terratec_htc_stick_init(dev); - - /* attach demodulator */ - dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk, - &dev->i2c_adap); - if (!dvb->fe[0]) { - result = -EINVAL; - goto out_free; - } - - /* Attach the demodulator. */ - if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, - &dev->i2c_adap, - &em28xx_cxd2820r_tda18271_config)) { - result = -EINVAL; - goto out_free; - } - break; - default: - em28xx_errdev("/2: The frontend of your DVB/ATSC card" - " isn't supported yet\n"); - break; - } - if (NULL == dvb->fe[0]) { - em28xx_errdev("/2: frontend initialization failed\n"); - result = -EINVAL; - goto out_free; - } - /* define general-purpose callback pointer */ - dvb->fe[0]->callback = em28xx_tuner_callback; - if (dvb->fe[1]) - dvb->fe[1]->callback = em28xx_tuner_callback; - - /* register everything */ - result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); - - if (result < 0) - goto out_free; - - /* MFE lock */ - dvb->adapter.mfe_shared = mfe_shared; - - em28xx_info("Successfully loaded em28xx-dvb\n"); -ret: - em28xx_set_mode(dev, EM28XX_SUSPEND); - mutex_unlock(&dev->lock); - return result; - -out_free: - kfree(dvb); - dev->dvb = NULL; - goto ret; -} - -static inline void prevent_sleep(struct dvb_frontend_ops *ops) -{ - ops->set_voltage = NULL; - ops->sleep = NULL; - ops->tuner_ops.sleep = NULL; -} - -static int em28xx_dvb_fini(struct em28xx *dev) -{ - if (!dev->board.has_dvb) { - /* This device does not support the extension */ - return 0; - } - - if (dev->dvb) { - struct em28xx_dvb *dvb = dev->dvb; - - if (dev->state & DEV_DISCONNECTED) { - /* We cannot tell the device to sleep - * once it has been unplugged. */ - if (dvb->fe[0]) - prevent_sleep(&dvb->fe[0]->ops); - if (dvb->fe[1]) - prevent_sleep(&dvb->fe[1]->ops); - } - - em28xx_unregister_dvb(dvb); - kfree(dvb); - dev->dvb = NULL; - } - - return 0; -} - -static struct em28xx_ops dvb_ops = { - .id = EM28XX_DVB, - .name = "Em28xx dvb Extension", - .init = em28xx_dvb_init, - .fini = em28xx_dvb_fini, -}; - -static int __init em28xx_dvb_register(void) -{ - return em28xx_register_extension(&dvb_ops); -} - -static void __exit em28xx_dvb_unregister(void) -{ - em28xx_unregister_extension(&dvb_ops); -} - -module_init(em28xx_dvb_register); -module_exit(em28xx_dvb_unregister); diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c deleted file mode 100644 index 1683bd9d51ee..000000000000 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - em28xx-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices - - Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> - Markus Rechberger <mrechberger@gmail.com> - Mauro Carvalho Chehab <mchehab@infradead.org> - Sascha Sommer <saschasommer@freenet.de> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/usb.h> -#include <linux/i2c.h> - -#include "em28xx.h" -#include "tuner-xc2028.h" -#include <media/v4l2-common.h> -#include <media/tuner.h> - -/* ----------------------------------------------------------- */ - -static unsigned int i2c_scan; -module_param(i2c_scan, int, 0444); -MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); - -static unsigned int i2c_debug; -module_param(i2c_debug, int, 0644); -MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); - -#define dprintk2(lvl, fmt, args...) \ -do { \ - if (i2c_debug >= lvl) { \ - printk(KERN_DEBUG "%s at %s: " fmt, \ - dev->name, __func__ , ##args); \ - } \ -} while (0) - -/* - * em2800_i2c_send_max4() - * send up to 4 bytes to the i2c device - */ -static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr, - char *buf, int len) -{ - int ret; - int write_timeout; - unsigned char b2[6]; - BUG_ON(len < 1 || len > 4); - b2[5] = 0x80 + len - 1; - b2[4] = addr; - b2[3] = buf[0]; - if (len > 1) - b2[2] = buf[1]; - if (len > 2) - b2[1] = buf[2]; - if (len > 3) - b2[0] = buf[3]; - - ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); - if (ret != 2 + len) { - em28xx_warn("writing to i2c device failed (error=%i)\n", ret); - return -EIO; - } - for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; - write_timeout -= 5) { - ret = dev->em28xx_read_reg(dev, 0x05); - if (ret == 0x80 + len - 1) - return len; - msleep(5); - } - em28xx_warn("i2c write timed out\n"); - return -EIO; -} - -/* - * em2800_i2c_send_bytes() - */ -static int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf, - short len) -{ - char *bufPtr = buf; - int ret; - int wrcount = 0; - int count; - int maxLen = 4; - struct em28xx *dev = (struct em28xx *)data; - while (len > 0) { - count = (len > maxLen) ? maxLen : len; - ret = em2800_i2c_send_max4(dev, addr, bufPtr, count); - if (ret > 0) { - len -= count; - bufPtr += count; - wrcount += count; - } else - return (ret < 0) ? ret : -EFAULT; - } - return wrcount; -} - -/* - * em2800_i2c_check_for_device() - * check if there is a i2c_device at the supplied address - */ -static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr) -{ - char msg; - int ret; - int write_timeout; - msg = addr; - ret = dev->em28xx_write_regs(dev, 0x04, &msg, 1); - if (ret < 0) { - em28xx_warn("setting i2c device address failed (error=%i)\n", - ret); - return ret; - } - msg = 0x84; - ret = dev->em28xx_write_regs(dev, 0x05, &msg, 1); - if (ret < 0) { - em28xx_warn("preparing i2c read failed (error=%i)\n", ret); - return ret; - } - for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; - write_timeout -= 5) { - unsigned reg = dev->em28xx_read_reg(dev, 0x5); - - if (reg == 0x94) - return -ENODEV; - else if (reg == 0x84) - return 0; - msleep(5); - } - return -ENODEV; -} - -/* - * em2800_i2c_recv_bytes() - * read from the i2c device - */ -static int em2800_i2c_recv_bytes(struct em28xx *dev, unsigned char addr, - char *buf, int len) -{ - int ret; - /* check for the device and set i2c read address */ - ret = em2800_i2c_check_for_device(dev, addr); - if (ret) { - em28xx_warn - ("preparing read at i2c address 0x%x failed (error=%i)\n", - addr, ret); - return ret; - } - ret = dev->em28xx_read_reg_req_len(dev, 0x0, 0x3, buf, len); - if (ret < 0) { - em28xx_warn("reading from i2c device at 0x%x failed (error=%i)", - addr, ret); - return ret; - } - return ret; -} - -/* - * em28xx_i2c_send_bytes() - */ -static int em28xx_i2c_send_bytes(void *data, unsigned char addr, char *buf, - short len, int stop) -{ - int wrcount = 0; - struct em28xx *dev = (struct em28xx *)data; - int write_timeout, ret; - - wrcount = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len); - - /* Seems to be required after a write */ - for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; - write_timeout -= 5) { - ret = dev->em28xx_read_reg(dev, 0x05); - if (!ret) - break; - msleep(5); - } - - return wrcount; -} - -/* - * em28xx_i2c_recv_bytes() - * read a byte from the i2c device - */ -static int em28xx_i2c_recv_bytes(struct em28xx *dev, unsigned char addr, - char *buf, int len) -{ - int ret; - ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len); - if (ret < 0) { - em28xx_warn("reading i2c device failed (error=%i)\n", ret); - return ret; - } - if (dev->em28xx_read_reg(dev, 0x5) != 0) - return -ENODEV; - return ret; -} - -/* - * em28xx_i2c_check_for_device() - * check if there is a i2c_device at the supplied address - */ -static int em28xx_i2c_check_for_device(struct em28xx *dev, unsigned char addr) -{ - int ret; - - ret = dev->em28xx_read_reg_req(dev, 2, addr); - if (ret < 0) { - em28xx_warn("reading from i2c device failed (error=%i)\n", ret); - return ret; - } - if (dev->em28xx_read_reg(dev, 0x5) != 0) - return -ENODEV; - return 0; -} - -/* - * em28xx_i2c_xfer() - * the main i2c transfer function - */ -static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msgs[], int num) -{ - struct em28xx *dev = i2c_adap->algo_data; - int addr, rc, i, byte; - - if (num <= 0) - return 0; - for (i = 0; i < num; i++) { - addr = msgs[i].addr << 1; - dprintk2(2, "%s %s addr=%x len=%d:", - (msgs[i].flags & I2C_M_RD) ? "read" : "write", - i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); - if (!msgs[i].len) { /* no len: check only for device presence */ - if (dev->board.is_em2800) - rc = em2800_i2c_check_for_device(dev, addr); - else - rc = em28xx_i2c_check_for_device(dev, addr); - if (rc < 0) { - dprintk2(2, " no device\n"); - return rc; - } - - } else if (msgs[i].flags & I2C_M_RD) { - /* read bytes */ - if (dev->board.is_em2800) - rc = em2800_i2c_recv_bytes(dev, addr, - msgs[i].buf, - msgs[i].len); - else - rc = em28xx_i2c_recv_bytes(dev, addr, - msgs[i].buf, - msgs[i].len); - if (i2c_debug >= 2) { - for (byte = 0; byte < msgs[i].len; byte++) - printk(" %02x", msgs[i].buf[byte]); - } - } else { - /* write bytes */ - if (i2c_debug >= 2) { - for (byte = 0; byte < msgs[i].len; byte++) - printk(" %02x", msgs[i].buf[byte]); - } - if (dev->board.is_em2800) - rc = em2800_i2c_send_bytes(dev, addr, - msgs[i].buf, - msgs[i].len); - else - rc = em28xx_i2c_send_bytes(dev, addr, - msgs[i].buf, - msgs[i].len, - i == num - 1); - } - if (rc < 0) - goto err; - if (i2c_debug >= 2) - printk("\n"); - } - - return num; -err: - dprintk2(2, " ERROR: %i\n", rc); - return rc; -} - -/* based on linux/sunrpc/svcauth.h and linux/hash.h - * The original hash function returns a different value, if arch is x86_64 - * or i386. - */ -static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits) -{ - unsigned long hash = 0; - unsigned long l = 0; - int len = 0; - unsigned char c; - do { - if (len == length) { - c = (char)len; - len = -1; - } else - c = *buf++; - l = (l << 8) | c; - len++; - if ((len & (32 / 8 - 1)) == 0) - hash = ((hash^l) * 0x9e370001UL); - } while (len); - - return (hash >> (32 - bits)) & 0xffffffffUL; -} - -static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) -{ - unsigned char buf, *p = eedata; - struct em28xx_eeprom *em_eeprom = (void *)eedata; - int i, err, size = len, block; - - if (dev->chip_id == CHIP_ID_EM2874 || - dev->chip_id == CHIP_ID_EM28174 || - dev->chip_id == CHIP_ID_EM2884) { - /* Empia switched to a 16-bit addressable eeprom in newer - devices. While we could certainly write a routine to read - the eeprom, there is nothing of use in there that cannot be - accessed through registers, and there is the risk that we - could corrupt the eeprom (since a 16-bit read call is - interpreted as a write call by 8-bit eeproms). - */ - return 0; - } - - dev->i2c_client.addr = 0xa0 >> 1; - - /* Check if board has eeprom */ - err = i2c_master_recv(&dev->i2c_client, &buf, 0); - if (err < 0) { - em28xx_errdev("board has no eeprom\n"); - memset(eedata, 0, len); - return -ENODEV; - } - - buf = 0; - - err = i2c_master_send(&dev->i2c_client, &buf, 1); - if (err != 1) { - printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", - dev->name, err); - return err; - } - while (size > 0) { - if (size > 16) - block = 16; - else - block = size; - - if (block != - (err = i2c_master_recv(&dev->i2c_client, p, block))) { - printk(KERN_WARNING - "%s: i2c eeprom read error (err=%d)\n", - dev->name, err); - return err; - } - size -= block; - p += block; - } - for (i = 0; i < len; i++) { - if (0 == (i % 16)) - printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i); - printk(" %02x", eedata[i]); - if (15 == (i % 16)) - printk("\n"); - } - - if (em_eeprom->id == 0x9567eb1a) - dev->hash = em28xx_hash_mem(eedata, len, 32); - - printk(KERN_INFO "%s: EEPROM ID= 0x%08x, EEPROM hash = 0x%08lx\n", - dev->name, em_eeprom->id, dev->hash); - - printk(KERN_INFO "%s: EEPROM info:\n", dev->name); - - switch (em_eeprom->chip_conf >> 4 & 0x3) { - case 0: - printk(KERN_INFO "%s:\tNo audio on board.\n", dev->name); - break; - case 1: - printk(KERN_INFO "%s:\tAC97 audio (5 sample rates)\n", - dev->name); - break; - case 2: - printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n", - dev->name); - break; - case 3: - printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n", - dev->name); - break; - } - - if (em_eeprom->chip_conf & 1 << 3) - printk(KERN_INFO "%s:\tUSB Remote wakeup capable\n", dev->name); - - if (em_eeprom->chip_conf & 1 << 2) - printk(KERN_INFO "%s:\tUSB Self power capable\n", dev->name); - - switch (em_eeprom->chip_conf & 0x3) { - case 0: - printk(KERN_INFO "%s:\t500mA max power\n", dev->name); - break; - case 1: - printk(KERN_INFO "%s:\t400mA max power\n", dev->name); - break; - case 2: - printk(KERN_INFO "%s:\t300mA max power\n", dev->name); - break; - case 3: - printk(KERN_INFO "%s:\t200mA max power\n", dev->name); - break; - } - printk(KERN_INFO "%s:\tTable at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n", - dev->name, - em_eeprom->string_idx_table, - em_eeprom->string1, - em_eeprom->string2, - em_eeprom->string3); - - return 0; -} - -/* ----------------------------------------------------------- */ - -/* - * functionality() - */ -static u32 functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_SMBUS_EMUL; -} - -static struct i2c_algorithm em28xx_algo = { - .master_xfer = em28xx_i2c_xfer, - .functionality = functionality, -}; - -static struct i2c_adapter em28xx_adap_template = { - .owner = THIS_MODULE, - .name = "em28xx", - .algo = &em28xx_algo, -}; - -static struct i2c_client em28xx_client_template = { - .name = "em28xx internal", -}; - -/* ----------------------------------------------------------- */ - -/* - * i2c_devs - * incomplete list of known devices - */ -static char *i2c_devs[128] = { - [0x4a >> 1] = "saa7113h", - [0x52 >> 1] = "drxk", - [0x60 >> 1] = "remote IR sensor", - [0x8e >> 1] = "remote IR sensor", - [0x86 >> 1] = "tda9887", - [0x80 >> 1] = "msp34xx", - [0x88 >> 1] = "msp34xx", - [0xa0 >> 1] = "eeprom", - [0xb0 >> 1] = "tda9874", - [0xb8 >> 1] = "tvp5150a", - [0xba >> 1] = "webcam sensor or tvp5150a", - [0xc0 >> 1] = "tuner (analog)", - [0xc2 >> 1] = "tuner (analog)", - [0xc4 >> 1] = "tuner (analog)", - [0xc6 >> 1] = "tuner (analog)", -}; - -/* - * do_i2c_scan() - * check i2c address range for devices - */ -void em28xx_do_i2c_scan(struct em28xx *dev) -{ - u8 i2c_devicelist[128]; - unsigned char buf; - int i, rc; - - memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist)); - - for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) { - dev->i2c_client.addr = i; - rc = i2c_master_recv(&dev->i2c_client, &buf, 0); - if (rc < 0) - continue; - i2c_devicelist[i] = i; - printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n", - dev->name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); - } - - dev->i2c_hash = em28xx_hash_mem(i2c_devicelist, - ARRAY_SIZE(i2c_devicelist), 32); -} - -/* - * em28xx_i2c_register() - * register i2c bus - */ -int em28xx_i2c_register(struct em28xx *dev) -{ - int retval; - - BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg); - BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req); - dev->i2c_adap = em28xx_adap_template; - dev->i2c_adap.dev.parent = &dev->udev->dev; - strcpy(dev->i2c_adap.name, dev->name); - dev->i2c_adap.algo_data = dev; - i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); - - retval = i2c_add_adapter(&dev->i2c_adap); - if (retval < 0) { - em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n", - __func__, retval); - return retval; - } - - dev->i2c_client = em28xx_client_template; - dev->i2c_client.adapter = &dev->i2c_adap; - - retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); - if ((retval < 0) && (retval != -ENODEV)) { - em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n", - __func__, retval); - - return retval; - } - - if (i2c_scan) - em28xx_do_i2c_scan(dev); - - return 0; -} - -/* - * em28xx_i2c_unregister() - * unregister i2c_bus - */ -int em28xx_i2c_unregister(struct em28xx *dev) -{ - i2c_del_adapter(&dev->i2c_adap); - return 0; -} diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c deleted file mode 100644 index 97d36b4f19db..000000000000 --- a/drivers/media/video/em28xx/em28xx-input.c +++ /dev/null @@ -1,645 +0,0 @@ -/* - handle em28xx IR remotes via linux kernel input layer. - - Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> - Markus Rechberger <mrechberger@gmail.com> - Mauro Carvalho Chehab <mchehab@infradead.org> - Sascha Sommer <saschasommer@freenet.de> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/usb.h> -#include <linux/slab.h> - -#include "em28xx.h" - -#define EM28XX_SNAPSHOT_KEY KEY_CAMERA -#define EM28XX_SBUTTON_QUERY_INTERVAL 500 -#define EM28XX_R0C_USBSUSP_SNAPSHOT 0x20 - -static unsigned int ir_debug; -module_param(ir_debug, int, 0644); -MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); - -#define MODULE_NAME "em28xx" - -#define i2cdprintk(fmt, arg...) \ - if (ir_debug) { \ - printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ - } - -#define dprintk(fmt, arg...) \ - if (ir_debug) { \ - printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ - } - -/********************************************************** - Polling structure used by em28xx IR's - **********************************************************/ - -struct em28xx_ir_poll_result { - unsigned int toggle_bit:1; - unsigned int read_count:7; - u8 rc_address; - u8 rc_data[4]; /* 1 byte on em2860/2880, 4 on em2874 */ -}; - -struct em28xx_IR { - struct em28xx *dev; - struct rc_dev *rc; - char name[32]; - char phys[32]; - - /* poll external decoder */ - int polling; - struct delayed_work work; - unsigned int full_code:1; - unsigned int last_readcount; - - int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); -}; - -/********************************************************** - I2C IR based get keycodes - should be used with ir-kbd-i2c - **********************************************************/ - -static int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) -{ - unsigned char b; - - /* poll IR chip */ - if (1 != i2c_master_recv(ir->c, &b, 1)) { - i2cdprintk("read error\n"); - return -EIO; - } - - /* it seems that 0xFE indicates that a button is still hold - down, while 0xff indicates that no button is hold - down. 0xfe sequences are sometimes interrupted by 0xFF */ - - i2cdprintk("key %02x\n", b); - - if (b == 0xff) - return 0; - - if (b == 0xfe) - /* keep old data */ - return 1; - - *ir_key = b; - *ir_raw = b; - return 1; -} - -static int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) -{ - unsigned char buf[2]; - u16 code; - int size; - - /* poll IR chip */ - size = i2c_master_recv(ir->c, buf, sizeof(buf)); - - if (size != 2) - return -EIO; - - /* Does eliminate repeated parity code */ - if (buf[1] == 0xff) - return 0; - - ir->old = buf[1]; - - /* - * Rearranges bits to the right order. - * The bit order were determined experimentally by using - * The original Hauppauge Grey IR and another RC5 that uses addr=0x08 - * The RC5 code has 14 bits, but we've experimentally determined - * the meaning for only 11 bits. - * So, the code translation is not complete. Yet, it is enough to - * work with the provided RC5 IR. - */ - code = - ((buf[0] & 0x01) ? 0x0020 : 0) | /* 0010 0000 */ - ((buf[0] & 0x02) ? 0x0010 : 0) | /* 0001 0000 */ - ((buf[0] & 0x04) ? 0x0008 : 0) | /* 0000 1000 */ - ((buf[0] & 0x08) ? 0x0004 : 0) | /* 0000 0100 */ - ((buf[0] & 0x10) ? 0x0002 : 0) | /* 0000 0010 */ - ((buf[0] & 0x20) ? 0x0001 : 0) | /* 0000 0001 */ - ((buf[1] & 0x08) ? 0x1000 : 0) | /* 0001 0000 */ - ((buf[1] & 0x10) ? 0x0800 : 0) | /* 0000 1000 */ - ((buf[1] & 0x20) ? 0x0400 : 0) | /* 0000 0100 */ - ((buf[1] & 0x40) ? 0x0200 : 0) | /* 0000 0010 */ - ((buf[1] & 0x80) ? 0x0100 : 0); /* 0000 0001 */ - - i2cdprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x%02x)\n", - code, buf[1], buf[0]); - - /* return key */ - *ir_key = code; - *ir_raw = code; - return 1; -} - -static int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, - u32 *ir_raw) -{ - unsigned char buf[3]; - - /* poll IR chip */ - - if (3 != i2c_master_recv(ir->c, buf, 3)) { - i2cdprintk("read error\n"); - return -EIO; - } - - i2cdprintk("key %02x\n", buf[2]&0x3f); - if (buf[0] != 0x00) - return 0; - - *ir_key = buf[2]&0x3f; - *ir_raw = buf[2]&0x3f; - - return 1; -} - -static int em28xx_get_key_winfast_usbii_deluxe(struct IR_i2c *ir, u32 *ir_key, - u32 *ir_raw) -{ - unsigned char subaddr, keydetect, key; - - struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0, .buf = &subaddr, .len = 1}, - - { .addr = ir->c->addr, .flags = I2C_M_RD, .buf = &keydetect, .len = 1} }; - - subaddr = 0x10; - if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { - i2cdprintk("read error\n"); - return -EIO; - } - if (keydetect == 0x00) - return 0; - - subaddr = 0x00; - msg[1].buf = &key; - if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { - i2cdprintk("read error\n"); - return -EIO; - } - if (key == 0x00) - return 0; - - *ir_key = key; - *ir_raw = key; - return 1; -} - -/********************************************************** - Poll based get keycode functions - **********************************************************/ - -/* This is for the em2860/em2880 */ -static int default_polling_getkey(struct em28xx_IR *ir, - struct em28xx_ir_poll_result *poll_result) -{ - struct em28xx *dev = ir->dev; - int rc; - u8 msg[3] = { 0, 0, 0 }; - - /* Read key toggle, brand, and key code - on registers 0x45, 0x46 and 0x47 - */ - rc = dev->em28xx_read_reg_req_len(dev, 0, EM28XX_R45_IR, - msg, sizeof(msg)); - if (rc < 0) - return rc; - - /* Infrared toggle (Reg 0x45[7]) */ - poll_result->toggle_bit = (msg[0] >> 7); - - /* Infrared read count (Reg 0x45[6:0] */ - poll_result->read_count = (msg[0] & 0x7f); - - /* Remote Control Address (Reg 0x46) */ - poll_result->rc_address = msg[1]; - - /* Remote Control Data (Reg 0x47) */ - poll_result->rc_data[0] = msg[2]; - - return 0; -} - -static int em2874_polling_getkey(struct em28xx_IR *ir, - struct em28xx_ir_poll_result *poll_result) -{ - struct em28xx *dev = ir->dev; - int rc; - u8 msg[5] = { 0, 0, 0, 0, 0 }; - - /* Read key toggle, brand, and key code - on registers 0x51-55 - */ - rc = dev->em28xx_read_reg_req_len(dev, 0, EM2874_R51_IR, - msg, sizeof(msg)); - if (rc < 0) - return rc; - - /* Infrared toggle (Reg 0x51[7]) */ - poll_result->toggle_bit = (msg[0] >> 7); - - /* Infrared read count (Reg 0x51[6:0] */ - poll_result->read_count = (msg[0] & 0x7f); - - /* Remote Control Address (Reg 0x52) */ - poll_result->rc_address = msg[1]; - - /* Remote Control Data (Reg 0x53-55) */ - poll_result->rc_data[0] = msg[2]; - poll_result->rc_data[1] = msg[3]; - poll_result->rc_data[2] = msg[4]; - - return 0; -} - -/********************************************************** - Polling code for em28xx - **********************************************************/ - -static void em28xx_ir_handle_key(struct em28xx_IR *ir) -{ - int result; - struct em28xx_ir_poll_result poll_result; - - /* read the registers containing the IR status */ - result = ir->get_key(ir, &poll_result); - if (unlikely(result < 0)) { - dprintk("ir->get_key() failed %d\n", result); - return; - } - - if (unlikely(poll_result.read_count != ir->last_readcount)) { - dprintk("%s: toggle: %d, count: %d, key 0x%02x%02x\n", __func__, - poll_result.toggle_bit, poll_result.read_count, - poll_result.rc_address, poll_result.rc_data[0]); - if (ir->full_code) - rc_keydown(ir->rc, - poll_result.rc_address << 8 | - poll_result.rc_data[0], - poll_result.toggle_bit); - else - rc_keydown(ir->rc, - poll_result.rc_data[0], - poll_result.toggle_bit); - - if (ir->dev->chip_id == CHIP_ID_EM2874 || - ir->dev->chip_id == CHIP_ID_EM2884) - /* The em2874 clears the readcount field every time the - register is read. The em2860/2880 datasheet says that it - is supposed to clear the readcount, but it doesn't. So with - the em2874, we are looking for a non-zero read count as - opposed to a readcount that is incrementing */ - ir->last_readcount = 0; - else - ir->last_readcount = poll_result.read_count; - } -} - -static void em28xx_ir_work(struct work_struct *work) -{ - struct em28xx_IR *ir = container_of(work, struct em28xx_IR, work.work); - - em28xx_ir_handle_key(ir); - schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); -} - -static int em28xx_ir_start(struct rc_dev *rc) -{ - struct em28xx_IR *ir = rc->priv; - - INIT_DELAYED_WORK(&ir->work, em28xx_ir_work); - schedule_delayed_work(&ir->work, 0); - - return 0; -} - -static void em28xx_ir_stop(struct rc_dev *rc) -{ - struct em28xx_IR *ir = rc->priv; - - cancel_delayed_work_sync(&ir->work); -} - -static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type) -{ - int rc = 0; - struct em28xx_IR *ir = rc_dev->priv; - struct em28xx *dev = ir->dev; - u8 ir_config = EM2874_IR_RC5; - - /* Adjust xclk based o IR table for RC5/NEC tables */ - - if (rc_type == RC_TYPE_RC5) { - dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; - ir->full_code = 1; - } else if (rc_type == RC_TYPE_NEC) { - dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; - ir_config = EM2874_IR_NEC; - ir->full_code = 1; - } else if (rc_type != RC_TYPE_UNKNOWN) - rc = -EINVAL; - - em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, - EM28XX_XCLK_IR_RC5_MODE); - - /* Setup the proper handler based on the chip */ - switch (dev->chip_id) { - case CHIP_ID_EM2860: - case CHIP_ID_EM2883: - ir->get_key = default_polling_getkey; - break; - case CHIP_ID_EM2884: - case CHIP_ID_EM2874: - case CHIP_ID_EM28174: - ir->get_key = em2874_polling_getkey; - em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1); - break; - default: - printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n", - dev->chip_id); - rc = -EINVAL; - } - - return rc; -} - -static void em28xx_register_i2c_ir(struct em28xx *dev) -{ - /* Leadtek winfast tv USBII deluxe can find a non working IR-device */ - /* at address 0x18, so if that address is needed for another board in */ - /* the future, please put it after 0x1f. */ - struct i2c_board_info info; - const unsigned short addr_list[] = { - 0x1f, 0x30, 0x47, I2C_CLIENT_END - }; - - memset(&info, 0, sizeof(struct i2c_board_info)); - memset(&dev->init_data, 0, sizeof(dev->init_data)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); - - /* detect & configure */ - switch (dev->model) { - case EM2800_BOARD_TERRATEC_CINERGY_200: - case EM2820_BOARD_TERRATEC_CINERGY_250: - dev->init_data.ir_codes = RC_MAP_EM_TERRATEC; - dev->init_data.get_key = em28xx_get_key_terratec; - dev->init_data.name = "i2c IR (EM28XX Terratec)"; - break; - case EM2820_BOARD_PINNACLE_USB_2: - dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY; - dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey; - dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; - break; - case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: - dev->init_data.ir_codes = RC_MAP_HAUPPAUGE; - dev->init_data.get_key = em28xx_get_key_em_haup; - dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; - break; - case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: - dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE; - dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe; - dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)"; - break; - } - - if (dev->init_data.name) - info.platform_data = &dev->init_data; - i2c_new_probed_device(&dev->i2c_adap, &info, addr_list, NULL); -} - -/********************************************************** - Handle Webcam snapshot button - **********************************************************/ - -static void em28xx_query_sbutton(struct work_struct *work) -{ - /* Poll the register and see if the button is depressed */ - struct em28xx *dev = - container_of(work, struct em28xx, sbutton_query_work.work); - int ret; - - ret = em28xx_read_reg(dev, EM28XX_R0C_USBSUSP); - - if (ret & EM28XX_R0C_USBSUSP_SNAPSHOT) { - u8 cleared; - /* Button is depressed, clear the register */ - cleared = ((u8) ret) & ~EM28XX_R0C_USBSUSP_SNAPSHOT; - em28xx_write_regs(dev, EM28XX_R0C_USBSUSP, &cleared, 1); - - /* Not emulate the keypress */ - input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY, - 1); - /* Now unpress the key */ - input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY, - 0); - } - - /* Schedule next poll */ - schedule_delayed_work(&dev->sbutton_query_work, - msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL)); -} - -static void em28xx_register_snapshot_button(struct em28xx *dev) -{ - struct input_dev *input_dev; - int err; - - em28xx_info("Registering snapshot button...\n"); - input_dev = input_allocate_device(); - if (!input_dev) { - em28xx_errdev("input_allocate_device failed\n"); - return; - } - - usb_make_path(dev->udev, dev->snapshot_button_path, - sizeof(dev->snapshot_button_path)); - strlcat(dev->snapshot_button_path, "/sbutton", - sizeof(dev->snapshot_button_path)); - INIT_DELAYED_WORK(&dev->sbutton_query_work, em28xx_query_sbutton); - - input_dev->name = "em28xx snapshot button"; - input_dev->phys = dev->snapshot_button_path; - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); - set_bit(EM28XX_SNAPSHOT_KEY, input_dev->keybit); - input_dev->keycodesize = 0; - input_dev->keycodemax = 0; - input_dev->id.bustype = BUS_USB; - input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); - input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); - input_dev->id.version = 1; - input_dev->dev.parent = &dev->udev->dev; - - err = input_register_device(input_dev); - if (err) { - em28xx_errdev("input_register_device failed\n"); - input_free_device(input_dev); - return; - } - - dev->sbutton_input_dev = input_dev; - schedule_delayed_work(&dev->sbutton_query_work, - msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL)); - return; - -} - -static void em28xx_deregister_snapshot_button(struct em28xx *dev) -{ - if (dev->sbutton_input_dev != NULL) { - em28xx_info("Deregistering snapshot button\n"); - cancel_delayed_work_sync(&dev->sbutton_query_work); - input_unregister_device(dev->sbutton_input_dev); - dev->sbutton_input_dev = NULL; - } - return; -} - -static int em28xx_ir_init(struct em28xx *dev) -{ - struct em28xx_IR *ir; - struct rc_dev *rc; - int err = -ENOMEM; - - if (dev->board.ir_codes == NULL) { - /* No remote control support */ - em28xx_warn("Remote control support is not available for " - "this card.\n"); - return 0; - } - - ir = kzalloc(sizeof(*ir), GFP_KERNEL); - rc = rc_allocate_device(); - if (!ir || !rc) - goto err_out_free; - - /* record handles to ourself */ - ir->dev = dev; - dev->ir = ir; - ir->rc = rc; - - /* - * em2874 supports more protocols. For now, let's just announce - * the two protocols that were already tested - */ - rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC; - rc->priv = ir; - rc->change_protocol = em28xx_ir_change_protocol; - rc->open = em28xx_ir_start; - rc->close = em28xx_ir_stop; - - /* By default, keep protocol field untouched */ - err = em28xx_ir_change_protocol(rc, RC_TYPE_UNKNOWN); - if (err) - goto err_out_free; - - /* This is how often we ask the chip for IR information */ - ir->polling = 100; /* ms */ - - /* init input device */ - snprintf(ir->name, sizeof(ir->name), "em28xx IR (%s)", - dev->name); - - usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); - strlcat(ir->phys, "/input0", sizeof(ir->phys)); - - rc->input_name = ir->name; - rc->input_phys = ir->phys; - rc->input_id.bustype = BUS_USB; - rc->input_id.version = 1; - rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); - rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct); - rc->dev.parent = &dev->udev->dev; - rc->map_name = dev->board.ir_codes; - rc->driver_name = MODULE_NAME; - - /* all done */ - err = rc_register_device(rc); - if (err) - goto err_out_stop; - - em28xx_register_i2c_ir(dev); - -#if defined(CONFIG_MODULES) && defined(MODULE) - if (dev->board.has_ir_i2c) - request_module("ir-kbd-i2c"); -#endif - if (dev->board.has_snapshot_button) - em28xx_register_snapshot_button(dev); - - return 0; - - err_out_stop: - dev->ir = NULL; - err_out_free: - rc_free_device(rc); - kfree(ir); - return err; -} - -static int em28xx_ir_fini(struct em28xx *dev) -{ - struct em28xx_IR *ir = dev->ir; - - em28xx_deregister_snapshot_button(dev); - - /* skip detach on non attached boards */ - if (!ir) - return 0; - - if (ir->rc) - rc_unregister_device(ir->rc); - - /* done */ - kfree(ir); - dev->ir = NULL; - return 0; -} - -static struct em28xx_ops rc_ops = { - .id = EM28XX_RC, - .name = "Em28xx Input Extension", - .init = em28xx_ir_init, - .fini = em28xx_ir_fini, -}; - -static int __init em28xx_rc_register(void) -{ - return em28xx_register_extension(&rc_ops); -} - -static void __exit em28xx_rc_unregister(void) -{ - em28xx_unregister_extension(&rc_ops); -} - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); -MODULE_DESCRIPTION("Em28xx Input driver"); - -module_init(em28xx_rc_register); -module_exit(em28xx_rc_unregister); diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h deleted file mode 100644 index 6ff368297f6e..000000000000 --- a/drivers/media/video/em28xx/em28xx-reg.h +++ /dev/null @@ -1,226 +0,0 @@ -#define EM_GPIO_0 (1 << 0) -#define EM_GPIO_1 (1 << 1) -#define EM_GPIO_2 (1 << 2) -#define EM_GPIO_3 (1 << 3) -#define EM_GPIO_4 (1 << 4) -#define EM_GPIO_5 (1 << 5) -#define EM_GPIO_6 (1 << 6) -#define EM_GPIO_7 (1 << 7) - -#define EM_GPO_0 (1 << 0) -#define EM_GPO_1 (1 << 1) -#define EM_GPO_2 (1 << 2) -#define EM_GPO_3 (1 << 3) - -/* em28xx endpoints */ -#define EM28XX_EP_ANALOG 0x82 -#define EM28XX_EP_AUDIO 0x83 -#define EM28XX_EP_DIGITAL 0x84 - -/* em2800 registers */ -#define EM2800_R08_AUDIOSRC 0x08 - -/* em28xx registers */ - -#define EM28XX_R00_CHIPCFG 0x00 - -/* em28xx Chip Configuration 0x00 */ -#define EM28XX_CHIPCFG_VENDOR_AUDIO 0x80 -#define EM28XX_CHIPCFG_I2S_VOLUME_CAPABLE 0x40 -#define EM28XX_CHIPCFG_I2S_5_SAMPRATES 0x30 -#define EM28XX_CHIPCFG_I2S_3_SAMPRATES 0x20 -#define EM28XX_CHIPCFG_AC97 0x10 -#define EM28XX_CHIPCFG_AUDIOMASK 0x30 - -#define EM28XX_R01_CHIPCFG2 0x01 - -/* em28xx Chip Configuration 2 0x01 */ -#define EM28XX_CHIPCFG2_TS_PRESENT 0x10 -#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_MASK 0x0c /* bits 3-2 */ -#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_1MF 0x00 -#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_2MF 0x04 -#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_4MF 0x08 -#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_8MF 0x0c -#define EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK 0x03 /* bits 0-1 */ -#define EM28XX_CHIPCFG2_TS_PACKETSIZE_188 0x00 -#define EM28XX_CHIPCFG2_TS_PACKETSIZE_376 0x01 -#define EM28XX_CHIPCFG2_TS_PACKETSIZE_564 0x02 -#define EM28XX_CHIPCFG2_TS_PACKETSIZE_752 0x03 - - - /* GPIO/GPO registers */ -#define EM2880_R04_GPO 0x04 /* em2880-em2883 only */ -#define EM28XX_R08_GPIO 0x08 /* em2820 or upper */ - -#define EM28XX_R06_I2C_CLK 0x06 - -/* em28xx I2C Clock Register (0x06) */ -#define EM28XX_I2C_CLK_ACK_LAST_READ 0x80 -#define EM28XX_I2C_CLK_WAIT_ENABLE 0x40 -#define EM28XX_I2C_EEPROM_ON_BOARD 0x08 -#define EM28XX_I2C_EEPROM_KEY_VALID 0x04 -#define EM2874_I2C_SECONDARY_BUS_SELECT 0x04 /* em2874 has two i2c busses */ -#define EM28XX_I2C_FREQ_1_5_MHZ 0x03 /* bus frequency (bits [1-0]) */ -#define EM28XX_I2C_FREQ_25_KHZ 0x02 -#define EM28XX_I2C_FREQ_400_KHZ 0x01 -#define EM28XX_I2C_FREQ_100_KHZ 0x00 - - -#define EM28XX_R0A_CHIPID 0x0a -#define EM28XX_R0C_USBSUSP 0x0c /* */ - -#define EM28XX_R0E_AUDIOSRC 0x0e -#define EM28XX_R0F_XCLK 0x0f - -/* em28xx XCLK Register (0x0f) */ -#define EM28XX_XCLK_AUDIO_UNMUTE 0x80 /* otherwise audio muted */ -#define EM28XX_XCLK_I2S_MSB_TIMING 0x40 /* otherwise standard timing */ -#define EM28XX_XCLK_IR_RC5_MODE 0x20 /* otherwise NEC mode */ -#define EM28XX_XCLK_IR_NEC_CHK_PARITY 0x10 -#define EM28XX_XCLK_FREQUENCY_30MHZ 0x00 /* Freq. select (bits [3-0]) */ -#define EM28XX_XCLK_FREQUENCY_15MHZ 0x01 -#define EM28XX_XCLK_FREQUENCY_10MHZ 0x02 -#define EM28XX_XCLK_FREQUENCY_7_5MHZ 0x03 -#define EM28XX_XCLK_FREQUENCY_6MHZ 0x04 -#define EM28XX_XCLK_FREQUENCY_5MHZ 0x05 -#define EM28XX_XCLK_FREQUENCY_4_3MHZ 0x06 -#define EM28XX_XCLK_FREQUENCY_12MHZ 0x07 -#define EM28XX_XCLK_FREQUENCY_20MHZ 0x08 -#define EM28XX_XCLK_FREQUENCY_20MHZ_2 0x09 -#define EM28XX_XCLK_FREQUENCY_48MHZ 0x0a -#define EM28XX_XCLK_FREQUENCY_24MHZ 0x0b - -#define EM28XX_R10_VINMODE 0x10 - -#define EM28XX_R11_VINCTRL 0x11 - -/* em28xx Video Input Control Register 0x11 */ -#define EM28XX_VINCTRL_VBI_SLICED 0x80 -#define EM28XX_VINCTRL_VBI_RAW 0x40 -#define EM28XX_VINCTRL_VOUT_MODE_IN 0x20 /* HREF,VREF,VACT in output */ -#define EM28XX_VINCTRL_CCIR656_ENABLE 0x10 -#define EM28XX_VINCTRL_VBI_16BIT_RAW 0x08 /* otherwise 8-bit raw */ -#define EM28XX_VINCTRL_FID_ON_HREF 0x04 -#define EM28XX_VINCTRL_DUAL_EDGE_STROBE 0x02 -#define EM28XX_VINCTRL_INTERLACED 0x01 - -#define EM28XX_R12_VINENABLE 0x12 /* */ - -#define EM28XX_R14_GAMMA 0x14 -#define EM28XX_R15_RGAIN 0x15 -#define EM28XX_R16_GGAIN 0x16 -#define EM28XX_R17_BGAIN 0x17 -#define EM28XX_R18_ROFFSET 0x18 -#define EM28XX_R19_GOFFSET 0x19 -#define EM28XX_R1A_BOFFSET 0x1a - -#define EM28XX_R1B_OFLOW 0x1b -#define EM28XX_R1C_HSTART 0x1c -#define EM28XX_R1D_VSTART 0x1d -#define EM28XX_R1E_CWIDTH 0x1e -#define EM28XX_R1F_CHEIGHT 0x1f - -#define EM28XX_R20_YGAIN 0x20 -#define EM28XX_R21_YOFFSET 0x21 -#define EM28XX_R22_UVGAIN 0x22 -#define EM28XX_R23_UOFFSET 0x23 -#define EM28XX_R24_VOFFSET 0x24 -#define EM28XX_R25_SHARPNESS 0x25 - -#define EM28XX_R26_COMPR 0x26 -#define EM28XX_R27_OUTFMT 0x27 - -/* em28xx Output Format Register (0x27) */ -#define EM28XX_OUTFMT_RGB_8_RGRG 0x00 -#define EM28XX_OUTFMT_RGB_8_GRGR 0x01 -#define EM28XX_OUTFMT_RGB_8_GBGB 0x02 -#define EM28XX_OUTFMT_RGB_8_BGBG 0x03 -#define EM28XX_OUTFMT_RGB_16_656 0x04 -#define EM28XX_OUTFMT_RGB_8_BAYER 0x08 /* Pattern in Reg 0x10[1-0] */ -#define EM28XX_OUTFMT_YUV211 0x10 -#define EM28XX_OUTFMT_YUV422_Y0UY1V 0x14 -#define EM28XX_OUTFMT_YUV422_Y1UY0V 0x15 -#define EM28XX_OUTFMT_YUV411 0x18 - - -#define EM28XX_R28_XMIN 0x28 -#define EM28XX_R29_XMAX 0x29 -#define EM28XX_R2A_YMIN 0x2a -#define EM28XX_R2B_YMAX 0x2b - -#define EM28XX_R30_HSCALELOW 0x30 -#define EM28XX_R31_HSCALEHIGH 0x31 -#define EM28XX_R32_VSCALELOW 0x32 -#define EM28XX_R33_VSCALEHIGH 0x33 -#define EM28XX_R34_VBI_START_H 0x34 -#define EM28XX_R35_VBI_START_V 0x35 -#define EM28XX_R36_VBI_WIDTH 0x36 -#define EM28XX_R37_VBI_HEIGHT 0x37 - -#define EM28XX_R40_AC97LSB 0x40 -#define EM28XX_R41_AC97MSB 0x41 -#define EM28XX_R42_AC97ADDR 0x42 -#define EM28XX_R43_AC97BUSY 0x43 - -#define EM28XX_R45_IR 0x45 - /* 0x45 bit 7 - parity bit - bits 6-0 - count - 0x46 IR brand - 0x47 IR data - */ - -/* em2874 registers */ -#define EM2874_R50_IR_CONFIG 0x50 -#define EM2874_R51_IR 0x51 -#define EM2874_R5F_TS_ENABLE 0x5f -#define EM2874_R80_GPIO 0x80 - -/* em2874 IR config register (0x50) */ -#define EM2874_IR_NEC 0x00 -#define EM2874_IR_RC5 0x04 -#define EM2874_IR_RC6_MODE_0 0x08 -#define EM2874_IR_RC6_MODE_6A 0x0b - -/* em2874 Transport Stream Enable Register (0x5f) */ -#define EM2874_TS1_CAPTURE_ENABLE (1 << 0) -#define EM2874_TS1_FILTER_ENABLE (1 << 1) -#define EM2874_TS1_NULL_DISCARD (1 << 2) -#define EM2874_TS2_CAPTURE_ENABLE (1 << 4) -#define EM2874_TS2_FILTER_ENABLE (1 << 5) -#define EM2874_TS2_NULL_DISCARD (1 << 6) - -/* register settings */ -#define EM2800_AUDIO_SRC_TUNER 0x0d -#define EM2800_AUDIO_SRC_LINE 0x0c -#define EM28XX_AUDIO_SRC_TUNER 0xc0 -#define EM28XX_AUDIO_SRC_LINE 0x80 - -/* FIXME: Need to be populated with the other chip ID's */ -enum em28xx_chip_id { - CHIP_ID_EM2800 = 7, - CHIP_ID_EM2710 = 17, - CHIP_ID_EM2820 = 18, /* Also used by some em2710 */ - CHIP_ID_EM2840 = 20, - CHIP_ID_EM2750 = 33, - CHIP_ID_EM2860 = 34, - CHIP_ID_EM2870 = 35, - CHIP_ID_EM2883 = 36, - CHIP_ID_EM2874 = 65, - CHIP_ID_EM2884 = 68, - CHIP_ID_EM28174 = 113, -}; - -/* - * Registers used by em202 - */ - -/* EMP202 vendor registers */ -#define EM202_EXT_MODEM_CTRL 0x3e -#define EM202_GPIO_CONF 0x4c -#define EM202_GPIO_POLARITY 0x4e -#define EM202_GPIO_STICKY 0x50 -#define EM202_GPIO_MASK 0x52 -#define EM202_GPIO_STATUS 0x54 -#define EM202_SPDIF_OUT_SEL 0x6a -#define EM202_ANTIPOP 0x72 -#define EM202_EAPD_GPIO_ACCESS 0x74 diff --git a/drivers/media/video/em28xx/em28xx-vbi.c b/drivers/media/video/em28xx/em28xx-vbi.c deleted file mode 100644 index 2b4c9cba2d67..000000000000 --- a/drivers/media/video/em28xx/em28xx-vbi.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - em28xx-vbi.c - VBI driver for em28xx - - Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> - - This work was sponsored by EyeMagnet Limited. - - 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., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/hardirq.h> -#include <linux/init.h> - -#include "em28xx.h" - -static unsigned int vbibufs = 5; -module_param(vbibufs, int, 0644); -MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32"); - -static unsigned int vbi_debug; -module_param(vbi_debug, int, 0644); -MODULE_PARM_DESC(vbi_debug, "enable debug messages [vbi]"); - -#define dprintk(level, fmt, arg...) if (vbi_debug >= level) \ - printk(KERN_DEBUG "%s: " fmt, dev->core->name , ## arg) - -/* ------------------------------------------------------------------ */ - -static void -free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf) -{ - struct em28xx_fh *fh = vq->priv_data; - struct em28xx *dev = fh->dev; - unsigned long flags = 0; - if (in_interrupt()) - BUG(); - - /* We used to wait for the buffer to finish here, but this didn't work - because, as we were keeping the state as VIDEOBUF_QUEUED, - videobuf_queue_cancel marked it as finished for us. - (Also, it could wedge forever if the hardware was misconfigured.) - - This should be safe; by the time we get here, the buffer isn't - queued anymore. If we ever start marking the buffers as - VIDEOBUF_ACTIVE, it won't be, though. - */ - spin_lock_irqsave(&dev->slock, flags); - if (dev->isoc_ctl.vbi_buf == buf) - dev->isoc_ctl.vbi_buf = NULL; - spin_unlock_irqrestore(&dev->slock, flags); - - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int -vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) -{ - struct em28xx_fh *fh = q->priv_data; - struct em28xx *dev = fh->dev; - - *size = dev->vbi_width * dev->vbi_height * 2; - - if (0 == *count) - *count = vbibufs; - if (*count < 2) - *count = 2; - if (*count > 32) - *count = 32; - return 0; -} - -static int -vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct em28xx_fh *fh = q->priv_data; - struct em28xx *dev = fh->dev; - struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); - int rc = 0; - - buf->vb.size = dev->vbi_width * dev->vbi_height * 2; - - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - buf->vb.width = dev->vbi_width; - buf->vb.height = dev->vbi_height; - buf->vb.field = field; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(q, &buf->vb, NULL); - if (rc < 0) - goto fail; - } - - buf->vb.state = VIDEOBUF_PREPARED; - return 0; - -fail: - free_buffer(q, buf); - return rc; -} - -static void -vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct em28xx_buffer *buf = container_of(vb, - struct em28xx_buffer, - vb); - struct em28xx_fh *fh = vq->priv_data; - struct em28xx *dev = fh->dev; - struct em28xx_dmaqueue *vbiq = &dev->vbiq; - - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vbiq->active); -} - -static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); - free_buffer(q, buf); -} - -struct videobuf_queue_ops em28xx_vbi_qops = { - .buf_setup = vbi_setup, - .buf_prepare = vbi_prepare, - .buf_queue = vbi_queue, - .buf_release = vbi_release, -}; diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c deleted file mode 100644 index ecb23df7f16e..000000000000 --- a/drivers/media/video/em28xx/em28xx-video.c +++ /dev/null @@ -1,2624 +0,0 @@ -/* - em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB - video capture devices - - Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> - Markus Rechberger <mrechberger@gmail.com> - Mauro Carvalho Chehab <mchehab@infradead.org> - Sascha Sommer <saschasommer@freenet.de> - - Some parts based on SN9C10x PC Camera Controllers GPL driver made - 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 <linux/init.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/bitmap.h> -#include <linux/usb.h> -#include <linux/i2c.h> -#include <linux/mm.h> -#include <linux/mutex.h> -#include <linux/slab.h> - -#include "em28xx.h" -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-chip-ident.h> -#include <media/msp3400.h> -#include <media/tuner.h> - -#define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \ - "Markus Rechberger <mrechberger@gmail.com>, " \ - "Mauro Carvalho Chehab <mchehab@infradead.org>, " \ - "Sascha Sommer <saschasommer@freenet.de>" - -#define DRIVER_DESC "Empia em28xx based USB video device driver" - -#define EM28XX_VERSION "0.1.3" - -#define em28xx_videodbg(fmt, arg...) do {\ - if (video_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __func__ , ##arg); } while (0) - -static unsigned int isoc_debug; -module_param(isoc_debug, int, 0644); -MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]"); - -#define em28xx_isocdbg(fmt, arg...) \ -do {\ - if (isoc_debug) { \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __func__ , ##arg); \ - } \ - } while (0) - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -MODULE_VERSION(EM28XX_VERSION); - -static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; -static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; -static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; - -module_param_array(video_nr, int, NULL, 0444); -module_param_array(vbi_nr, int, NULL, 0444); -module_param_array(radio_nr, int, NULL, 0444); -MODULE_PARM_DESC(video_nr, "video device numbers"); -MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); -MODULE_PARM_DESC(radio_nr, "radio device numbers"); - -static unsigned int video_debug; -module_param(video_debug, int, 0644); -MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); - -/* supported video standards */ -static struct em28xx_fmt format[] = { - { - .name = "16 bpp YUY2, 4:2:2, packed", - .fourcc = V4L2_PIX_FMT_YUYV, - .depth = 16, - .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, - }, { - .name = "16 bpp RGB 565, LE", - .fourcc = V4L2_PIX_FMT_RGB565, - .depth = 16, - .reg = EM28XX_OUTFMT_RGB_16_656, - }, { - .name = "8 bpp Bayer BGBG..GRGR", - .fourcc = V4L2_PIX_FMT_SBGGR8, - .depth = 8, - .reg = EM28XX_OUTFMT_RGB_8_BGBG, - }, { - .name = "8 bpp Bayer GRGR..BGBG", - .fourcc = V4L2_PIX_FMT_SGRBG8, - .depth = 8, - .reg = EM28XX_OUTFMT_RGB_8_GRGR, - }, { - .name = "8 bpp Bayer GBGB..RGRG", - .fourcc = V4L2_PIX_FMT_SGBRG8, - .depth = 8, - .reg = EM28XX_OUTFMT_RGB_8_GBGB, - }, { - .name = "12 bpp YUV411", - .fourcc = V4L2_PIX_FMT_YUV411P, - .depth = 12, - .reg = EM28XX_OUTFMT_YUV411, - }, -}; - -/* supported controls */ -/* Common to all boards */ -static struct v4l2_queryctrl ac97_qctrl[] = { - { - .id = V4L2_CID_AUDIO_VOLUME, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Volume", - .minimum = 0x0, - .maximum = 0x1f, - .step = 0x1, - .default_value = 0x1f, - .flags = V4L2_CTRL_FLAG_SLIDER, - }, { - .id = V4L2_CID_AUDIO_MUTE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, - .flags = 0, - } -}; - -/* ------------------------------------------------------------------ - DMA and thread functions - ------------------------------------------------------------------*/ - -/* - * Announces that a buffer were filled and request the next - */ -static inline void buffer_filled(struct em28xx *dev, - struct em28xx_dmaqueue *dma_q, - struct em28xx_buffer *buf) -{ - /* Advice that buffer was filled */ - em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - do_gettimeofday(&buf->vb.ts); - - dev->isoc_ctl.vid_buf = NULL; - - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); -} - -static inline void vbi_buffer_filled(struct em28xx *dev, - struct em28xx_dmaqueue *dma_q, - struct em28xx_buffer *buf) -{ - /* Advice that buffer was filled */ - em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); - - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - do_gettimeofday(&buf->vb.ts); - - dev->isoc_ctl.vbi_buf = NULL; - - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); -} - -/* - * Identify the buffer header type and properly handles - */ -static void em28xx_copy_video(struct em28xx *dev, - struct em28xx_dmaqueue *dma_q, - struct em28xx_buffer *buf, - unsigned char *p, - unsigned char *outp, unsigned long len) -{ - void *fieldstart, *startwrite, *startread; - int linesdone, currlinedone, offset, lencopy, remain; - int bytesperline = dev->width << 1; - - if (dma_q->pos + len > buf->vb.size) - len = buf->vb.size - dma_q->pos; - - startread = p; - remain = len; - - if (dev->progressive) - fieldstart = outp; - else { - /* Interlaces two half frames */ - if (buf->top_field) - fieldstart = outp; - else - fieldstart = outp + bytesperline; - } - - linesdone = dma_q->pos / bytesperline; - currlinedone = dma_q->pos % bytesperline; - - if (dev->progressive) - offset = linesdone * bytesperline + currlinedone; - else - offset = linesdone * bytesperline * 2 + currlinedone; - - startwrite = fieldstart + offset; - lencopy = bytesperline - currlinedone; - lencopy = lencopy > remain ? remain : lencopy; - - if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) { - em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n", - ((char *)startwrite + lencopy) - - ((char *)outp + buf->vb.size)); - remain = (char *)outp + buf->vb.size - (char *)startwrite; - lencopy = remain; - } - if (lencopy <= 0) - return; - memcpy(startwrite, startread, lencopy); - - remain -= lencopy; - - while (remain > 0) { - startwrite += lencopy + bytesperline; - startread += lencopy; - if (bytesperline > remain) - lencopy = remain; - else - lencopy = bytesperline; - - if ((char *)startwrite + lencopy > (char *)outp + - buf->vb.size) { - em28xx_isocdbg("Overflow of %zi bytes past buffer end" - "(2)\n", - ((char *)startwrite + lencopy) - - ((char *)outp + buf->vb.size)); - lencopy = remain = (char *)outp + buf->vb.size - - (char *)startwrite; - } - if (lencopy <= 0) - break; - - memcpy(startwrite, startread, lencopy); - - remain -= lencopy; - } - - dma_q->pos += len; -} - -static void em28xx_copy_vbi(struct em28xx *dev, - struct em28xx_dmaqueue *dma_q, - struct em28xx_buffer *buf, - unsigned char *p, - unsigned char *outp, unsigned long len) -{ - void *startwrite, *startread; - int offset; - int bytesperline; - - if (dev == NULL) { - em28xx_isocdbg("dev is null\n"); - return; - } - bytesperline = dev->vbi_width; - - if (dma_q == NULL) { - em28xx_isocdbg("dma_q is null\n"); - return; - } - if (buf == NULL) { - return; - } - if (p == NULL) { - em28xx_isocdbg("p is null\n"); - return; - } - if (outp == NULL) { - em28xx_isocdbg("outp is null\n"); - return; - } - - if (dma_q->pos + len > buf->vb.size) - len = buf->vb.size - dma_q->pos; - - startread = p; - - startwrite = outp + dma_q->pos; - offset = dma_q->pos; - - /* Make sure the bottom field populates the second half of the frame */ - if (buf->top_field == 0) { - startwrite += bytesperline * dev->vbi_height; - offset += bytesperline * dev->vbi_height; - } - - memcpy(startwrite, startread, len); - dma_q->pos += len; -} - -static inline void print_err_status(struct em28xx *dev, - int packet, int status) -{ - char *errmsg = "Unknown"; - - switch (status) { - case -ENOENT: - errmsg = "unlinked synchronuously"; - break; - case -ECONNRESET: - errmsg = "unlinked asynchronuously"; - break; - case -ENOSR: - errmsg = "Buffer error (overrun)"; - break; - case -EPIPE: - errmsg = "Stalled (device not responding)"; - break; - case -EOVERFLOW: - errmsg = "Babble (bad cable?)"; - break; - case -EPROTO: - errmsg = "Bit-stuff error (bad cable?)"; - break; - case -EILSEQ: - errmsg = "CRC/Timeout (could be anything)"; - break; - case -ETIME: - errmsg = "Device does not respond"; - break; - } - if (packet < 0) { - em28xx_isocdbg("URB status %d [%s].\n", status, errmsg); - } else { - em28xx_isocdbg("URB packet %d, status %d [%s].\n", - packet, status, errmsg); - } -} - -/* - * video-buf generic routine to get the next available buffer - */ -static inline void get_next_buf(struct em28xx_dmaqueue *dma_q, - struct em28xx_buffer **buf) -{ - struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); - char *outp; - - if (list_empty(&dma_q->active)) { - em28xx_isocdbg("No active queue to serve\n"); - dev->isoc_ctl.vid_buf = NULL; - *buf = NULL; - return; - } - - /* Get the next buffer */ - *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue); - - /* Cleans up buffer - Useful for testing for frame/URB loss */ - outp = videobuf_to_vmalloc(&(*buf)->vb); - memset(outp, 0, (*buf)->vb.size); - - dev->isoc_ctl.vid_buf = *buf; - - return; -} - -/* - * video-buf generic routine to get the next available VBI buffer - */ -static inline void vbi_get_next_buf(struct em28xx_dmaqueue *dma_q, - struct em28xx_buffer **buf) -{ - struct em28xx *dev = container_of(dma_q, struct em28xx, vbiq); - char *outp; - - if (list_empty(&dma_q->active)) { - em28xx_isocdbg("No active queue to serve\n"); - dev->isoc_ctl.vbi_buf = NULL; - *buf = NULL; - return; - } - - /* Get the next buffer */ - *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue); - /* Cleans up buffer - Useful for testing for frame/URB loss */ - outp = videobuf_to_vmalloc(&(*buf)->vb); - memset(outp, 0x00, (*buf)->vb.size); - - dev->isoc_ctl.vbi_buf = *buf; - - return; -} - -/* - * Controls the isoc copy of each urb packet - */ -static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb) -{ - struct em28xx_buffer *buf; - struct em28xx_dmaqueue *dma_q = &dev->vidq; - unsigned char *outp = NULL; - int i, len = 0, rc = 1; - unsigned char *p; - - if (!dev) - return 0; - - if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) - return 0; - - if (urb->status < 0) { - print_err_status(dev, -1, urb->status); - if (urb->status == -ENOENT) - return 0; - } - - buf = dev->isoc_ctl.vid_buf; - if (buf != NULL) - outp = videobuf_to_vmalloc(&buf->vb); - - for (i = 0; i < urb->number_of_packets; i++) { - int status = urb->iso_frame_desc[i].status; - - if (status < 0) { - print_err_status(dev, i, status); - if (urb->iso_frame_desc[i].status != -EPROTO) - continue; - } - - len = urb->iso_frame_desc[i].actual_length - 4; - - if (urb->iso_frame_desc[i].actual_length <= 0) { - /* em28xx_isocdbg("packet %d is empty",i); - spammy */ - continue; - } - if (urb->iso_frame_desc[i].actual_length > - dev->max_pkt_size) { - em28xx_isocdbg("packet bigger than packet size"); - continue; - } - - p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - - /* FIXME: incomplete buffer checks where removed to make - logic simpler. Impacts of those changes should be evaluated - */ - if (p[0] == 0x33 && p[1] == 0x95 && p[2] == 0x00) { - em28xx_isocdbg("VBI HEADER!!!\n"); - /* FIXME: Should add vbi copy */ - continue; - } - if (p[0] == 0x22 && p[1] == 0x5a) { - em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2], - len, (p[2] & 1) ? "odd" : "even"); - - if (dev->progressive || !(p[2] & 1)) { - if (buf != NULL) - buffer_filled(dev, dma_q, buf); - get_next_buf(dma_q, &buf); - if (buf == NULL) - outp = NULL; - else - outp = videobuf_to_vmalloc(&buf->vb); - } - - if (buf != NULL) { - if (p[2] & 1) - buf->top_field = 0; - else - buf->top_field = 1; - } - - dma_q->pos = 0; - } - if (buf != NULL) { - if (p[0] != 0x88 && p[0] != 0x22) { - em28xx_isocdbg("frame is not complete\n"); - len += 4; - } else { - p += 4; - } - em28xx_copy_video(dev, dma_q, buf, p, outp, len); - } - } - return rc; -} - -/* Version of isoc handler that takes into account a mixture of video and - VBI data */ -static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) -{ - struct em28xx_buffer *buf, *vbi_buf; - struct em28xx_dmaqueue *dma_q = &dev->vidq; - struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; - unsigned char *outp = NULL; - unsigned char *vbioutp = NULL; - int i, len = 0, rc = 1; - unsigned char *p; - int vbi_size; - - if (!dev) - return 0; - - if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) - return 0; - - if (urb->status < 0) { - print_err_status(dev, -1, urb->status); - if (urb->status == -ENOENT) - return 0; - } - - buf = dev->isoc_ctl.vid_buf; - if (buf != NULL) - outp = videobuf_to_vmalloc(&buf->vb); - - vbi_buf = dev->isoc_ctl.vbi_buf; - if (vbi_buf != NULL) - vbioutp = videobuf_to_vmalloc(&vbi_buf->vb); - - for (i = 0; i < urb->number_of_packets; i++) { - int status = urb->iso_frame_desc[i].status; - - if (status < 0) { - print_err_status(dev, i, status); - if (urb->iso_frame_desc[i].status != -EPROTO) - continue; - } - - len = urb->iso_frame_desc[i].actual_length; - if (urb->iso_frame_desc[i].actual_length <= 0) { - /* em28xx_isocdbg("packet %d is empty",i); - spammy */ - continue; - } - if (urb->iso_frame_desc[i].actual_length > - dev->max_pkt_size) { - em28xx_isocdbg("packet bigger than packet size"); - continue; - } - - p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - - /* capture type 0 = vbi start - capture type 1 = video start - capture type 2 = video in progress */ - if (p[0] == 0x33 && p[1] == 0x95) { - dev->capture_type = 0; - dev->vbi_read = 0; - em28xx_isocdbg("VBI START HEADER!!!\n"); - dev->cur_field = p[2]; - p += 4; - len -= 4; - } else if (p[0] == 0x88 && p[1] == 0x88 && - p[2] == 0x88 && p[3] == 0x88) { - /* continuation */ - p += 4; - len -= 4; - } else if (p[0] == 0x22 && p[1] == 0x5a) { - /* start video */ - p += 4; - len -= 4; - } - - vbi_size = dev->vbi_width * dev->vbi_height; - - if (dev->capture_type == 0) { - if (dev->vbi_read >= vbi_size) { - /* We've already read all the VBI data, so - treat the rest as video */ - em28xx_isocdbg("dev->vbi_read > vbi_size\n"); - } else if ((dev->vbi_read + len) < vbi_size) { - /* This entire frame is VBI data */ - if (dev->vbi_read == 0 && - (!(dev->cur_field & 1))) { - /* Brand new frame */ - if (vbi_buf != NULL) - vbi_buffer_filled(dev, - vbi_dma_q, - vbi_buf); - vbi_get_next_buf(vbi_dma_q, &vbi_buf); - if (vbi_buf == NULL) - vbioutp = NULL; - else - vbioutp = videobuf_to_vmalloc( - &vbi_buf->vb); - } - - if (dev->vbi_read == 0) { - vbi_dma_q->pos = 0; - if (vbi_buf != NULL) { - if (dev->cur_field & 1) - vbi_buf->top_field = 0; - else - vbi_buf->top_field = 1; - } - } - - dev->vbi_read += len; - em28xx_copy_vbi(dev, vbi_dma_q, vbi_buf, p, - vbioutp, len); - } else { - /* Some of this frame is VBI data and some is - video data */ - int vbi_data_len = vbi_size - dev->vbi_read; - dev->vbi_read += vbi_data_len; - em28xx_copy_vbi(dev, vbi_dma_q, vbi_buf, p, - vbioutp, vbi_data_len); - dev->capture_type = 1; - p += vbi_data_len; - len -= vbi_data_len; - } - } - - if (dev->capture_type == 1) { - dev->capture_type = 2; - if (dev->progressive || !(dev->cur_field & 1)) { - if (buf != NULL) - buffer_filled(dev, dma_q, buf); - get_next_buf(dma_q, &buf); - if (buf == NULL) - outp = NULL; - else - outp = videobuf_to_vmalloc(&buf->vb); - } - if (buf != NULL) { - if (dev->cur_field & 1) - buf->top_field = 0; - else - buf->top_field = 1; - } - - dma_q->pos = 0; - } - - if (buf != NULL && dev->capture_type == 2) { - if (len >= 4 && p[0] == 0x88 && p[1] == 0x88 && - p[2] == 0x88 && p[3] == 0x88) { - p += 4; - len -= 4; - } - if (len >= 4 && p[0] == 0x22 && p[1] == 0x5a) { - em28xx_isocdbg("Video frame %d, len=%i, %s\n", - p[2], len, (p[2] & 1) ? - "odd" : "even"); - p += 4; - len -= 4; - } - - if (len > 0) - em28xx_copy_video(dev, dma_q, buf, p, outp, - len); - } - } - return rc; -} - - -/* ------------------------------------------------------------------ - Videobuf operations - ------------------------------------------------------------------*/ - -static int -buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) -{ - struct em28xx_fh *fh = vq->priv_data; - struct em28xx *dev = fh->dev; - struct v4l2_frequency f; - - *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7) - >> 3; - - if (0 == *count) - *count = EM28XX_DEF_BUF; - - if (*count < EM28XX_MIN_BUF) - *count = EM28XX_MIN_BUF; - - /* Ask tuner to go to analog or radio mode */ - memset(&f, 0, sizeof(f)); - f.frequency = dev->ctl_freq; - f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); - - return 0; -} - -/* This is called *without* dev->slock held; please keep it that way */ -static void free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf) -{ - struct em28xx_fh *fh = vq->priv_data; - struct em28xx *dev = fh->dev; - unsigned long flags = 0; - if (in_interrupt()) - BUG(); - - /* We used to wait for the buffer to finish here, but this didn't work - because, as we were keeping the state as VIDEOBUF_QUEUED, - videobuf_queue_cancel marked it as finished for us. - (Also, it could wedge forever if the hardware was misconfigured.) - - This should be safe; by the time we get here, the buffer isn't - queued anymore. If we ever start marking the buffers as - VIDEOBUF_ACTIVE, it won't be, though. - */ - spin_lock_irqsave(&dev->slock, flags); - if (dev->isoc_ctl.vid_buf == buf) - dev->isoc_ctl.vid_buf = NULL; - spin_unlock_irqrestore(&dev->slock, flags); - - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int -buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct em28xx_fh *fh = vq->priv_data; - struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); - struct em28xx *dev = fh->dev; - int rc = 0, urb_init = 0; - - buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth - + 7) >> 3; - - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - buf->vb.width = dev->width; - buf->vb.height = dev->height; - buf->vb.field = field; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(vq, &buf->vb, NULL); - if (rc < 0) - goto fail; - } - - if (!dev->isoc_ctl.analog_bufs.num_bufs) - urb_init = 1; - - if (urb_init) { - if (em28xx_vbi_supported(dev) == 1) - rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE, - EM28XX_NUM_PACKETS, - EM28XX_NUM_BUFS, - dev->max_pkt_size, - em28xx_isoc_copy_vbi); - else - rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE, - EM28XX_NUM_PACKETS, - EM28XX_NUM_BUFS, - dev->max_pkt_size, - em28xx_isoc_copy); - if (rc < 0) - goto fail; - } - - buf->vb.state = VIDEOBUF_PREPARED; - return 0; - -fail: - free_buffer(vq, buf); - return rc; -} - -static void -buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct em28xx_buffer *buf = container_of(vb, - struct em28xx_buffer, - vb); - struct em28xx_fh *fh = vq->priv_data; - struct em28xx *dev = fh->dev; - struct em28xx_dmaqueue *vidq = &dev->vidq; - - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vidq->active); - -} - -static void buffer_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) -{ - struct em28xx_buffer *buf = container_of(vb, - struct em28xx_buffer, - vb); - struct em28xx_fh *fh = vq->priv_data; - struct em28xx *dev = (struct em28xx *)fh->dev; - - em28xx_isocdbg("em28xx: called buffer_release\n"); - - free_buffer(vq, buf); -} - -static struct videobuf_queue_ops em28xx_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, -}; - -/********************* v4l2 interface **************************************/ - -static void video_mux(struct em28xx *dev, int index) -{ - dev->ctl_input = index; - dev->ctl_ainput = INPUT(index)->amux; - dev->ctl_aoutput = INPUT(index)->aout; - - if (!dev->ctl_aoutput) - dev->ctl_aoutput = EM28XX_AOUT_MASTER; - - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, - INPUT(index)->vmux, 0, 0); - - if (dev->board.has_msp34xx) { - if (dev->i2s_speed) { - v4l2_device_call_all(&dev->v4l2_dev, 0, audio, - s_i2s_clock_freq, dev->i2s_speed); - } - /* Note: this is msp3400 specific */ - v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, - dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0); - } - - if (dev->board.adecoder != EM28XX_NOADECODER) { - v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, - dev->ctl_ainput, dev->ctl_aoutput, 0); - } - - em28xx_audio_analog_set(dev); -} - -/* Usage lock check functions */ -static int res_get(struct em28xx_fh *fh, unsigned int bit) -{ - struct em28xx *dev = fh->dev; - - if (fh->resources & bit) - /* have it already allocated */ - return 1; - - /* is it free? */ - if (dev->resources & bit) { - /* no, someone else uses it */ - return 0; - } - /* it's free, grab it */ - fh->resources |= bit; - dev->resources |= bit; - em28xx_videodbg("res: get %d\n", bit); - return 1; -} - -static int res_check(struct em28xx_fh *fh, unsigned int bit) -{ - return fh->resources & bit; -} - -static int res_locked(struct em28xx *dev, unsigned int bit) -{ - return dev->resources & bit; -} - -static void res_free(struct em28xx_fh *fh, unsigned int bits) -{ - struct em28xx *dev = fh->dev; - - BUG_ON((fh->resources & bits) != bits); - - fh->resources &= ~bits; - dev->resources &= ~bits; - em28xx_videodbg("res: put %d\n", bits); -} - -static int get_ressource(struct em28xx_fh *fh) -{ - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - return EM28XX_RESOURCE_VIDEO; - case V4L2_BUF_TYPE_VBI_CAPTURE: - return EM28XX_RESOURCE_VBI; - default: - BUG(); - return 0; - } -} - -/* - * ac97_queryctrl() - * return the ac97 supported controls - */ -static int ac97_queryctrl(struct v4l2_queryctrl *qc) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) { - if (qc->id && qc->id == ac97_qctrl[i].id) { - memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc)); - return 0; - } - } - - /* Control is not ac97 related */ - return 1; -} - -/* - * ac97_get_ctrl() - * return the current values for ac97 mute and volume - */ -static int ac97_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - ctrl->value = dev->mute; - return 0; - case V4L2_CID_AUDIO_VOLUME: - ctrl->value = dev->volume; - return 0; - default: - /* Control is not ac97 related */ - return 1; - } -} - -/* - * ac97_set_ctrl() - * set values for ac97 mute and volume - */ -static int ac97_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) - if (ctrl->id == ac97_qctrl[i].id) - goto handle; - - /* Announce that hasn't handle it */ - return 1; - -handle: - if (ctrl->value < ac97_qctrl[i].minimum || - ctrl->value > ac97_qctrl[i].maximum) - return -ERANGE; - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - dev->mute = ctrl->value; - break; - case V4L2_CID_AUDIO_VOLUME: - dev->volume = ctrl->value; - break; - } - - return em28xx_audio_analog_set(dev); -} - -static int check_dev(struct em28xx *dev) -{ - if (dev->state & DEV_DISCONNECTED) { - em28xx_errdev("v4l2 ioctl: device not present\n"); - return -ENODEV; - } - - if (dev->state & DEV_MISCONFIGURED) { - em28xx_errdev("v4l2 ioctl: device is misconfigured; " - "close and open it again\n"); - return -EIO; - } - return 0; -} - -static void get_scale(struct em28xx *dev, - unsigned int width, unsigned int height, - unsigned int *hscale, unsigned int *vscale) -{ - unsigned int maxw = norm_maxw(dev); - unsigned int maxh = norm_maxh(dev); - - *hscale = (((unsigned long)maxw) << 12) / width - 4096L; - if (*hscale >= 0x4000) - *hscale = 0x3fff; - - *vscale = (((unsigned long)maxh) << 12) / height - 4096L; - if (*vscale >= 0x4000) - *vscale = 0x3fff; -} - -/* ------------------------------------------------------------------ - IOCTL vidioc handling - ------------------------------------------------------------------*/ - -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - f->fmt.pix.width = dev->width; - f->fmt.pix.height = dev->height; - f->fmt.pix.pixelformat = dev->format->fourcc; - f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3; - f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height; - f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - - /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ - if (dev->progressive) - f->fmt.pix.field = V4L2_FIELD_NONE; - else - f->fmt.pix.field = dev->interlaced ? - V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; - return 0; -} - -static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(format); i++) - if (format[i].fourcc == fourcc) - return &format[i]; - - return NULL; -} - -static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - unsigned int width = f->fmt.pix.width; - unsigned int height = f->fmt.pix.height; - unsigned int maxw = norm_maxw(dev); - unsigned int maxh = norm_maxh(dev); - unsigned int hscale, vscale; - struct em28xx_fmt *fmt; - - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - if (!fmt) { - em28xx_videodbg("Fourcc format (%08x) invalid.\n", - f->fmt.pix.pixelformat); - return -EINVAL; - } - - if (dev->board.is_em2800) { - /* the em2800 can only scale down to 50% */ - height = height > (3 * maxh / 4) ? maxh : maxh / 2; - width = width > (3 * maxw / 4) ? maxw : maxw / 2; - /* MaxPacketSize for em2800 is too small to capture at full resolution - * use half of maxw as the scaler can only scale to 50% */ - if (width == maxw && height == maxh) - width /= 2; - } else { - /* width must even because of the YUYV format - height must be even because of interlacing */ - v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, - 1, 0); - } - - get_scale(dev, width, height, &hscale, &vscale); - - width = (((unsigned long)maxw) << 12) / (hscale + 4096L); - height = (((unsigned long)maxh) << 12) / (vscale + 4096L); - - f->fmt.pix.width = width; - f->fmt.pix.height = height; - f->fmt.pix.pixelformat = fmt->fourcc; - f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3; - f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height; - f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - if (dev->progressive) - f->fmt.pix.field = V4L2_FIELD_NONE; - else - f->fmt.pix.field = dev->interlaced ? - V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; - - return 0; -} - -static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc, - unsigned width, unsigned height) -{ - struct em28xx_fmt *fmt; - - fmt = format_by_fourcc(fourcc); - if (!fmt) - return -EINVAL; - - dev->format = fmt; - dev->width = width; - dev->height = height; - - /* set new image size */ - get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - - em28xx_set_alternate(dev); - em28xx_resolution_set(dev); - - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - vidioc_try_fmt_vid_cap(file, priv, f); - - if (videobuf_queue_is_busy(&fh->vb_vidq)) { - em28xx_errdev("%s queue busy\n", __func__); - return -EBUSY; - } - - return em28xx_set_video_format(dev, f->fmt.pix.pixelformat, - f->fmt.pix.width, f->fmt.pix.height); -} - -static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - *norm = dev->norm; - - return 0; -} - -static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm); - - return 0; -} - -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - struct v4l2_format f; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - dev->norm = *norm; - - /* Adjusts width/height, if needed */ - f.fmt.pix.width = dev->width; - f.fmt.pix.height = dev->height; - vidioc_try_fmt_vid_cap(file, priv, &f); - - /* set new image size */ - dev->width = f.fmt.pix.width; - dev->height = f.fmt.pix.height; - get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); - - em28xx_resolution_set(dev); - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); - - return 0; -} - -static int vidioc_g_parm(struct file *file, void *priv, - struct v4l2_streamparm *p) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc = 0; - - if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (dev->board.is_webcam) - rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0, - video, g_parm, p); - else - v4l2_video_std_frame_period(dev->norm, - &p->parm.capture.timeperframe); - - return rc; -} - -static int vidioc_s_parm(struct file *file, void *priv, - struct v4l2_streamparm *p) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - if (!dev->board.is_webcam) - return -EINVAL; - - if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - return v4l2_device_call_until_err(&dev->v4l2_dev, 0, video, s_parm, p); -} - -static const char *iname[] = { - [EM28XX_VMUX_COMPOSITE1] = "Composite1", - [EM28XX_VMUX_COMPOSITE2] = "Composite2", - [EM28XX_VMUX_COMPOSITE3] = "Composite3", - [EM28XX_VMUX_COMPOSITE4] = "Composite4", - [EM28XX_VMUX_SVIDEO] = "S-Video", - [EM28XX_VMUX_TELEVISION] = "Television", - [EM28XX_VMUX_CABLE] = "Cable TV", - [EM28XX_VMUX_DVB] = "DVB", - [EM28XX_VMUX_DEBUG] = "for debug only", -}; - -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *i) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - unsigned int n; - - n = i->index; - if (n >= MAX_EM28XX_INPUT) - return -EINVAL; - if (0 == INPUT(n)->type) - return -EINVAL; - - i->index = n; - i->type = V4L2_INPUT_TYPE_CAMERA; - - strcpy(i->name, iname[INPUT(n)->type]); - - if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) || - (EM28XX_VMUX_CABLE == INPUT(n)->type)) - i->type = V4L2_INPUT_TYPE_TUNER; - - i->std = dev->vdev->tvnorms; - - return 0; -} - -static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - *i = dev->ctl_input; - - return 0; -} - -static int vidioc_s_input(struct file *file, void *priv, unsigned int i) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (i >= MAX_EM28XX_INPUT) - return -EINVAL; - if (0 == INPUT(i)->type) - return -EINVAL; - - video_mux(dev, i); - return 0; -} - -static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - if (!dev->audio_mode.has_audio) - return -EINVAL; - - switch (a->index) { - case EM28XX_AMUX_VIDEO: - strcpy(a->name, "Television"); - break; - case EM28XX_AMUX_LINE_IN: - strcpy(a->name, "Line In"); - break; - case EM28XX_AMUX_VIDEO2: - strcpy(a->name, "Television alt"); - break; - case EM28XX_AMUX_PHONE: - strcpy(a->name, "Phone"); - break; - case EM28XX_AMUX_MIC: - strcpy(a->name, "Mic"); - break; - case EM28XX_AMUX_CD: - strcpy(a->name, "CD"); - break; - case EM28XX_AMUX_AUX: - strcpy(a->name, "Aux"); - break; - case EM28XX_AMUX_PCM_OUT: - strcpy(a->name, "PCM"); - break; - default: - return -EINVAL; - } - - a->index = dev->ctl_ainput; - a->capability = V4L2_AUDCAP_STEREO; - - return 0; -} - -static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - - if (!dev->audio_mode.has_audio) - return -EINVAL; - - if (a->index >= MAX_EM28XX_INPUT) - return -EINVAL; - if (0 == INPUT(a->index)->type) - return -EINVAL; - - dev->ctl_ainput = INPUT(a->index)->amux; - dev->ctl_aoutput = INPUT(a->index)->aout; - - if (!dev->ctl_aoutput) - dev->ctl_aoutput = EM28XX_AOUT_MASTER; - - return 0; -} - -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int id = qc->id; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - memset(qc, 0, sizeof(*qc)); - - qc->id = id; - - /* enumerate AC97 controls */ - if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { - rc = ac97_queryctrl(qc); - if (!rc) - return 0; - } - - /* enumerate V4L2 device controls */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc); - - if (qc->type) - return 0; - else - return -EINVAL; -} - -/* - * FIXME: This is an indirect way to check if a control exists at a - * subdev. Instead of that hack, maybe the better would be to change all - * subdevs to return -ENOIOCTLCMD, if an ioctl is not supported. - */ -static int check_subdev_ctrl(struct em28xx *dev, int id) -{ - struct v4l2_queryctrl qc; - - memset(&qc, 0, sizeof(qc)); - qc.id = id; - - /* enumerate V4L2 device controls */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, &qc); - - if (qc.type) - return 0; - else - return -EINVAL; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - rc = 0; - - /* Set an AC97 control */ - if (dev->audio_mode.ac97 != EM28XX_NO_AC97) - rc = ac97_get_ctrl(dev, ctrl); - else - rc = 1; - - /* It were not an AC97 control. Sends it to the v4l2 dev interface */ - if (rc == 1) { - if (check_subdev_ctrl(dev, ctrl->id)) - return -EINVAL; - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl); - rc = 0; - } - - return rc; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - /* Set an AC97 control */ - if (dev->audio_mode.ac97 != EM28XX_NO_AC97) - rc = ac97_set_ctrl(dev, ctrl); - else - rc = 1; - - /* It isn't an AC97 control. Sends it to the v4l2 dev interface */ - if (rc == 1) { - rc = check_subdev_ctrl(dev, ctrl->id); - if (!rc) - v4l2_device_call_all(&dev->v4l2_dev, 0, - core, s_ctrl, ctrl); - /* - * In the case of non-AC97 volume controls, we still need - * to do some setups at em28xx, in order to mute/unmute - * and to adjust audio volume. However, the value ranges - * should be checked by the corresponding V4L subdriver. - */ - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - dev->mute = ctrl->value; - rc = em28xx_audio_analog_set(dev); - break; - case V4L2_CID_AUDIO_VOLUME: - dev->volume = ctrl->value; - rc = em28xx_audio_analog_set(dev); - } - } - return (rc < 0) ? rc : 0; -} - -static int vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (0 != t->index) - return -EINVAL; - - strcpy(t->name, "Tuner"); - t->type = V4L2_TUNER_ANALOG_TV; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); - return 0; -} - -static int vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (0 != t->index) - return -EINVAL; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); - return 0; -} - -static int vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - f->frequency = dev->ctl_freq; - return 0; -} - -static int vidioc_s_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (0 != f->tuner) - return -EINVAL; - - if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV)) - return -EINVAL; - if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO)) - return -EINVAL; - - dev->ctl_freq = f->frequency; - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f); - - return 0; -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int em28xx_reg_len(int reg) -{ - switch (reg) { - case EM28XX_R40_AC97LSB: - case EM28XX_R30_HSCALELOW: - case EM28XX_R32_VSCALELOW: - return 2; - default: - return 1; - } -} - -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip); - - return 0; -} - - -static int vidioc_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int ret; - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_AC97: - ret = em28xx_read_ac97(dev, reg->reg); - if (ret < 0) - return ret; - - reg->val = ret; - reg->size = 1; - return 0; - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* TODO: is this correct? */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - - /* Match host */ - reg->size = em28xx_reg_len(reg->reg); - if (reg->size == 1) { - ret = em28xx_read_reg(dev, reg->reg); - - if (ret < 0) - return ret; - - reg->val = ret; - } else { - __le16 val = 0; - ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS, - reg->reg, (char *)&val, 2); - if (ret < 0) - return ret; - - reg->val = le16_to_cpu(val); - } - - return 0; -} - -static int vidioc_s_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - __le16 buf; - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_AC97: - return em28xx_write_ac97(dev, reg->reg, reg->val); - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* TODO: is this correct? */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - - /* Match host */ - buf = cpu_to_le16(reg->val); - - return em28xx_write_regs(dev, reg->reg, (char *)&buf, - em28xx_reg_len(reg->reg)); -} -#endif - - -static int vidioc_cropcap(struct file *file, void *priv, - struct v4l2_cropcap *cc) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - cc->bounds.left = 0; - cc->bounds.top = 0; - cc->bounds.width = dev->width; - cc->bounds.height = dev->height; - cc->defrect = cc->bounds; - cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */ - cc->pixelaspect.denominator = 59; - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc = -EINVAL; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (unlikely(type != fh->type)) - return -EINVAL; - - em28xx_videodbg("vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n", - fh, type, fh->resources, dev->resources); - - if (unlikely(!res_get(fh, get_ressource(fh)))) - return -EBUSY; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_streamon(&fh->vb_vidq); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_streamon(&fh->vb_vbiq); - - return rc; -} - -static int vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type type) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) - return -EINVAL; - if (type != fh->type) - return -EINVAL; - - em28xx_videodbg("vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n", - fh, type, fh->resources, dev->resources); - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (res_check(fh, EM28XX_RESOURCE_VIDEO)) { - videobuf_streamoff(&fh->vb_vidq); - res_free(fh, EM28XX_RESOURCE_VIDEO); - } - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - if (res_check(fh, EM28XX_RESOURCE_VBI)) { - videobuf_streamoff(&fh->vb_vbiq); - res_free(fh, EM28XX_RESOURCE_VBI); - } - } - - return 0; -} - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); - strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card)); - usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); - - cap->capabilities = - V4L2_CAP_SLICED_VBI_CAPTURE | - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; - - if (dev->vbi_dev) - cap->capabilities |= V4L2_CAP_VBI_CAPTURE; - - if (dev->audio_mode.has_audio) - cap->capabilities |= V4L2_CAP_AUDIO; - - if (dev->tuner_type != TUNER_ABSENT) - cap->capabilities |= V4L2_CAP_TUNER; - - return 0; -} - -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - if (unlikely(f->index >= ARRAY_SIZE(format))) - return -EINVAL; - - strlcpy(f->description, format[f->index].name, sizeof(f->description)); - f->pixelformat = format[f->index].fourcc; - - return 0; -} - -static int vidioc_enum_framesizes(struct file *file, void *priv, - struct v4l2_frmsizeenum *fsize) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - struct em28xx_fmt *fmt; - unsigned int maxw = norm_maxw(dev); - unsigned int maxh = norm_maxh(dev); - - fmt = format_by_fourcc(fsize->pixel_format); - if (!fmt) { - em28xx_videodbg("Fourcc format (%08x) invalid.\n", - fsize->pixel_format); - return -EINVAL; - } - - if (dev->board.is_em2800) { - if (fsize->index > 1) - return -EINVAL; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - fsize->discrete.width = maxw / (1 + fsize->index); - fsize->discrete.height = maxh / (1 + fsize->index); - return 0; - } - - if (fsize->index != 0) - return -EINVAL; - - /* Report a continuous range */ - fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; - fsize->stepwise.min_width = 48; - fsize->stepwise.min_height = 32; - fsize->stepwise.max_width = maxw; - fsize->stepwise.max_height = maxh; - fsize->stepwise.step_width = 1; - fsize->stepwise.step_height = 1; - return 0; -} - -/* Sliced VBI ioctls */ -static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - f->fmt.sliced.service_set = 0; - v4l2_device_call_all(&dev->v4l2_dev, 0, vbi, g_sliced_fmt, &f->fmt.sliced); - - if (f->fmt.sliced.service_set == 0) - rc = -EINVAL; - - return rc; -} - -static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - v4l2_device_call_all(&dev->v4l2_dev, 0, vbi, g_sliced_fmt, &f->fmt.sliced); - - if (f->fmt.sliced.service_set == 0) - return -EINVAL; - - return 0; -} - -/* RAW VBI ioctls */ - -static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, - struct v4l2_format *format) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - format->fmt.vbi.samples_per_line = dev->vbi_width; - format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - format->fmt.vbi.offset = 0; - format->fmt.vbi.flags = 0; - format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; - format->fmt.vbi.count[0] = dev->vbi_height; - format->fmt.vbi.count[1] = dev->vbi_height; - - /* Varies by video standard (NTSC, PAL, etc.) */ - if (dev->norm & V4L2_STD_525_60) { - /* NTSC */ - format->fmt.vbi.start[0] = 10; - format->fmt.vbi.start[1] = 273; - } else if (dev->norm & V4L2_STD_625_50) { - /* PAL */ - format->fmt.vbi.start[0] = 6; - format->fmt.vbi.start[1] = 318; - } - - return 0; -} - -static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv, - struct v4l2_format *format) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - format->fmt.vbi.samples_per_line = dev->vbi_width; - format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - format->fmt.vbi.offset = 0; - format->fmt.vbi.flags = 0; - format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; - format->fmt.vbi.count[0] = dev->vbi_height; - format->fmt.vbi.count[1] = dev->vbi_height; - - /* Varies by video standard (NTSC, PAL, etc.) */ - if (dev->norm & V4L2_STD_525_60) { - /* NTSC */ - format->fmt.vbi.start[0] = 10; - format->fmt.vbi.start[1] = 273; - } else if (dev->norm & V4L2_STD_625_50) { - /* PAL */ - format->fmt.vbi.start[0] = 6; - format->fmt.vbi.start[1] = 318; - } - - return 0; -} - -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - return videobuf_reqbufs(&fh->vb_vidq, rb); - else - return videobuf_reqbufs(&fh->vb_vbiq, rb); -} - -static int vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *b) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - return videobuf_querybuf(&fh->vb_vidq, b); - else { - /* FIXME: I'm not sure yet whether this is a bug in zvbi or - the videobuf framework, but we probably shouldn't be - returning a buffer larger than that which was asked for. - At a minimum, it causes a crash in zvbi since it does - a memcpy based on the source buffer length */ - int result = videobuf_querybuf(&fh->vb_vbiq, b); - b->length = dev->vbi_width * dev->vbi_height * 2; - - return result; - } -} - -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - return videobuf_qbuf(&fh->vb_vidq, b); - else - return videobuf_qbuf(&fh->vb_vbiq, b); -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & - O_NONBLOCK); - else - return videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags & - O_NONBLOCK); -} - -/* ----------------------------------------------------------- */ -/* RADIO ESPECIFIC IOCTLS */ -/* ----------------------------------------------------------- */ - -static int radio_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct em28xx *dev = ((struct em28xx_fh *)priv)->dev; - - strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); - strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card)); - usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); - - cap->capabilities = V4L2_CAP_TUNER; - return 0; -} - -static int radio_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct em28xx *dev = ((struct em28xx_fh *)priv)->dev; - - if (unlikely(t->index > 0)) - return -EINVAL; - - strcpy(t->name, "Radio"); - t->type = V4L2_TUNER_RADIO; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); - - return 0; -} - -static int radio_enum_input(struct file *file, void *priv, - struct v4l2_input *i) -{ - if (i->index != 0) - return -EINVAL; - strcpy(i->name, "Radio"); - i->type = V4L2_INPUT_TYPE_TUNER; - - return 0; -} - -static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - if (unlikely(a->index)) - return -EINVAL; - - strcpy(a->name, "Radio"); - return 0; -} - -static int radio_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct em28xx *dev = ((struct em28xx_fh *)priv)->dev; - - if (0 != t->index) - return -EINVAL; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); - - return 0; -} - -static int radio_s_audio(struct file *file, void *fh, - struct v4l2_audio *a) -{ - return 0; -} - -static int radio_s_input(struct file *file, void *fh, unsigned int i) -{ - return 0; -} - -static int radio_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - int i; - - if (qc->id < V4L2_CID_BASE || - qc->id >= V4L2_CID_LASTP1) - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) { - if (qc->id && qc->id == ac97_qctrl[i].id) { - memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc)); - return 0; - } - } - - return -EINVAL; -} - -/* - * em28xx_v4l2_open() - * inits the device and starts isoc transfer - */ -static int em28xx_v4l2_open(struct file *filp) -{ - int errCode = 0, radio = 0; - struct video_device *vdev = video_devdata(filp); - struct em28xx *dev = video_drvdata(filp); - enum v4l2_buf_type fh_type = 0; - struct em28xx_fh *fh; - enum v4l2_field field; - - switch (vdev->vfl_type) { - case VFL_TYPE_GRABBER: - fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - break; - case VFL_TYPE_VBI: - fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; - break; - case VFL_TYPE_RADIO: - radio = 1; - break; - } - - em28xx_videodbg("open dev=%s type=%s users=%d\n", - video_device_node_name(vdev), v4l2_type_names[fh_type], - dev->users); - - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); - if (!fh) { - em28xx_errdev("em28xx-video.c: Out of memory?!\n"); - mutex_unlock(&dev->lock); - return -ENOMEM; - } - fh->dev = dev; - fh->radio = radio; - fh->type = fh_type; - filp->private_data = fh; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { - em28xx_set_mode(dev, EM28XX_ANALOG_MODE); - em28xx_set_alternate(dev); - em28xx_resolution_set(dev); - - /* Needed, since GPIO might have disabled power of - some i2c device - */ - em28xx_wake_i2c(dev); - - } - if (fh->radio) { - em28xx_videodbg("video_open: setting radio device\n"); - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio); - } - - dev->users++; - - if (dev->progressive) - field = V4L2_FIELD_NONE; - else - field = V4L2_FIELD_INTERLACED; - - videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops, - NULL, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, field, - sizeof(struct em28xx_buffer), fh, &dev->lock); - - videobuf_queue_vmalloc_init(&fh->vb_vbiq, &em28xx_vbi_qops, - NULL, &dev->slock, - V4L2_BUF_TYPE_VBI_CAPTURE, - V4L2_FIELD_SEQ_TB, - sizeof(struct em28xx_buffer), fh, &dev->lock); - mutex_unlock(&dev->lock); - - return errCode; -} - -/* - * em28xx_realease_resources() - * unregisters the v4l2,i2c and usb devices - * called when the device gets disconected or at module unload -*/ -void em28xx_release_analog_resources(struct em28xx *dev) -{ - - /*FIXME: I2C IR should be disconnected */ - - if (dev->radio_dev) { - if (video_is_registered(dev->radio_dev)) - video_unregister_device(dev->radio_dev); - else - video_device_release(dev->radio_dev); - dev->radio_dev = NULL; - } - if (dev->vbi_dev) { - em28xx_info("V4L2 device %s deregistered\n", - video_device_node_name(dev->vbi_dev)); - if (video_is_registered(dev->vbi_dev)) - video_unregister_device(dev->vbi_dev); - else - video_device_release(dev->vbi_dev); - dev->vbi_dev = NULL; - } - if (dev->vdev) { - em28xx_info("V4L2 device %s deregistered\n", - video_device_node_name(dev->vdev)); - if (video_is_registered(dev->vdev)) - video_unregister_device(dev->vdev); - else - video_device_release(dev->vdev); - dev->vdev = NULL; - } -} - -/* - * em28xx_v4l2_close() - * stops streaming and deallocates all resources allocated by the v4l2 - * calls and ioctls - */ -static int em28xx_v4l2_close(struct file *filp) -{ - struct em28xx_fh *fh = filp->private_data; - struct em28xx *dev = fh->dev; - int errCode; - - em28xx_videodbg("users=%d\n", dev->users); - - mutex_lock(&dev->lock); - if (res_check(fh, EM28XX_RESOURCE_VIDEO)) { - videobuf_stop(&fh->vb_vidq); - res_free(fh, EM28XX_RESOURCE_VIDEO); - } - - if (res_check(fh, EM28XX_RESOURCE_VBI)) { - videobuf_stop(&fh->vb_vbiq); - res_free(fh, EM28XX_RESOURCE_VBI); - } - - if (dev->users == 1) { - /* the device is already disconnect, - free the remaining resources */ - if (dev->state & DEV_DISCONNECTED) { - em28xx_release_resources(dev); - kfree(dev->alt_max_pkt_size); - kfree(dev); - kfree(fh); - mutex_unlock(&dev->lock); - return 0; - } - - /* Save some power by putting tuner to sleep */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); - - /* do this before setting alternate! */ - em28xx_uninit_isoc(dev, EM28XX_ANALOG_MODE); - em28xx_set_mode(dev, EM28XX_SUSPEND); - - /* set alternate 0 */ - dev->alt = 0; - em28xx_videodbg("setting alternate 0\n"); - errCode = usb_set_interface(dev->udev, 0, 0); - if (errCode < 0) { - em28xx_errdev("cannot change alternate number to " - "0 (error=%i)\n", errCode); - } - } - - videobuf_mmap_free(&fh->vb_vidq); - videobuf_mmap_free(&fh->vb_vbiq); - kfree(fh); - dev->users--; - mutex_unlock(&dev->lock); - return 0; -} - -/* - * em28xx_v4l2_read() - * will allocate buffers when called for the first time - */ -static ssize_t -em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count, - loff_t *pos) -{ - struct em28xx_fh *fh = filp->private_data; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - /* FIXME: read() is not prepared to allow changing the video - resolution while streaming. Seems a bug at em28xx_set_fmt - */ - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (res_locked(dev, EM28XX_RESOURCE_VIDEO)) - rc = -EBUSY; - else - rc = videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, - filp->f_flags & O_NONBLOCK); - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - if (!res_get(fh, EM28XX_RESOURCE_VBI)) - rc = -EBUSY; - else - rc = videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0, - filp->f_flags & O_NONBLOCK); - } - mutex_unlock(&dev->lock); - - return rc; -} - -/* - * em28xx_poll() - * will allocate buffers when called for the first time - */ -static unsigned int em28xx_poll(struct file *filp, poll_table *wait) -{ - struct em28xx_fh *fh = filp->private_data; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (!res_get(fh, EM28XX_RESOURCE_VIDEO)) - return POLLERR; - return videobuf_poll_stream(filp, &fh->vb_vidq, wait); - } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - if (!res_get(fh, EM28XX_RESOURCE_VBI)) - return POLLERR; - return videobuf_poll_stream(filp, &fh->vb_vbiq, wait); - } else { - return POLLERR; - } -} - -static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait) -{ - struct em28xx_fh *fh = filp->private_data; - struct em28xx *dev = fh->dev; - unsigned int res; - - mutex_lock(&dev->lock); - res = em28xx_poll(filp, wait); - mutex_unlock(&dev->lock); - return res; -} - -/* - * em28xx_v4l2_mmap() - */ -static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct em28xx_fh *fh = filp->private_data; - struct em28xx *dev = fh->dev; - int rc; - - rc = check_dev(dev); - if (rc < 0) - return rc; - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma); - mutex_unlock(&dev->lock); - - em28xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n", - (unsigned long)vma->vm_start, - (unsigned long)vma->vm_end-(unsigned long)vma->vm_start, - rc); - - return rc; -} - -static const struct v4l2_file_operations em28xx_v4l_fops = { - .owner = THIS_MODULE, - .open = em28xx_v4l2_open, - .release = em28xx_v4l2_close, - .read = em28xx_v4l2_read, - .poll = em28xx_v4l2_poll, - .mmap = em28xx_v4l2_mmap, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, - .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, - .vidioc_enum_framesizes = vidioc_enum_framesizes, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_cropcap = vidioc_cropcap, - .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, - .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, - .vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, - - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, - .vidioc_g_std = vidioc_g_std, - .vidioc_querystd = vidioc_querystd, - .vidioc_s_std = vidioc_s_std, - .vidioc_g_parm = vidioc_g_parm, - .vidioc_s_parm = vidioc_s_parm, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .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, - .vidioc_g_chip_ident = vidioc_g_chip_ident, -#endif -}; - -static const struct video_device em28xx_video_template = { - .fops = &em28xx_v4l_fops, - .release = video_device_release, - .ioctl_ops = &video_ioctl_ops, - - .tvnorms = V4L2_STD_ALL, - .current_norm = V4L2_STD_PAL, -}; - -static const struct v4l2_file_operations radio_fops = { - .owner = THIS_MODULE, - .open = em28xx_v4l2_open, - .release = em28xx_v4l2_close, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops radio_ioctl_ops = { - .vidioc_querycap = radio_querycap, - .vidioc_g_tuner = radio_g_tuner, - .vidioc_enum_input = radio_enum_input, - .vidioc_g_audio = radio_g_audio, - .vidioc_s_tuner = radio_s_tuner, - .vidioc_s_audio = radio_s_audio, - .vidioc_s_input = radio_s_input, - .vidioc_queryctrl = radio_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .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 -}; - -static struct video_device em28xx_radio_template = { - .name = "em28xx-radio", - .fops = &radio_fops, - .ioctl_ops = &radio_ioctl_ops, -}; - -/******************************** usb interface ******************************/ - - - -static struct video_device *em28xx_vdev_init(struct em28xx *dev, - const struct video_device *template, - const char *type_name) -{ - struct video_device *vfd; - - vfd = video_device_alloc(); - if (NULL == vfd) - return NULL; - - *vfd = *template; - vfd->v4l2_dev = &dev->v4l2_dev; - vfd->release = video_device_release; - vfd->debug = video_debug; - vfd->lock = &dev->lock; - - snprintf(vfd->name, sizeof(vfd->name), "%s %s", - dev->name, type_name); - - video_set_drvdata(vfd, dev); - return vfd; -} - -int em28xx_register_analog_devices(struct em28xx *dev) -{ - u8 val; - int ret; - unsigned int maxw; - - printk(KERN_INFO "%s: v4l2 driver version %s\n", - dev->name, EM28XX_VERSION); - - /* set default norm */ - dev->norm = em28xx_video_template.current_norm; - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); - dev->interlaced = EM28XX_INTERLACED_DEFAULT; - - /* Analog specific initialization */ - dev->format = &format[0]; - - maxw = norm_maxw(dev); - /* MaxPacketSize for em2800 is too small to capture at full resolution - * use half of maxw as the scaler can only scale to 50% */ - if (dev->board.is_em2800) - maxw /= 2; - - em28xx_set_video_format(dev, format[0].fourcc, - maxw, norm_maxh(dev)); - - video_mux(dev, 0); - - /* Audio defaults */ - dev->mute = 1; - dev->volume = 0x1f; - -/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */ - val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK); - em28xx_write_reg(dev, EM28XX_R0F_XCLK, - (EM28XX_XCLK_AUDIO_UNMUTE | val)); - - em28xx_set_outfmt(dev); - em28xx_colorlevels_set_default(dev); - em28xx_compression_disable(dev); - - /* allocate and fill video video_device struct */ - dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); - if (!dev->vdev) { - em28xx_errdev("cannot allocate video_device.\n"); - return -ENODEV; - } - - /* register v4l2 video video_device */ - ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER, - video_nr[dev->devno]); - if (ret) { - em28xx_errdev("unable to register video device (error=%i).\n", - ret); - return ret; - } - - /* Allocate and fill vbi video_device struct */ - if (em28xx_vbi_supported(dev) == 1) { - dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, - "vbi"); - - /* register v4l2 vbi video_device */ - ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, - vbi_nr[dev->devno]); - if (ret < 0) { - em28xx_errdev("unable to register vbi device\n"); - return ret; - } - } - - if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) { - dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, - "radio"); - if (!dev->radio_dev) { - em28xx_errdev("cannot allocate video_device.\n"); - return -ENODEV; - } - ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, - radio_nr[dev->devno]); - if (ret < 0) { - em28xx_errdev("can't register radio device\n"); - return ret; - } - em28xx_info("Registered radio device as %s\n", - video_device_node_name(dev->radio_dev)); - } - - em28xx_info("V4L2 video device registered as %s\n", - video_device_node_name(dev->vdev)); - - if (dev->vbi_dev) - em28xx_info("V4L2 VBI device registered as %s\n", - video_device_node_name(dev->vbi_dev)); - - return 0; -} diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h deleted file mode 100644 index 8757523e6863..000000000000 --- a/drivers/media/video/em28xx/em28xx.h +++ /dev/null @@ -1,809 +0,0 @@ -/* - em28xx.h - driver for Empia EM2800/EM2820/2840 USB video capture devices - - Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com> - Ludovico Cavedon <cavedon@sssup.it> - Mauro Carvalho Chehab <mchehab@infradead.org> - - Based on the em2800 driver from Sascha Sommer <saschasommer@freenet.de> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _EM28XX_H -#define _EM28XX_H - -#include <linux/workqueue.h> -#include <linux/i2c.h> -#include <linux/mutex.h> -#include <linux/videodev2.h> - -#include <media/videobuf-vmalloc.h> -#include <media/v4l2-device.h> -#include <media/ir-kbd-i2c.h> -#include <media/rc-core.h> -#if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) -#include <media/videobuf-dvb.h> -#endif -#include "tuner-xc2028.h" -#include "xc5000.h" -#include "em28xx-reg.h" - -/* Boards supported by driver */ -#define EM2800_BOARD_UNKNOWN 0 -#define EM2820_BOARD_UNKNOWN 1 -#define EM2820_BOARD_TERRATEC_CINERGY_250 2 -#define EM2820_BOARD_PINNACLE_USB_2 3 -#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 4 -#define EM2820_BOARD_MSI_VOX_USB_2 5 -#define EM2800_BOARD_TERRATEC_CINERGY_200 6 -#define EM2800_BOARD_LEADTEK_WINFAST_USBII 7 -#define EM2800_BOARD_KWORLD_USB2800 8 -#define EM2820_BOARD_PINNACLE_DVC_90 9 -#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 10 -#define EM2880_BOARD_TERRATEC_HYBRID_XS 11 -#define EM2820_BOARD_KWORLD_PVRTV2800RF 12 -#define EM2880_BOARD_TERRATEC_PRODIGY_XS 13 -#define EM2820_BOARD_PROLINK_PLAYTV_USB2 14 -#define EM2800_BOARD_VGEAR_POCKETTV 15 -#define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 16 -#define EM2880_BOARD_PINNACLE_PCTV_HD_PRO 17 -#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 18 -#define EM2860_BOARD_SAA711X_REFERENCE_DESIGN 19 -#define EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 20 -#define EM2800_BOARD_GRABBEEX_USB2800 21 -#define EM2750_BOARD_UNKNOWN 22 -#define EM2750_BOARD_DLCW_130 23 -#define EM2820_BOARD_DLINK_USB_TV 24 -#define EM2820_BOARD_GADMEI_UTV310 25 -#define EM2820_BOARD_HERCULES_SMART_TV_USB2 26 -#define EM2820_BOARD_PINNACLE_USB_2_FM1216ME 27 -#define EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE 28 -#define EM2860_BOARD_TVP5150_REFERENCE_DESIGN 29 -#define EM2820_BOARD_VIDEOLOGY_20K14XUSB 30 -#define EM2821_BOARD_USBGEAR_VD204 31 -#define EM2821_BOARD_SUPERCOMP_USB_2 32 -#define EM2860_BOARD_ELGATO_VIDEO_CAPTURE 33 -#define EM2860_BOARD_TERRATEC_HYBRID_XS 34 -#define EM2860_BOARD_TYPHOON_DVD_MAKER 35 -#define EM2860_BOARD_NETGMBH_CAM 36 -#define EM2860_BOARD_GADMEI_UTV330 37 -#define EM2861_BOARD_YAKUMO_MOVIE_MIXER 38 -#define EM2861_BOARD_KWORLD_PVRTV_300U 39 -#define EM2861_BOARD_PLEXTOR_PX_TV100U 40 -#define EM2870_BOARD_KWORLD_350U 41 -#define EM2870_BOARD_KWORLD_355U 42 -#define EM2870_BOARD_TERRATEC_XS 43 -#define EM2870_BOARD_TERRATEC_XS_MT2060 44 -#define EM2870_BOARD_PINNACLE_PCTV_DVB 45 -#define EM2870_BOARD_COMPRO_VIDEOMATE 46 -#define EM2880_BOARD_KWORLD_DVB_305U 47 -#define EM2880_BOARD_KWORLD_DVB_310U 48 -#define EM2880_BOARD_MSI_DIGIVOX_AD 49 -#define EM2880_BOARD_MSI_DIGIVOX_AD_II 50 -#define EM2880_BOARD_TERRATEC_HYBRID_XS_FR 51 -#define EM2881_BOARD_DNT_DA2_HYBRID 52 -#define EM2881_BOARD_PINNACLE_HYBRID_PRO 53 -#define EM2882_BOARD_KWORLD_VS_DVBT 54 -#define EM2882_BOARD_TERRATEC_HYBRID_XS 55 -#define EM2882_BOARD_PINNACLE_HYBRID_PRO_330E 56 -#define EM2883_BOARD_KWORLD_HYBRID_330U 57 -#define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58 -#define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 -#define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61 -#define EM2820_BOARD_GADMEI_TVR200 62 -#define EM2860_BOARD_KAIOMY_TVNPC_U2 63 -#define EM2860_BOARD_EASYCAP 64 -#define EM2820_BOARD_IODATA_GVMVP_SZ 65 -#define EM2880_BOARD_EMPIRE_DUAL_TV 66 -#define EM2860_BOARD_TERRATEC_GRABBY 67 -#define EM2860_BOARD_TERRATEC_AV350 68 -#define EM2882_BOARD_KWORLD_ATSC_315U 69 -#define EM2882_BOARD_EVGA_INDTUBE 70 -#define EM2820_BOARD_SILVERCREST_WEBCAM 71 -#define EM2861_BOARD_GADMEI_UTV330PLUS 72 -#define EM2870_BOARD_REDDO_DVB_C_USB_BOX 73 -#define EM2800_BOARD_VC211A 74 -#define EM2882_BOARD_DIKOM_DK300 75 -#define EM2870_BOARD_KWORLD_A340 76 -#define EM2874_BOARD_LEADERSHIP_ISDBT 77 -#define EM28174_BOARD_PCTV_290E 78 -#define EM2884_BOARD_TERRATEC_H5 79 -#define EM28174_BOARD_PCTV_460E 80 -#define EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C 81 -#define EM2884_BOARD_CINERGY_HTC_STICK 82 -#define EM2860_BOARD_HT_VIDBOX_NW03 83 -#define EM2874_BOARD_MAXMEDIA_UB425_TC 84 -#define EM2884_BOARD_PCTV_510E 85 -#define EM2884_BOARD_PCTV_520E 86 - -/* Limits minimum and default number of buffers */ -#define EM28XX_MIN_BUF 4 -#define EM28XX_DEF_BUF 8 - -/*Limits the max URB message size */ -#define URB_MAX_CTRL_SIZE 80 - -/* Params for validated field */ -#define EM28XX_BOARD_NOT_VALIDATED 1 -#define EM28XX_BOARD_VALIDATED 0 - -/* Params for em28xx_cmd() audio */ -#define EM28XX_START_AUDIO 1 -#define EM28XX_STOP_AUDIO 0 - -/* maximum number of em28xx boards */ -#define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */ - -/* maximum number of frames that can be queued */ -#define EM28XX_NUM_FRAMES 5 -/* number of frames that get used for v4l2_read() */ -#define EM28XX_NUM_READ_FRAMES 2 - -/* number of buffers for isoc transfers */ -#define EM28XX_NUM_BUFS 5 -#define EM28XX_DVB_NUM_BUFS 5 - -/* number of packets for each buffer - windows requests only 64 packets .. so we better do the same - this is what I found out for all alternate numbers there! - */ -#define EM28XX_NUM_PACKETS 64 -#define EM28XX_DVB_MAX_PACKETS 64 - -#define EM28XX_INTERLACED_DEFAULT 1 - -/* -#define (use usbview if you want to get the other alternate number infos) -#define -#define alternate number 2 -#define Endpoint Address: 82 - Direction: in - Attribute: 1 - Type: Isoc - Max Packet Size: 1448 - Interval: 125us - - alternate number 7 - - Endpoint Address: 82 - Direction: in - Attribute: 1 - Type: Isoc - Max Packet Size: 3072 - Interval: 125us -*/ - -/* time to wait when stopping the isoc transfer */ -#define EM28XX_URB_TIMEOUT \ - msecs_to_jiffies(EM28XX_NUM_BUFS * EM28XX_NUM_PACKETS) - -/* time in msecs to wait for i2c writes to finish */ -#define EM2800_I2C_WRITE_TIMEOUT 20 - -enum em28xx_mode { - EM28XX_SUSPEND, - EM28XX_ANALOG_MODE, - EM28XX_DIGITAL_MODE, -}; - - -struct em28xx; - -struct em28xx_usb_isoc_bufs { - /* max packet size of isoc transaction */ - int max_pkt_size; - - /* number of packets in each buffer */ - int num_packets; - - /* number of allocated urbs */ - int num_bufs; - - /* urb for isoc transfers */ - struct urb **urb; - - /* transfer buffers for isoc transfer */ - char **transfer_buffer; -}; - -struct em28xx_usb_isoc_ctl { - /* isoc transfer buffers for analog mode */ - struct em28xx_usb_isoc_bufs analog_bufs; - - /* isoc transfer buffers for digital mode */ - struct em28xx_usb_isoc_bufs digital_bufs; - - /* Stores already requested buffers */ - struct em28xx_buffer *vid_buf; - struct em28xx_buffer *vbi_buf; - - /* isoc urb callback */ - int (*isoc_copy) (struct em28xx *dev, struct urb *urb); - -}; - -/* Struct to enumberate video formats */ -struct em28xx_fmt { - char *name; - u32 fourcc; /* v4l2 format id */ - int depth; - int reg; -}; - -/* buffer for one video frame */ -struct em28xx_buffer { - /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - - struct list_head frame; - int top_field; -}; - -struct em28xx_dmaqueue { - struct list_head active; - - wait_queue_head_t wq; - - /* Counters to control buffer fill */ - int pos; -}; - -/* inputs */ - -#define MAX_EM28XX_INPUT 4 -enum enum28xx_itype { - EM28XX_VMUX_COMPOSITE1 = 1, - EM28XX_VMUX_COMPOSITE2, - EM28XX_VMUX_COMPOSITE3, - EM28XX_VMUX_COMPOSITE4, - EM28XX_VMUX_SVIDEO, - EM28XX_VMUX_TELEVISION, - EM28XX_VMUX_CABLE, - EM28XX_VMUX_DVB, - EM28XX_VMUX_DEBUG, - EM28XX_RADIO, -}; - -enum em28xx_ac97_mode { - EM28XX_NO_AC97 = 0, - EM28XX_AC97_EM202, - EM28XX_AC97_SIGMATEL, - EM28XX_AC97_OTHER, -}; - -struct em28xx_audio_mode { - enum em28xx_ac97_mode ac97; - - u16 ac97_feat; - u32 ac97_vendor_id; - - unsigned int has_audio:1; - - unsigned int i2s_3rates:1; - unsigned int i2s_5rates:1; -}; - -/* em28xx has two audio inputs: tuner and line in. - However, on most devices, an auxiliary AC97 codec device is used. - The AC97 device may have several different inputs and outputs, - depending on their model. So, it is possible to use AC97 mixer to - address more than two different entries. - */ -enum em28xx_amux { - /* This is the only entry for em28xx tuner input */ - EM28XX_AMUX_VIDEO, /* em28xx tuner, AC97 mixer Video */ - - EM28XX_AMUX_LINE_IN, /* AC97 mixer Line In */ - - /* Some less-common mixer setups */ - EM28XX_AMUX_VIDEO2, /* em28xx Line in, AC97 mixer Video */ - EM28XX_AMUX_PHONE, - EM28XX_AMUX_MIC, - EM28XX_AMUX_CD, - EM28XX_AMUX_AUX, - EM28XX_AMUX_PCM_OUT, -}; - -enum em28xx_aout { - /* AC97 outputs */ - EM28XX_AOUT_MASTER = 1 << 0, - EM28XX_AOUT_LINE = 1 << 1, - EM28XX_AOUT_MONO = 1 << 2, - EM28XX_AOUT_LFE = 1 << 3, - EM28XX_AOUT_SURR = 1 << 4, - - /* PCM IN Mixer - used by AC97_RECORD_SELECT register */ - EM28XX_AOUT_PCM_IN = 1 << 7, - - /* Bits 10-8 are used to indicate the PCM IN record select */ - EM28XX_AOUT_PCM_MIC_PCM = 0 << 8, - EM28XX_AOUT_PCM_CD = 1 << 8, - EM28XX_AOUT_PCM_VIDEO = 2 << 8, - EM28XX_AOUT_PCM_AUX = 3 << 8, - EM28XX_AOUT_PCM_LINE = 4 << 8, - EM28XX_AOUT_PCM_STEREO = 5 << 8, - EM28XX_AOUT_PCM_MONO = 6 << 8, - EM28XX_AOUT_PCM_PHONE = 7 << 8, -}; - -static inline int ac97_return_record_select(int a_out) -{ - return (a_out & 0x700) >> 8; -} - -struct em28xx_reg_seq { - int reg; - unsigned char val, mask; - int sleep; -}; - -struct em28xx_input { - enum enum28xx_itype type; - unsigned int vmux; - enum em28xx_amux amux; - enum em28xx_aout aout; - struct em28xx_reg_seq *gpio; -}; - -#define INPUT(nr) (&em28xx_boards[dev->model].input[nr]) - -enum em28xx_decoder { - EM28XX_NODECODER = 0, - EM28XX_TVP5150, - EM28XX_SAA711X, -}; - -enum em28xx_sensor { - EM28XX_NOSENSOR = 0, - EM28XX_MT9V011, - EM28XX_MT9M001, - EM28XX_MT9M111, -}; - -enum em28xx_adecoder { - EM28XX_NOADECODER = 0, - EM28XX_TVAUDIO, -}; - -struct em28xx_board { - char *name; - int vchannels; - int tuner_type; - int tuner_addr; - - /* i2c flags */ - unsigned int tda9887_conf; - - /* GPIO sequences */ - struct em28xx_reg_seq *dvb_gpio; - struct em28xx_reg_seq *suspend_gpio; - struct em28xx_reg_seq *tuner_gpio; - struct em28xx_reg_seq *mute_gpio; - - unsigned int is_em2800:1; - unsigned int has_msp34xx:1; - unsigned int mts_firmware:1; - unsigned int max_range_640_480:1; - unsigned int has_dvb:1; - unsigned int has_snapshot_button:1; - unsigned int is_webcam:1; - unsigned int valid:1; - unsigned int has_ir_i2c:1; - - unsigned char xclk, i2c_speed; - unsigned char radio_addr; - unsigned short tvaudio_addr; - - enum em28xx_decoder decoder; - enum em28xx_adecoder adecoder; - - struct em28xx_input input[MAX_EM28XX_INPUT]; - struct em28xx_input radio; - char *ir_codes; -}; - -struct em28xx_eeprom { - u32 id; /* 0x9567eb1a */ - u16 vendor_ID; - u16 product_ID; - - u16 chip_conf; - - u16 board_conf; - - u16 string1, string2, string3; - - u8 string_idx_table; -}; - -/* device states */ -enum em28xx_dev_state { - DEV_INITIALIZED = 0x01, - DEV_DISCONNECTED = 0x02, - DEV_MISCONFIGURED = 0x04, -}; - -#define EM28XX_AUDIO_BUFS 5 -#define EM28XX_NUM_AUDIO_PACKETS 64 -#define EM28XX_AUDIO_MAX_PACKET_SIZE 196 /* static value */ -#define EM28XX_CAPTURE_STREAM_EN 1 - -/* em28xx extensions */ -#define EM28XX_AUDIO 0x10 -#define EM28XX_DVB 0x20 -#define EM28XX_RC 0x30 - -/* em28xx resource types (used for res_get/res_lock etc */ -#define EM28XX_RESOURCE_VIDEO 0x01 -#define EM28XX_RESOURCE_VBI 0x02 - -struct em28xx_audio { - char name[50]; - char *transfer_buffer[EM28XX_AUDIO_BUFS]; - struct urb *urb[EM28XX_AUDIO_BUFS]; - struct usb_device *udev; - unsigned int capture_transfer_done; - struct snd_pcm_substream *capture_pcm_substream; - - unsigned int hwptr_done_capture; - struct snd_card *sndcard; - - int users; - spinlock_t slock; -}; - -struct em28xx; - -struct em28xx_fh { - struct em28xx *dev; - int radio; - unsigned int resources; - - struct videobuf_queue vb_vidq; - struct videobuf_queue vb_vbiq; - - enum v4l2_buf_type type; -}; - -/* main device struct */ -struct em28xx { - /* generic device properties */ - char name[30]; /* name (including minor) of the device */ - int model; /* index in the device_data struct */ - int devno; /* marks the number of this device */ - enum em28xx_chip_id chip_id; - - int audio_ifnum; - - struct v4l2_device v4l2_dev; - struct em28xx_board board; - - /* Webcam specific fields */ - enum em28xx_sensor em28xx_sensor; - int sensor_xres, sensor_yres; - int sensor_xtal; - - /* Allows progressive (e. g. non-interlaced) mode */ - int progressive; - - /* Vinmode/Vinctl used at the driver */ - int vinmode, vinctl; - - unsigned int has_audio_class:1; - unsigned int has_alsa_audio:1; - unsigned int is_audio_only:1; - - /* Controls audio streaming */ - struct work_struct wq_trigger; /* Trigger to start/stop audio for alsa module */ - atomic_t stream_started; /* stream should be running if true */ - - struct em28xx_fmt *format; - - struct em28xx_IR *ir; - - /* Some older em28xx chips needs a waiting time after writing */ - unsigned int wait_after_write; - - struct list_head devlist; - - u32 i2s_speed; /* I2S speed for audio digital stream */ - - struct em28xx_audio_mode audio_mode; - - int tuner_type; /* type of the tuner */ - int tuner_addr; /* tuner address */ - int tda9887_conf; - /* i2c i/o */ - struct i2c_adapter i2c_adap; - struct i2c_client i2c_client; - /* video for linux */ - int users; /* user count for exclusive use */ - struct video_device *vdev; /* video for linux device struct */ - v4l2_std_id norm; /* selected tv norm */ - int ctl_freq; /* selected frequency */ - unsigned int ctl_input; /* selected input */ - unsigned int ctl_ainput;/* selected audio input */ - unsigned int ctl_aoutput;/* selected audio output */ - int mute; - int volume; - /* frame properties */ - int width; /* current frame width */ - int height; /* current frame height */ - unsigned hscale; /* horizontal scale factor (see datasheet) */ - unsigned vscale; /* vertical scale factor (see datasheet) */ - int interlaced; /* 1=interlace fileds, 0=just top fileds */ - unsigned int video_bytesread; /* Number of bytes read */ - - unsigned long hash; /* eeprom hash - for boards with generic ID */ - unsigned long i2c_hash; /* i2c devicelist hash - - for boards with generic ID */ - - struct em28xx_audio adev; - - /* states */ - enum em28xx_dev_state state; - - /* vbi related state tracking */ - int capture_type; - int vbi_read; - unsigned char cur_field; - unsigned int vbi_width; - unsigned int vbi_height; /* lines per field */ - - struct work_struct request_module_wk; - - /* locks */ - struct mutex lock; - struct mutex ctrl_urb_lock; /* protects urb_buf */ - /* spinlock_t queue_lock; */ - struct list_head inqueue, outqueue; - struct video_device *vbi_dev; - struct video_device *radio_dev; - - /* resources in use */ - unsigned int resources; - - unsigned char eedata[256]; - - /* Isoc control struct */ - struct em28xx_dmaqueue vidq; - struct em28xx_dmaqueue vbiq; - struct em28xx_usb_isoc_ctl isoc_ctl; - spinlock_t slock; - - /* usb transfer */ - struct usb_device *udev; /* the usb device */ - int alt; /* alternate */ - int max_pkt_size; /* max packet size of isoc transaction */ - int num_alt; /* Number of alternative settings */ - unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ - int dvb_alt; /* alternate for DVB */ - unsigned int dvb_max_pkt_size; /* wMaxPacketSize for DVB */ - char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ - - /* helper funcs that call usb_control_msg */ - int (*em28xx_write_regs) (struct em28xx *dev, u16 reg, - char *buf, int len); - int (*em28xx_read_reg) (struct em28xx *dev, u16 reg); - int (*em28xx_read_reg_req_len) (struct em28xx *dev, u8 req, u16 reg, - char *buf, int len); - int (*em28xx_write_regs_req) (struct em28xx *dev, u8 req, u16 reg, - char *buf, int len); - int (*em28xx_read_reg_req) (struct em28xx *dev, u8 req, u16 reg); - - enum em28xx_mode mode; - - /* register numbers for GPO/GPIO registers */ - u16 reg_gpo_num, reg_gpio_num; - - /* Caches GPO and GPIO registers */ - unsigned char reg_gpo, reg_gpio; - - /* Snapshot button */ - char snapshot_button_path[30]; /* path of the input dev */ - struct input_dev *sbutton_input_dev; - struct delayed_work sbutton_query_work; - - struct em28xx_dvb *dvb; - - /* I2C keyboard data */ - struct IR_i2c_init_data init_data; -}; - -struct em28xx_ops { - struct list_head next; - char *name; - int id; - int (*init)(struct em28xx *); - int (*fini)(struct em28xx *); -}; - -/* Provided by em28xx-i2c.c */ -void em28xx_do_i2c_scan(struct em28xx *dev); -int em28xx_i2c_register(struct em28xx *dev); -int em28xx_i2c_unregister(struct em28xx *dev); - -/* Provided by em28xx-core.c */ - -u32 em28xx_request_buffers(struct em28xx *dev, u32 count); -void em28xx_queue_unusedframes(struct em28xx *dev); -void em28xx_release_buffers(struct em28xx *dev); - -int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, - char *buf, int len); -int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg); -int em28xx_read_reg(struct em28xx *dev, u16 reg); -int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, - int len); -int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len); -int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val); -int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, - u8 bitmask); - -int em28xx_read_ac97(struct em28xx *dev, u8 reg); -int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val); - -int em28xx_audio_analog_set(struct em28xx *dev); -int em28xx_audio_setup(struct em28xx *dev); - -int em28xx_colorlevels_set_default(struct em28xx *dev); -int em28xx_capture_start(struct em28xx *dev, int start); -int em28xx_vbi_supported(struct em28xx *dev); -int em28xx_set_outfmt(struct em28xx *dev); -int em28xx_resolution_set(struct em28xx *dev); -int em28xx_set_alternate(struct em28xx *dev); -int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode, - int max_packets, int num_bufs, int max_pkt_size); -int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode, - int max_packets, int num_bufs, int max_pkt_size, - int (*isoc_copy) (struct em28xx *dev, struct urb *urb)); -void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode); -void em28xx_stop_urbs(struct em28xx *dev); -int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev); -int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode); -int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); -void em28xx_wake_i2c(struct em28xx *dev); -int em28xx_register_extension(struct em28xx_ops *dev); -void em28xx_unregister_extension(struct em28xx_ops *dev); -void em28xx_init_extension(struct em28xx *dev); -void em28xx_close_extension(struct em28xx *dev); - -/* Provided by em28xx-video.c */ -int em28xx_register_analog_devices(struct em28xx *dev); -void em28xx_release_analog_resources(struct em28xx *dev); - -/* Provided by em28xx-cards.c */ -extern int em2800_variant_detect(struct usb_device *udev, int model); -extern struct em28xx_board em28xx_boards[]; -extern struct usb_device_id em28xx_id_table[]; -extern const unsigned int em28xx_bcount; -int em28xx_tuner_callback(void *ptr, int component, int command, int arg); -void em28xx_release_resources(struct em28xx *dev); - -/* Provided by em28xx-vbi.c */ -extern struct videobuf_queue_ops em28xx_vbi_qops; - -/* printk macros */ - -#define em28xx_err(fmt, arg...) do {\ - printk(KERN_ERR fmt , ##arg); } while (0) - -#define em28xx_errdev(fmt, arg...) do {\ - printk(KERN_ERR "%s: "fmt,\ - dev->name , ##arg); } while (0) - -#define em28xx_info(fmt, arg...) do {\ - printk(KERN_INFO "%s: "fmt,\ - dev->name , ##arg); } while (0) -#define em28xx_warn(fmt, arg...) do {\ - printk(KERN_WARNING "%s: "fmt,\ - dev->name , ##arg); } while (0) - -static inline int em28xx_compression_disable(struct em28xx *dev) -{ - /* side effect of disabling scaler and mixer */ - return em28xx_write_reg(dev, EM28XX_R26_COMPR, 0x00); -} - -static inline int em28xx_contrast_get(struct em28xx *dev) -{ - return em28xx_read_reg(dev, EM28XX_R20_YGAIN) & 0x1f; -} - -static inline int em28xx_brightness_get(struct em28xx *dev) -{ - return em28xx_read_reg(dev, EM28XX_R21_YOFFSET); -} - -static inline int em28xx_saturation_get(struct em28xx *dev) -{ - return em28xx_read_reg(dev, EM28XX_R22_UVGAIN) & 0x1f; -} - -static inline int em28xx_u_balance_get(struct em28xx *dev) -{ - return em28xx_read_reg(dev, EM28XX_R23_UOFFSET); -} - -static inline int em28xx_v_balance_get(struct em28xx *dev) -{ - return em28xx_read_reg(dev, EM28XX_R24_VOFFSET); -} - -static inline int em28xx_gamma_get(struct em28xx *dev) -{ - return em28xx_read_reg(dev, EM28XX_R14_GAMMA) & 0x3f; -} - -static inline int em28xx_contrast_set(struct em28xx *dev, s32 val) -{ - u8 tmp = (u8) val; - return em28xx_write_regs(dev, EM28XX_R20_YGAIN, &tmp, 1); -} - -static inline int em28xx_brightness_set(struct em28xx *dev, s32 val) -{ - u8 tmp = (u8) val; - return em28xx_write_regs(dev, EM28XX_R21_YOFFSET, &tmp, 1); -} - -static inline int em28xx_saturation_set(struct em28xx *dev, s32 val) -{ - u8 tmp = (u8) val; - return em28xx_write_regs(dev, EM28XX_R22_UVGAIN, &tmp, 1); -} - -static inline int em28xx_u_balance_set(struct em28xx *dev, s32 val) -{ - u8 tmp = (u8) val; - return em28xx_write_regs(dev, EM28XX_R23_UOFFSET, &tmp, 1); -} - -static inline int em28xx_v_balance_set(struct em28xx *dev, s32 val) -{ - u8 tmp = (u8) val; - return em28xx_write_regs(dev, EM28XX_R24_VOFFSET, &tmp, 1); -} - -static inline int em28xx_gamma_set(struct em28xx *dev, s32 val) -{ - u8 tmp = (u8) val; - return em28xx_write_regs(dev, EM28XX_R14_GAMMA, &tmp, 1); -} - -/*FIXME: maxw should be dependent of alt mode */ -static inline unsigned int norm_maxw(struct em28xx *dev) -{ - if (dev->board.is_webcam) - return dev->sensor_xres; - - if (dev->board.max_range_640_480) - return 640; - - return 720; -} - -static inline unsigned int norm_maxh(struct em28xx *dev) -{ - if (dev->board.is_webcam) - return dev->sensor_yres; - - if (dev->board.max_range_640_480) - return 480; - - return (dev->norm & V4L2_STD_625_50) ? 576 : 480; -} -#endif diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig deleted file mode 100644 index dfe268bfa4f8..000000000000 --- a/drivers/media/video/gspca/Kconfig +++ /dev/null @@ -1,425 +0,0 @@ -menuconfig USB_GSPCA - tristate "GSPCA based webcams" - depends on VIDEO_V4L2 - default m - ---help--- - Say Y here if you want to enable selecting webcams based - on the GSPCA framework. - - See <file:Documentation/video4linux/gspca.txt> for more info. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" to use this driver. - - To compile this driver as modules, choose M here: the - module will be called gspca_main. - - -if USB_GSPCA && VIDEO_V4L2 - -source "drivers/media/video/gspca/m5602/Kconfig" -source "drivers/media/video/gspca/stv06xx/Kconfig" -source "drivers/media/video/gspca/gl860/Kconfig" - -config USB_GSPCA_BENQ - tristate "Benq USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for the Benq DC E300 camera. - - To compile this driver as a module, choose M here: the - module will be called gspca_benq. - -config USB_GSPCA_CONEX - tristate "Conexant Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the Conexant chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_conex. - -config USB_GSPCA_CPIA1 - tristate "cpia CPiA (version 1) Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for USB cameras based on the cpia - CPiA chip. Note that you need atleast version 0.6.4 of libv4l for - applications to understand the videoformat generated by this driver. - - To compile this driver as a module, choose M here: the - module will be called gspca_cpia1. - -config USB_GSPCA_ETOMS - tristate "Etoms USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the Etoms chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_etoms. - -config USB_GSPCA_FINEPIX - tristate "Fujifilm FinePix USB V4L2 driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the FinePix chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_finepix. - -config USB_GSPCA_JEILINJ - tristate "Jeilin JPEG USB V4L2 driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on this Jeilin chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_jeilinj. - -config USB_GSPCA_JL2005BCD - tristate "JL2005B/C/D USB V4L2 driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based the - JL2005B, JL2005C, or JL2005D chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_jl2005bcd. - -config USB_GSPCA_KINECT - tristate "Kinect sensor device USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for the Microsoft Kinect sensor device. - - To compile this driver as a module, choose M here: the - module will be called gspca_kinect. - -config USB_GSPCA_KONICA - tristate "Konica USB Camera V4L2 driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the Konica chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_konica. - -config USB_GSPCA_MARS - tristate "Mars USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the Mars chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_mars. - -config USB_GSPCA_MR97310A - tristate "Mars-Semi MR97310A USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the MR97310A chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_mr97310a. - -config USB_GSPCA_NW80X - tristate "Divio based (NW80x) USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the NW80x chips. - - To compile this driver as a module, choose M here: the - module will be called gspca_nw80x. - -config USB_GSPCA_OV519 - tristate "OV51x / OVFX2 / W996xCF USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on one of these: - OV511(+), OV518(+), OV519, OVFX2, W9967CF, W9968CF - - To compile this driver as a module, choose M here: the - module will be called gspca_ov519. - -config USB_GSPCA_OV534 - tristate "OV534 OV772x USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the OV534 chip - and sensor OV772x (e.g. Sony Playstation EYE) - - To compile this driver as a module, choose M here: the - module will be called gspca_ov534. - -config USB_GSPCA_OV534_9 - tristate "OV534 OV965x USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the OV534 chip - and sensor OV965x (e.g. Hercules Dualpix) - - To compile this driver as a module, choose M here: the - module will be called gspca_ov534_9. - -config USB_GSPCA_PAC207 - tristate "Pixart PAC207 USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the PAC207 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_pac207. - -config USB_GSPCA_PAC7302 - tristate "Pixart PAC7302 USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the PAC7302 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_pac7302. - -config USB_GSPCA_PAC7311 - tristate "Pixart PAC7311 USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the PAC7311 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_pac7311. - -config USB_GSPCA_SE401 - tristate "SE401 USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the - Endpoints (formerly known as AOX) se401 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_se401. - -config USB_GSPCA_SN9C2028 - tristate "SONIX Dual-Mode USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want streaming support for Sonix SN9C2028 cameras. - These are supported as stillcams in libgphoto2/camlibs/sonix. - - To compile this driver as a module, choose M here: the - module will be called gspca_sn9c2028. - -config USB_GSPCA_SN9C20X - tristate "SN9C20X USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the - sn9c20x chips (SN9C201 and SN9C202). - - To compile this driver as a module, choose M here: the - module will be called gspca_sn9c20x. - -config USB_GSPCA_SONIXB - tristate "SONIX Bayer USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the Sonix - chips with Bayer format (SN9C101, SN9C102 and SN9C103). - - To compile this driver as a module, choose M here: the - module will be called gspca_sonixb. - -config USB_GSPCA_SONIXJ - tristate "SONIX JPEG USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the Sonix - chips with JPEG format (SN9C102P, SN9C105 and >= SN9C110). - - To compile this driver as a module, choose M here: the - module will be called gspca_sonixj - -config USB_GSPCA_SPCA500 - tristate "SPCA500 USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the SPCA500 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_spca500. - -config USB_GSPCA_SPCA501 - tristate "SPCA501 USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the SPCA501 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_spca501. - -config USB_GSPCA_SPCA505 - tristate "SPCA505 USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the SPCA505 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_spca505. - -config USB_GSPCA_SPCA506 - tristate "SPCA506 USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the SPCA506 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_spca506. - -config USB_GSPCA_SPCA508 - tristate "SPCA508 USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the SPCA508 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_spca508. - -config USB_GSPCA_SPCA561 - tristate "SPCA561 USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the SPCA561 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_spca561. - -config USB_GSPCA_SPCA1528 - tristate "SPCA1528 USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the SPCA1528 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_spca1528. - -config USB_GSPCA_SQ905 - tristate "SQ Technologies SQ905 based USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the SQ905 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_sq905. - -config USB_GSPCA_SQ905C - tristate "SQ Technologies SQ905C based USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the SQ905C chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_sq905c. - -config USB_GSPCA_SQ930X - tristate "SQ Technologies SQ930X based USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the SQ930X chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_sq930x. - -config USB_GSPCA_STK014 - tristate "Syntek DV4000 (STK014) USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the STK014 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_stk014. - -config USB_GSPCA_STV0680 - tristate "STV0680 USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the STV0680 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_stv0680. - -config USB_GSPCA_SUNPLUS - tristate "SUNPLUS USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the Sunplus - SPCA504(abc) SPCA533 SPCA536 chips. - - To compile this driver as a module, choose M here: the - module will be called gspca_sunplus. - -config USB_GSPCA_T613 - tristate "T613 (JPEG Compliance) USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the T613 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_t613. - -config USB_GSPCA_TOPRO - tristate "TOPRO USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the - TP6800 and TP6810 Topro chips. - - To compile this driver as a module, choose M here: the - module will be called gspca_topro. - -config USB_GSPCA_TV8532 - tristate "TV8532 USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the TV8531 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_tv8532. - -config USB_GSPCA_VC032X - tristate "VC032X USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the VC032X chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_vc032x. - -config USB_GSPCA_VICAM - tristate "ViCam USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for the 3com homeconnect camera - (vicam). - - To compile this driver as a module, choose M here: the - module will be called gspca_vicam. - -config USB_GSPCA_XIRLINK_CIT - tristate "Xirlink C-It USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for Xirlink C-It bases cameras. - - To compile this driver as a module, choose M here: the - module will be called gspca_xirlink_cit. - -config USB_GSPCA_ZC3XX - tristate "ZC3XX USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the ZC3XX chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_zc3xx. - -endif diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile deleted file mode 100644 index c901da0bd657..000000000000 --- a/drivers/media/video/gspca/Makefile +++ /dev/null @@ -1,93 +0,0 @@ -obj-$(CONFIG_USB_GSPCA) += gspca_main.o -obj-$(CONFIG_USB_GSPCA_BENQ) += gspca_benq.o -obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o -obj-$(CONFIG_USB_GSPCA_CPIA1) += gspca_cpia1.o -obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o -obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o -obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o -obj-$(CONFIG_USB_GSPCA_JL2005BCD) += gspca_jl2005bcd.o -obj-$(CONFIG_USB_GSPCA_KINECT) += gspca_kinect.o -obj-$(CONFIG_USB_GSPCA_KONICA) += gspca_konica.o -obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o -obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o -obj-$(CONFIG_USB_GSPCA_NW80X) += gspca_nw80x.o -obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o -obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o -obj-$(CONFIG_USB_GSPCA_OV534_9) += gspca_ov534_9.o -obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o -obj-$(CONFIG_USB_GSPCA_PAC7302) += gspca_pac7302.o -obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o -obj-$(CONFIG_USB_GSPCA_SE401) += gspca_se401.o -obj-$(CONFIG_USB_GSPCA_SN9C2028) += gspca_sn9c2028.o -obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o -obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o -obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o -obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o -obj-$(CONFIG_USB_GSPCA_SPCA501) += gspca_spca501.o -obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o -obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o -obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o -obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o -obj-$(CONFIG_USB_GSPCA_SPCA1528) += gspca_spca1528.o -obj-$(CONFIG_USB_GSPCA_SQ905) += gspca_sq905.o -obj-$(CONFIG_USB_GSPCA_SQ905C) += gspca_sq905c.o -obj-$(CONFIG_USB_GSPCA_SQ930X) += gspca_sq930x.o -obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o -obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o -obj-$(CONFIG_USB_GSPCA_STV0680) += gspca_stv0680.o -obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o -obj-$(CONFIG_USB_GSPCA_TOPRO) += gspca_topro.o -obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o -obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o -obj-$(CONFIG_USB_GSPCA_VICAM) += gspca_vicam.o -obj-$(CONFIG_USB_GSPCA_XIRLINK_CIT) += gspca_xirlink_cit.o -obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o - -gspca_main-objs := gspca.o autogain_functions.o -gspca_benq-objs := benq.o -gspca_conex-objs := conex.o -gspca_cpia1-objs := cpia1.o -gspca_etoms-objs := etoms.o -gspca_finepix-objs := finepix.o -gspca_jeilinj-objs := jeilinj.o -gspca_jl2005bcd-objs := jl2005bcd.o -gspca_kinect-objs := kinect.o -gspca_konica-objs := konica.o -gspca_mars-objs := mars.o -gspca_mr97310a-objs := mr97310a.o -gspca_nw80x-objs := nw80x.o -gspca_ov519-objs := ov519.o -gspca_ov534-objs := ov534.o -gspca_ov534_9-objs := ov534_9.o -gspca_pac207-objs := pac207.o -gspca_pac7302-objs := pac7302.o -gspca_pac7311-objs := pac7311.o -gspca_se401-objs := se401.o -gspca_sn9c2028-objs := sn9c2028.o -gspca_sn9c20x-objs := sn9c20x.o -gspca_sonixb-objs := sonixb.o -gspca_sonixj-objs := sonixj.o -gspca_spca500-objs := spca500.o -gspca_spca501-objs := spca501.o -gspca_spca505-objs := spca505.o -gspca_spca506-objs := spca506.o -gspca_spca508-objs := spca508.o -gspca_spca561-objs := spca561.o -gspca_spca1528-objs := spca1528.o -gspca_sq905-objs := sq905.o -gspca_sq905c-objs := sq905c.o -gspca_sq930x-objs := sq930x.o -gspca_stk014-objs := stk014.o -gspca_stv0680-objs := stv0680.o -gspca_sunplus-objs := sunplus.o -gspca_t613-objs := t613.o -gspca_topro-objs := topro.o -gspca_tv8532-objs := tv8532.o -gspca_vc032x-objs := vc032x.o -gspca_vicam-objs := vicam.o -gspca_xirlink_cit-objs := xirlink_cit.o -gspca_zc3xx-objs := zc3xx.o - -obj-$(CONFIG_USB_M5602) += m5602/ -obj-$(CONFIG_USB_STV06XX) += stv06xx/ -obj-$(CONFIG_USB_GL860) += gl860/ diff --git a/drivers/media/video/gspca/autogain_functions.c b/drivers/media/video/gspca/autogain_functions.c deleted file mode 100644 index 67db674bb044..000000000000 --- a/drivers/media/video/gspca/autogain_functions.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Functions for auto gain. - * - * Copyright (C) 2010-2012 Hans de Goede <hdegoede@redhat.com> - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "gspca.h" - -/* auto gain and exposure algorithm based on the knee algorithm described here: - http://ytse.tricolour.net/docs/LowLightOptimization.html - - Returns 0 if no changes were made, 1 if the gain and or exposure settings - where changed. */ -int gspca_expo_autogain( - struct gspca_dev *gspca_dev, - int avg_lum, - int desired_avg_lum, - int deadzone, - int gain_knee, - int exposure_knee) -{ - s32 gain, orig_gain, exposure, orig_exposure; - int i, steps, retval = 0; - - if (v4l2_ctrl_g_ctrl(gspca_dev->autogain) == 0) - return 0; - - orig_gain = gain = v4l2_ctrl_g_ctrl(gspca_dev->gain); - orig_exposure = exposure = v4l2_ctrl_g_ctrl(gspca_dev->exposure); - - /* If we are of a multiple of deadzone, do multiple steps to reach the - desired lumination fast (with the risc of a slight overshoot) */ - steps = abs(desired_avg_lum - avg_lum) / deadzone; - - PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d", - avg_lum, desired_avg_lum, steps); - - for (i = 0; i < steps; i++) { - if (avg_lum > desired_avg_lum) { - if (gain > gain_knee) - gain--; - else if (exposure > exposure_knee) - exposure--; - else if (gain > gspca_dev->gain->default_value) - gain--; - else if (exposure > gspca_dev->exposure->minimum) - exposure--; - else if (gain > gspca_dev->gain->minimum) - gain--; - else - break; - } else { - if (gain < gspca_dev->gain->default_value) - gain++; - else if (exposure < exposure_knee) - exposure++; - else if (gain < gain_knee) - gain++; - else if (exposure < gspca_dev->exposure->maximum) - exposure++; - else if (gain < gspca_dev->gain->maximum) - gain++; - else - break; - } - } - - if (gain != orig_gain) { - v4l2_ctrl_s_ctrl(gspca_dev->gain, gain); - retval = 1; - } - if (exposure != orig_exposure) { - v4l2_ctrl_s_ctrl(gspca_dev->exposure, exposure); - retval = 1; - } - - if (retval) - PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d", - gain, exposure); - return retval; -} -EXPORT_SYMBOL(gspca_expo_autogain); - -/* Autogain + exposure algorithm for cameras with a coarse exposure control - (usually this means we can only control the clockdiv to change exposure) - As changing the clockdiv so that the fps drops from 30 to 15 fps for - example, will lead to a huge exposure change (it effectively doubles), - this algorithm normally tries to only adjust the gain (between 40 and - 80 %) and if that does not help, only then changes exposure. This leads - to a much more stable image then using the knee algorithm which at - certain points of the knee graph will only try to adjust exposure, - which leads to oscilating as one exposure step is huge. - - Returns 0 if no changes were made, 1 if the gain and or exposure settings - where changed. */ -int gspca_coarse_grained_expo_autogain( - struct gspca_dev *gspca_dev, - int avg_lum, - int desired_avg_lum, - int deadzone) -{ - s32 gain_low, gain_high, gain, orig_gain, exposure, orig_exposure; - int steps, retval = 0; - - if (v4l2_ctrl_g_ctrl(gspca_dev->autogain) == 0) - return 0; - - orig_gain = gain = v4l2_ctrl_g_ctrl(gspca_dev->gain); - orig_exposure = exposure = v4l2_ctrl_g_ctrl(gspca_dev->exposure); - - gain_low = (gspca_dev->gain->maximum - gspca_dev->gain->minimum) / - 5 * 2 + gspca_dev->gain->minimum; - gain_high = (gspca_dev->gain->maximum - gspca_dev->gain->minimum) / - 5 * 4 + gspca_dev->gain->minimum; - - /* If we are of a multiple of deadzone, do multiple steps to reach the - desired lumination fast (with the risc of a slight overshoot) */ - steps = (desired_avg_lum - avg_lum) / deadzone; - - PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d", - avg_lum, desired_avg_lum, steps); - - if ((gain + steps) > gain_high && - exposure < gspca_dev->exposure->maximum) { - gain = gain_high; - gspca_dev->exp_too_low_cnt++; - gspca_dev->exp_too_high_cnt = 0; - } else if ((gain + steps) < gain_low && - exposure > gspca_dev->exposure->minimum) { - gain = gain_low; - gspca_dev->exp_too_high_cnt++; - gspca_dev->exp_too_low_cnt = 0; - } else { - gain += steps; - if (gain > gspca_dev->gain->maximum) - gain = gspca_dev->gain->maximum; - else if (gain < gspca_dev->gain->minimum) - gain = gspca_dev->gain->minimum; - gspca_dev->exp_too_high_cnt = 0; - gspca_dev->exp_too_low_cnt = 0; - } - - if (gspca_dev->exp_too_high_cnt > 3) { - exposure--; - gspca_dev->exp_too_high_cnt = 0; - } else if (gspca_dev->exp_too_low_cnt > 3) { - exposure++; - gspca_dev->exp_too_low_cnt = 0; - } - - if (gain != orig_gain) { - v4l2_ctrl_s_ctrl(gspca_dev->gain, gain); - retval = 1; - } - if (exposure != orig_exposure) { - v4l2_ctrl_s_ctrl(gspca_dev->exposure, exposure); - retval = 1; - } - - if (retval) - PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d", - gain, exposure); - return retval; -} -EXPORT_SYMBOL(gspca_coarse_grained_expo_autogain); diff --git a/drivers/media/video/gspca/autogain_functions.h b/drivers/media/video/gspca/autogain_functions.h deleted file mode 100644 index d625eafe63eb..000000000000 --- a/drivers/media/video/gspca/autogain_functions.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Functions for auto gain. - * - * Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.com> - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef WANT_REGULAR_AUTOGAIN -/* auto gain and exposure algorithm based on the knee algorithm described here: - http://ytse.tricolour.net/docs/LowLightOptimization.html - - Returns 0 if no changes were made, 1 if the gain and or exposure settings - where changed. */ -static inline int auto_gain_n_exposure( - struct gspca_dev *gspca_dev, - int avg_lum, - int desired_avg_lum, - int deadzone, - int gain_knee, - int exposure_knee) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i, steps, gain, orig_gain, exposure, orig_exposure; - int retval = 0; - - orig_gain = gain = sd->ctrls[GAIN].val; - orig_exposure = exposure = sd->ctrls[EXPOSURE].val; - - /* If we are of a multiple of deadzone, do multiple steps to reach the - desired lumination fast (with the risc of a slight overshoot) */ - steps = abs(desired_avg_lum - avg_lum) / deadzone; - - PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d", - avg_lum, desired_avg_lum, steps); - - for (i = 0; i < steps; i++) { - if (avg_lum > desired_avg_lum) { - if (gain > gain_knee) - gain--; - else if (exposure > exposure_knee) - exposure--; - else if (gain > sd->ctrls[GAIN].def) - gain--; - else if (exposure > sd->ctrls[EXPOSURE].min) - exposure--; - else if (gain > sd->ctrls[GAIN].min) - gain--; - else - break; - } else { - if (gain < sd->ctrls[GAIN].def) - gain++; - else if (exposure < exposure_knee) - exposure++; - else if (gain < gain_knee) - gain++; - else if (exposure < sd->ctrls[EXPOSURE].max) - exposure++; - else if (gain < sd->ctrls[GAIN].max) - gain++; - else - break; - } - } - - if (gain != orig_gain) { - sd->ctrls[GAIN].val = gain; - setgain(gspca_dev); - retval = 1; - } - if (exposure != orig_exposure) { - sd->ctrls[EXPOSURE].val = exposure; - setexposure(gspca_dev); - retval = 1; - } - - if (retval) - PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d", - gain, exposure); - return retval; -} -#endif - -#ifdef WANT_COARSE_EXPO_AUTOGAIN -/* Autogain + exposure algorithm for cameras with a coarse exposure control - (usually this means we can only control the clockdiv to change exposure) - As changing the clockdiv so that the fps drops from 30 to 15 fps for - example, will lead to a huge exposure change (it effectively doubles), - this algorithm normally tries to only adjust the gain (between 40 and - 80 %) and if that does not help, only then changes exposure. This leads - to a much more stable image then using the knee algorithm which at - certain points of the knee graph will only try to adjust exposure, - which leads to oscilating as one exposure step is huge. - - Note this assumes that the sd struct for the cam in question has - exp_too_low_cnt and exp_too_high_cnt int members for use by this function. - - Returns 0 if no changes were made, 1 if the gain and or exposure settings - where changed. */ -static inline int coarse_grained_expo_autogain( - struct gspca_dev *gspca_dev, - int avg_lum, - int desired_avg_lum, - int deadzone) -{ - struct sd *sd = (struct sd *) gspca_dev; - int steps, gain, orig_gain, exposure, orig_exposure; - int gain_low, gain_high; - int retval = 0; - - orig_gain = gain = sd->ctrls[GAIN].val; - orig_exposure = exposure = sd->ctrls[EXPOSURE].val; - - gain_low = (sd->ctrls[GAIN].max - sd->ctrls[GAIN].min) / 5 * 2; - gain_low += sd->ctrls[GAIN].min; - gain_high = (sd->ctrls[GAIN].max - sd->ctrls[GAIN].min) / 5 * 4; - gain_high += sd->ctrls[GAIN].min; - - /* If we are of a multiple of deadzone, do multiple steps to reach the - desired lumination fast (with the risc of a slight overshoot) */ - steps = (desired_avg_lum - avg_lum) / deadzone; - - PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d", - avg_lum, desired_avg_lum, steps); - - if ((gain + steps) > gain_high && - exposure < sd->ctrls[EXPOSURE].max) { - gain = gain_high; - sd->exp_too_low_cnt++; - sd->exp_too_high_cnt = 0; - } else if ((gain + steps) < gain_low && - exposure > sd->ctrls[EXPOSURE].min) { - gain = gain_low; - sd->exp_too_high_cnt++; - sd->exp_too_low_cnt = 0; - } else { - gain += steps; - if (gain > sd->ctrls[GAIN].max) - gain = sd->ctrls[GAIN].max; - else if (gain < sd->ctrls[GAIN].min) - gain = sd->ctrls[GAIN].min; - sd->exp_too_high_cnt = 0; - sd->exp_too_low_cnt = 0; - } - - if (sd->exp_too_high_cnt > 3) { - exposure--; - sd->exp_too_high_cnt = 0; - } else if (sd->exp_too_low_cnt > 3) { - exposure++; - sd->exp_too_low_cnt = 0; - } - - if (gain != orig_gain) { - sd->ctrls[GAIN].val = gain; - setgain(gspca_dev); - retval = 1; - } - if (exposure != orig_exposure) { - sd->ctrls[EXPOSURE].val = exposure; - setexposure(gspca_dev); - retval = 1; - } - - if (retval) - PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d", - gain, exposure); - return retval; -} -#endif diff --git a/drivers/media/video/gspca/benq.c b/drivers/media/video/gspca/benq.c deleted file mode 100644 index 352f32190e68..000000000000 --- a/drivers/media/video/gspca/benq.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Benq DC E300 subdriver - * - * Copyright (C) 2009 Jean-Francois Moine (http://moinejf.free.fr) - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "benq" - -#include "gspca.h" - -MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); -MODULE_DESCRIPTION("Benq DC E300 USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ -}; - -static const struct v4l2_pix_format vga_mode[] = { - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG}, -}; - -static void sd_isoc_irq(struct urb *urb); - -/* -- write a register -- */ -static void reg_w(struct gspca_dev *gspca_dev, - u16 value, u16 index) -{ - struct usb_device *dev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return; - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x02, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - NULL, - 0, - 500); - if (ret < 0) { - pr_err("reg_w err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - gspca_dev->cam.cam_mode = vga_mode; - gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); - gspca_dev->cam.no_urb_create = 1; - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - return 0; -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct urb *urb; - int i, n; - - /* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */ -#if MAX_NURBS < 4 -#error "Not enough URBs in the gspca table" -#endif -#define SD_PKT_SZ 64 -#define SD_NPKT 32 - for (n = 0; n < 4; n++) { - urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL); - if (!urb) { - pr_err("usb_alloc_urb failed\n"); - return -ENOMEM; - } - gspca_dev->urb[n] = urb; - urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev, - SD_PKT_SZ * SD_NPKT, - GFP_KERNEL, - &urb->transfer_dma); - - if (urb->transfer_buffer == NULL) { - pr_err("usb_alloc_coherent failed\n"); - return -ENOMEM; - } - urb->dev = gspca_dev->dev; - urb->context = gspca_dev; - urb->transfer_buffer_length = SD_PKT_SZ * SD_NPKT; - urb->pipe = usb_rcvisocpipe(gspca_dev->dev, - n & 1 ? 0x82 : 0x83); - urb->transfer_flags = URB_ISO_ASAP - | URB_NO_TRANSFER_DMA_MAP; - urb->interval = 1; - urb->complete = sd_isoc_irq; - urb->number_of_packets = SD_NPKT; - for (i = 0; i < SD_NPKT; i++) { - urb->iso_frame_desc[i].length = SD_PKT_SZ; - urb->iso_frame_desc[i].offset = SD_PKT_SZ * i; - } - } - - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct usb_interface *intf; - - reg_w(gspca_dev, 0x003c, 0x0003); - reg_w(gspca_dev, 0x003c, 0x0004); - reg_w(gspca_dev, 0x003c, 0x0005); - reg_w(gspca_dev, 0x003c, 0x0006); - reg_w(gspca_dev, 0x003c, 0x0007); - - intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); - usb_set_interface(gspca_dev->dev, gspca_dev->iface, - intf->num_altsetting - 1); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - /* unused */ -} - -/* reception of an URB */ -static void sd_isoc_irq(struct urb *urb) -{ - struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; - struct urb *urb0; - u8 *data; - int i, st; - - PDEBUG(D_PACK, "sd isoc irq"); - if (!gspca_dev->streaming) - return; - if (urb->status != 0) { - if (urb->status == -ESHUTDOWN) - return; /* disconnection */ -#ifdef CONFIG_PM - if (gspca_dev->frozen) - return; -#endif - pr_err("urb status: %d\n", urb->status); - return; - } - - /* if this is a control URN (ep 0x83), wait */ - if (urb == gspca_dev->urb[0] || urb == gspca_dev->urb[2]) - return; - - /* scan both received URBs */ - if (urb == gspca_dev->urb[1]) - urb0 = gspca_dev->urb[0]; - else - urb0 = gspca_dev->urb[2]; - for (i = 0; i < urb->number_of_packets; i++) { - - /* check the packet status and length */ - if (urb0->iso_frame_desc[i].actual_length != SD_PKT_SZ - || urb->iso_frame_desc[i].actual_length != SD_PKT_SZ) { - PDEBUG(D_ERR, "ISOC bad lengths %d / %d", - urb0->iso_frame_desc[i].actual_length, - urb->iso_frame_desc[i].actual_length); - gspca_dev->last_packet_type = DISCARD_PACKET; - continue; - } - st = urb0->iso_frame_desc[i].status; - if (st == 0) - st = urb->iso_frame_desc[i].status; - if (st) { - pr_err("ISOC data error: [%d] status=%d\n", - i, st); - gspca_dev->last_packet_type = DISCARD_PACKET; - continue; - } - - /* - * The images are received in URBs of different endpoints - * (0x83 and 0x82). - * Image pieces in URBs of ep 0x83 are continuated in URBs of - * ep 0x82 of the same index. - * The packets in the URBs of endpoint 0x83 start with: - * - 80 ba/bb 00 00 = start of image followed by 'ff d8' - * - 04 ba/bb oo oo = image piece - * where 'oo oo' is the image offset - (not cheked) - * - (other -> bad frame) - * The images are JPEG encoded with full header and - * normal ff escape. - * The end of image ('ff d9') may occur in any URB. - * (not cheked) - */ - data = (u8 *) urb0->transfer_buffer - + urb0->iso_frame_desc[i].offset; - if (data[0] == 0x80 && (data[1] & 0xfe) == 0xba) { - - /* new image */ - gspca_frame_add(gspca_dev, LAST_PACKET, - NULL, 0); - gspca_frame_add(gspca_dev, FIRST_PACKET, - data + 4, SD_PKT_SZ - 4); - } else if (data[0] == 0x04 && (data[1] & 0xfe) == 0xba) { - gspca_frame_add(gspca_dev, INTER_PACKET, - data + 4, SD_PKT_SZ - 4); - } else { - gspca_dev->last_packet_type = DISCARD_PACKET; - continue; - } - data = (u8 *) urb->transfer_buffer - + urb->iso_frame_desc[i].offset; - gspca_frame_add(gspca_dev, INTER_PACKET, - data, SD_PKT_SZ); - } - - /* resubmit the URBs */ - st = usb_submit_urb(urb0, GFP_ATOMIC); - if (st < 0) - pr_err("usb_submit_urb(0) ret %d\n", st); - st = usb_submit_urb(urb, GFP_ATOMIC); - if (st < 0) - pr_err("usb_submit_urb() ret %d\n", st); -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x04a5, 0x3035)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c deleted file mode 100644 index c9052f20435e..000000000000 --- a/drivers/media/video/gspca/conex.c +++ /dev/null @@ -1,966 +0,0 @@ -/* - * Connexant Cx11646 library - * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr - * - * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "conex" - -#include "gspca.h" -#define CONEX_CAM 1 /* special JPEG header */ -#include "jpeg.h" - -MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); -MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver"); -MODULE_LICENSE("GPL"); - -#define QUALITY 50 - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - struct v4l2_ctrl *brightness; - struct v4l2_ctrl *contrast; - struct v4l2_ctrl *sat; - - u8 jpeg_hdr[JPEG_HDR_SZ]; -}; - -static const struct v4l2_pix_format vga_mode[] = { - {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 3}, - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2}, - {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; - -/* the read bytes are found in gspca_dev->usb_buf */ -static void reg_r(struct gspca_dev *gspca_dev, - __u16 index, - __u16 len) -{ - struct usb_device *dev = gspca_dev->dev; - -#ifdef GSPCA_DEBUG - if (len > USB_BUF_SZ) { - pr_err("reg_r: buffer overflow\n"); - return; - } -#endif - usb_control_msg(dev, - usb_rcvctrlpipe(dev, 0), - 0, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, - index, gspca_dev->usb_buf, len, - 500); - PDEBUG(D_USBI, "reg read [%02x] -> %02x ..", - index, gspca_dev->usb_buf[0]); -} - -/* the bytes to write are in gspca_dev->usb_buf */ -static void reg_w_val(struct gspca_dev *gspca_dev, - __u16 index, - __u8 val) -{ - struct usb_device *dev = gspca_dev->dev; - - gspca_dev->usb_buf[0] = val; - usb_control_msg(dev, - usb_sndctrlpipe(dev, 0), - 0, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, - index, gspca_dev->usb_buf, 1, 500); -} - -static void reg_w(struct gspca_dev *gspca_dev, - __u16 index, - const __u8 *buffer, - __u16 len) -{ - struct usb_device *dev = gspca_dev->dev; - -#ifdef GSPCA_DEBUG - if (len > USB_BUF_SZ) { - pr_err("reg_w: buffer overflow\n"); - return; - } - PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer); -#endif - memcpy(gspca_dev->usb_buf, buffer, len); - usb_control_msg(dev, - usb_sndctrlpipe(dev, 0), - 0, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, - index, gspca_dev->usb_buf, len, 500); -} - -static const __u8 cx_sensor_init[][4] = { - {0x88, 0x11, 0x01, 0x01}, - {0x88, 0x12, 0x70, 0x01}, - {0x88, 0x0f, 0x00, 0x01}, - {0x88, 0x05, 0x01, 0x01}, - {} -}; - -static const __u8 cx11646_fw1[][3] = { - {0x00, 0x02, 0x00}, - {0x01, 0x43, 0x00}, - {0x02, 0xA7, 0x00}, - {0x03, 0x8B, 0x01}, - {0x04, 0xE9, 0x02}, - {0x05, 0x08, 0x04}, - {0x06, 0x08, 0x05}, - {0x07, 0x07, 0x06}, - {0x08, 0xE7, 0x06}, - {0x09, 0xC6, 0x07}, - {0x0A, 0x86, 0x08}, - {0x0B, 0x46, 0x09}, - {0x0C, 0x05, 0x0A}, - {0x0D, 0xA5, 0x0A}, - {0x0E, 0x45, 0x0B}, - {0x0F, 0xE5, 0x0B}, - {0x10, 0x85, 0x0C}, - {0x11, 0x25, 0x0D}, - {0x12, 0xC4, 0x0D}, - {0x13, 0x45, 0x0E}, - {0x14, 0xE4, 0x0E}, - {0x15, 0x64, 0x0F}, - {0x16, 0xE4, 0x0F}, - {0x17, 0x64, 0x10}, - {0x18, 0xE4, 0x10}, - {0x19, 0x64, 0x11}, - {0x1A, 0xE4, 0x11}, - {0x1B, 0x64, 0x12}, - {0x1C, 0xE3, 0x12}, - {0x1D, 0x44, 0x13}, - {0x1E, 0xC3, 0x13}, - {0x1F, 0x24, 0x14}, - {0x20, 0xA3, 0x14}, - {0x21, 0x04, 0x15}, - {0x22, 0x83, 0x15}, - {0x23, 0xE3, 0x15}, - {0x24, 0x43, 0x16}, - {0x25, 0xA4, 0x16}, - {0x26, 0x23, 0x17}, - {0x27, 0x83, 0x17}, - {0x28, 0xE3, 0x17}, - {0x29, 0x43, 0x18}, - {0x2A, 0xA3, 0x18}, - {0x2B, 0x03, 0x19}, - {0x2C, 0x63, 0x19}, - {0x2D, 0xC3, 0x19}, - {0x2E, 0x22, 0x1A}, - {0x2F, 0x63, 0x1A}, - {0x30, 0xC3, 0x1A}, - {0x31, 0x23, 0x1B}, - {0x32, 0x83, 0x1B}, - {0x33, 0xE2, 0x1B}, - {0x34, 0x23, 0x1C}, - {0x35, 0x83, 0x1C}, - {0x36, 0xE2, 0x1C}, - {0x37, 0x23, 0x1D}, - {0x38, 0x83, 0x1D}, - {0x39, 0xE2, 0x1D}, - {0x3A, 0x23, 0x1E}, - {0x3B, 0x82, 0x1E}, - {0x3C, 0xC3, 0x1E}, - {0x3D, 0x22, 0x1F}, - {0x3E, 0x63, 0x1F}, - {0x3F, 0xC1, 0x1F}, - {} -}; -static void cx11646_fw(struct gspca_dev*gspca_dev) -{ - int i = 0; - - reg_w_val(gspca_dev, 0x006a, 0x02); - while (cx11646_fw1[i][1]) { - reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3); - i++; - } - reg_w_val(gspca_dev, 0x006a, 0x00); -} - -static const __u8 cxsensor[] = { - 0x88, 0x12, 0x70, 0x01, - 0x88, 0x0d, 0x02, 0x01, - 0x88, 0x0f, 0x00, 0x01, - 0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */ - 0x88, 0x02, 0x10, 0x01, - 0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */ - 0x88, 0x0B, 0x00, 0x01, - 0x88, 0x0A, 0x0A, 0x01, - 0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */ - 0x88, 0x05, 0x01, 0x01, - 0xA1, 0x18, 0x00, 0x01, - 0x00 -}; - -static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff }; -static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff }; -static const __u8 reg10[] = { 0xb1, 0xb1 }; -static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */ -static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f }; - /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */ -static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 }; - /* 320{0x04,0x0c,0x05,0x0f}; //320 */ -static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */ -static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }; - -static void cx_sensor(struct gspca_dev*gspca_dev) -{ - int i = 0; - int length; - const __u8 *ptsensor = cxsensor; - - reg_w(gspca_dev, 0x0020, reg20, 8); - reg_w(gspca_dev, 0x0028, reg28, 8); - reg_w(gspca_dev, 0x0010, reg10, 2); - reg_w_val(gspca_dev, 0x0092, 0x03); - - switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { - case 0: - reg_w(gspca_dev, 0x0071, reg71a, 4); - break; - case 1: - reg_w(gspca_dev, 0x0071, reg71b, 4); - break; - default: -/* case 2: */ - reg_w(gspca_dev, 0x0071, reg71c, 4); - break; - case 3: - reg_w(gspca_dev, 0x0071, reg71d, 4); - break; - } - reg_w(gspca_dev, 0x007b, reg7b, 6); - reg_w_val(gspca_dev, 0x00f8, 0x00); - reg_w(gspca_dev, 0x0010, reg10, 2); - reg_w_val(gspca_dev, 0x0098, 0x41); - for (i = 0; i < 11; i++) { - if (i == 3 || i == 5 || i == 8) - length = 8; - else - length = 4; - reg_w(gspca_dev, 0x00e5, ptsensor, length); - if (length == 4) - reg_r(gspca_dev, 0x00e8, 1); - else - reg_r(gspca_dev, 0x00e8, length); - ptsensor += length; - } - reg_r(gspca_dev, 0x00e7, 8); -} - -static const __u8 cx_inits_176[] = { - 0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */ - 0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03, - 0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30, - 0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, - 0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF, - 0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02, - 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -static const __u8 cx_inits_320[] = { - 0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01, - 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01, - 0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81, - 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff, - 0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02, - 0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -static const __u8 cx_inits_352[] = { - 0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03, - 0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b, - 0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25, - 0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00, - 0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff, - 0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02, - 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -static const __u8 cx_inits_640[] = { - 0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01, - 0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01, - 0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81, - 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff, - 0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02, - 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static void cx11646_initsize(struct gspca_dev *gspca_dev) -{ - const __u8 *cxinit; - static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 }; - static const __u8 reg17[] = - { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 }; - - switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { - case 0: - cxinit = cx_inits_640; - break; - case 1: - cxinit = cx_inits_352; - break; - default: -/* case 2: */ - cxinit = cx_inits_320; - break; - case 3: - cxinit = cx_inits_176; - break; - } - reg_w_val(gspca_dev, 0x009a, 0x01); - reg_w_val(gspca_dev, 0x0010, 0x10); - reg_w(gspca_dev, 0x0012, reg12, 5); - reg_w(gspca_dev, 0x0017, reg17, 8); - reg_w_val(gspca_dev, 0x00c0, 0x00); - reg_w_val(gspca_dev, 0x00c1, 0x04); - reg_w_val(gspca_dev, 0x00c2, 0x04); - - reg_w(gspca_dev, 0x0061, cxinit, 8); - cxinit += 8; - reg_w(gspca_dev, 0x00ca, cxinit, 8); - cxinit += 8; - reg_w(gspca_dev, 0x00d2, cxinit, 8); - cxinit += 8; - reg_w(gspca_dev, 0x00da, cxinit, 6); - cxinit += 8; - reg_w(gspca_dev, 0x0041, cxinit, 8); - cxinit += 8; - reg_w(gspca_dev, 0x0049, cxinit, 8); - cxinit += 8; - reg_w(gspca_dev, 0x0051, cxinit, 2); - - reg_r(gspca_dev, 0x0010, 1); -} - -static const __u8 cx_jpeg_init[][8] = { - {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15}, /* 1 */ - {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11}, - {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22}, - {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26}, - {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a}, - {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73}, - {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D}, - {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0}, - {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01}, - {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12}, - {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35}, - {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31}, - {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43}, - {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A}, - {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73}, - {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95}, - {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83}, - {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05}, - {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02}, - {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A}, - {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01}, - {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05}, - {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00}, - {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05}, - {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01}, - {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21}, - {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22}, - {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23}, - {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24}, - {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17}, - {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29}, - {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A}, - {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A}, - {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A}, - {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A}, - {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A}, - {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A}, - {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99}, - {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8}, - {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7}, - {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6}, - {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5}, - {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3}, - {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1}, - {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9}, - {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04}, - {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01}, - {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04}, - {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07}, - {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14}, - {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33}, - {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16}, - {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19}, - {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36}, - {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46}, - {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56}, - {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66}, - {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76}, - {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85}, - {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94}, - {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3}, - {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2}, - {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA}, - {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9}, - {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8}, - {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7}, - {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6}, - {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F}, - {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22}, - {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11}, - {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00}, - {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08}, - {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00}, - {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA}, - {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02}, - {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00} /* 79 */ -}; - - -static const __u8 cxjpeg_640[][8] = { - {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10}, /* 1 */ - {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d}, - {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a}, - {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d}, - {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38}, - {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57}, - {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F}, - {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79}, - {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01}, - {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E}, - {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28}, - {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25}, - {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33}, - {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44}, - {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57}, - {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71}, - {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63}, - {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00}, - {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00}, - {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22}, - {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55}, - {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF}, - {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80}, - {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02}, - {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00}, - {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00}, - {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */ -}; -static const __u8 cxjpeg_352[][8] = { - {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d}, - {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a}, - {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14}, - {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17}, - {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C}, - {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44}, - {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A}, - {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F}, - {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01}, - {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B}, - {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F}, - {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D}, - {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28}, - {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35}, - {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44}, - {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58}, - {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D}, - {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00}, - {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00}, - {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22}, - {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55}, - {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF}, - {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60}, - {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02}, - {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00}, - {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00}, - {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} -}; -static const __u8 cxjpeg_320[][8] = { - {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05}, - {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04}, - {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08}, - {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09}, - {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11}, - {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A}, - {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D}, - {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24}, - {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01}, - {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04}, - {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C}, - {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B}, - {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F}, - {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14}, - {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A}, - {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22}, - {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E}, - {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00}, - {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00}, - {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22}, - {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55}, - {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF}, - {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40}, - {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02}, - {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00}, - {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00}, - {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */ -}; -static const __u8 cxjpeg_176[][8] = { - {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d}, - {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A}, - {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14}, - {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17}, - {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C}, - {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44}, - {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A}, - {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F}, - {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01}, - {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B}, - {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F}, - {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D}, - {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28}, - {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35}, - {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44}, - {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58}, - {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D}, - {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00}, - {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00}, - {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22}, - {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55}, - {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF}, - {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0}, - {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02}, - {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00}, - {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00}, - {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} -}; -/* 640 take with the zcx30x part */ -static const __u8 cxjpeg_qtable[][8] = { - {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08}, - {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07}, - {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a}, - {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f}, - {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c}, - {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c}, - {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30}, - {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d}, - {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01}, - {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a}, - {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32}, - {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32}, - {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32}, - {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32}, - {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32}, - {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32}, - {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32}, - {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */ -}; - - -static void cx11646_jpegInit(struct gspca_dev*gspca_dev) -{ - int i; - int length; - - reg_w_val(gspca_dev, 0x00c0, 0x01); - reg_w_val(gspca_dev, 0x00c3, 0x00); - reg_w_val(gspca_dev, 0x00c0, 0x00); - reg_r(gspca_dev, 0x0001, 1); - length = 8; - for (i = 0; i < 79; i++) { - if (i == 78) - length = 6; - reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length); - } - reg_r(gspca_dev, 0x0002, 1); - reg_w_val(gspca_dev, 0x0055, 0x14); -} - -static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 }; -static const __u8 regE5_8[] = - { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 }; -static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 }; -static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 }; -static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 }; -static const __u8 reg51[] = { 0x77, 0x03 }; -#define reg70 0x03 - -static void cx11646_jpeg(struct gspca_dev*gspca_dev) -{ - int i; - int length; - __u8 Reg55; - int retry; - - reg_w_val(gspca_dev, 0x00c0, 0x01); - reg_w_val(gspca_dev, 0x00c3, 0x00); - reg_w_val(gspca_dev, 0x00c0, 0x00); - reg_r(gspca_dev, 0x0001, 1); - length = 8; - switch (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv) { - case 0: - for (i = 0; i < 27; i++) { - if (i == 26) - length = 2; - reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length); - } - Reg55 = 0x28; - break; - case 1: - for (i = 0; i < 27; i++) { - if (i == 26) - length = 2; - reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length); - } - Reg55 = 0x16; - break; - default: -/* case 2: */ - for (i = 0; i < 27; i++) { - if (i == 26) - length = 2; - reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length); - } - Reg55 = 0x14; - break; - case 3: - for (i = 0; i < 27; i++) { - if (i == 26) - length = 2; - reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length); - } - Reg55 = 0x0B; - break; - } - - reg_r(gspca_dev, 0x0002, 1); - reg_w_val(gspca_dev, 0x0055, Reg55); - reg_r(gspca_dev, 0x0002, 1); - reg_w(gspca_dev, 0x0010, reg10, 2); - reg_w_val(gspca_dev, 0x0054, 0x02); - reg_w_val(gspca_dev, 0x0054, 0x01); - reg_w_val(gspca_dev, 0x0000, 0x94); - reg_w_val(gspca_dev, 0x0053, 0xc0); - reg_w_val(gspca_dev, 0x00fc, 0xe1); - reg_w_val(gspca_dev, 0x0000, 0x00); - /* wait for completion */ - retry = 50; - do { - reg_r(gspca_dev, 0x0002, 1); - /* 0x07 until 0x00 */ - if (gspca_dev->usb_buf[0] == 0x00) - break; - reg_w_val(gspca_dev, 0x0053, 0x00); - } while (--retry); - if (retry == 0) - PDEBUG(D_ERR, "Damned Errors sending jpeg Table"); - /* send the qtable now */ - reg_r(gspca_dev, 0x0001, 1); /* -> 0x18 */ - length = 8; - for (i = 0; i < 18; i++) { - if (i == 17) - length = 2; - reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length); - - } - reg_r(gspca_dev, 0x0002, 1); /* 0x00 */ - reg_r(gspca_dev, 0x0053, 1); /* 0x00 */ - reg_w_val(gspca_dev, 0x0054, 0x02); - reg_w_val(gspca_dev, 0x0054, 0x01); - reg_w_val(gspca_dev, 0x0000, 0x94); - reg_w_val(gspca_dev, 0x0053, 0xc0); - - reg_r(gspca_dev, 0x0038, 1); /* 0x40 */ - reg_r(gspca_dev, 0x0038, 1); /* 0x40 */ - reg_r(gspca_dev, 0x001f, 1); /* 0x38 */ - reg_w(gspca_dev, 0x0012, reg12, 5); - reg_w(gspca_dev, 0x00e5, regE5_8, 8); - reg_r(gspca_dev, 0x00e8, 8); - reg_w(gspca_dev, 0x00e5, regE5a, 4); - reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */ - reg_w_val(gspca_dev, 0x009a, 0x01); - reg_w(gspca_dev, 0x00e5, regE5b, 4); - reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */ - reg_w(gspca_dev, 0x00e5, regE5c, 4); - reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */ - - reg_w(gspca_dev, 0x0051, reg51, 2); - reg_w(gspca_dev, 0x0010, reg10, 2); - reg_w_val(gspca_dev, 0x0070, reg70); -} - -static void cx11646_init1(struct gspca_dev *gspca_dev) -{ - int i = 0; - - reg_w_val(gspca_dev, 0x0010, 0x00); - reg_w_val(gspca_dev, 0x0053, 0x00); - reg_w_val(gspca_dev, 0x0052, 0x00); - reg_w_val(gspca_dev, 0x009b, 0x2f); - reg_w_val(gspca_dev, 0x009c, 0x10); - reg_r(gspca_dev, 0x0098, 1); - reg_w_val(gspca_dev, 0x0098, 0x40); - reg_r(gspca_dev, 0x0099, 1); - reg_w_val(gspca_dev, 0x0099, 0x07); - reg_w_val(gspca_dev, 0x0039, 0x40); - reg_w_val(gspca_dev, 0x003c, 0xff); - reg_w_val(gspca_dev, 0x003f, 0x1f); - reg_w_val(gspca_dev, 0x003d, 0x40); -/* reg_w_val(gspca_dev, 0x003d, 0x60); */ - reg_r(gspca_dev, 0x0099, 1); /* ->0x07 */ - - while (cx_sensor_init[i][0]) { - reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]); - reg_r(gspca_dev, 0x00e8, 1); /* -> 0x00 */ - if (i == 1) { - reg_w_val(gspca_dev, 0x00ed, 0x01); - reg_r(gspca_dev, 0x00ed, 1); /* -> 0x01 */ - } - i++; - } - reg_w_val(gspca_dev, 0x00c3, 0x00); -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct cam *cam; - - cam = &gspca_dev->cam; - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - cx11646_init1(gspca_dev); - cx11646_initsize(gspca_dev); - cx11646_fw(gspca_dev); - cx_sensor(gspca_dev); - cx11646_jpegInit(gspca_dev); - return 0; -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* create the JPEG header */ - jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, - 0x22); /* JPEG 411 */ - jpeg_set_qual(sd->jpeg_hdr, QUALITY); - - cx11646_initsize(gspca_dev); - cx11646_fw(gspca_dev); - cx_sensor(gspca_dev); - cx11646_jpeg(gspca_dev); - return 0; -} - -/* called on streamoff with alt 0 and on disconnect */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - int retry = 50; - - if (!gspca_dev->present) - return; - reg_w_val(gspca_dev, 0x0000, 0x00); - reg_r(gspca_dev, 0x0002, 1); - reg_w_val(gspca_dev, 0x0053, 0x00); - - while (retry--) { -/* reg_r(gspca_dev, 0x0002, 1);*/ - reg_r(gspca_dev, 0x0053, 1); - if (gspca_dev->usb_buf[0] == 0) - break; - } - reg_w_val(gspca_dev, 0x0000, 0x00); - reg_r(gspca_dev, 0x0002, 1); - - reg_w_val(gspca_dev, 0x0010, 0x00); - reg_r(gspca_dev, 0x0033, 1); - reg_w_val(gspca_dev, 0x00fc, 0xe0); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (data[0] == 0xff && data[1] == 0xd8) { - - /* start of frame */ - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - - /* put the JPEG header in the new frame */ - gspca_frame_add(gspca_dev, FIRST_PACKET, - sd->jpeg_hdr, JPEG_HDR_SZ); - data += 2; - len -= 2; - } - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 val, s32 sat) -{ - __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 }; - __u8 reg51c[2]; - - regE5cbx[2] = val; - reg_w(gspca_dev, 0x00e5, regE5cbx, 8); - reg_r(gspca_dev, 0x00e8, 8); - reg_w(gspca_dev, 0x00e5, regE5c, 4); - reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */ - - reg51c[0] = 0x77; - reg51c[1] = sat; - reg_w(gspca_dev, 0x0051, reg51c, 2); - reg_w(gspca_dev, 0x0010, reg10, 2); - reg_w_val(gspca_dev, 0x0070, reg70); -} - -static void setcontrast(struct gspca_dev *gspca_dev, s32 val, s32 sat) -{ - __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */ -/* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */ - __u8 reg51c[2]; - - regE5acx[2] = val; - reg_w(gspca_dev, 0x00e5, regE5acx, 4); - reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */ - reg51c[0] = 0x77; - reg51c[1] = sat; - reg_w(gspca_dev, 0x0051, reg51c, 2); - reg_w(gspca_dev, 0x0010, reg10, 2); - reg_w_val(gspca_dev, 0x0070, reg70); -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val); - break; - case V4L2_CID_CONTRAST: - setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val); - break; - case V4L2_CID_SATURATION: - setbrightness(gspca_dev, sd->brightness->cur.val, ctrl->val); - setcontrast(gspca_dev, sd->contrast->cur.val, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 3); - sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 0xd4); - sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0x0a, 0x1f, 1, 0x0c); - sd->sat = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SATURATION, 0, 7, 1, 3); - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x0572, 0x0041)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c deleted file mode 100644 index 2499a881d9a3..000000000000 --- a/drivers/media/video/gspca/cpia1.c +++ /dev/null @@ -1,1905 +0,0 @@ -/* - * cpia CPiA (1) gspca driver - * - * Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.com> - * - * This module is adapted from the in kernel v4l1 cpia driver which is : - * - * (C) Copyright 1999-2000 Peter Pregler - * (C) Copyright 1999-2000 Scott J. Bertin - * (C) Copyright 1999-2000 Johannes Erdfelt <johannes@erdfelt.com> - * (C) Copyright 2000 STMicroelectronics - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "cpia1" - -#include <linux/input.h> -#include "gspca.h" - -MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); -MODULE_DESCRIPTION("Vision CPiA"); -MODULE_LICENSE("GPL"); - -/* constant value's */ -#define MAGIC_0 0x19 -#define MAGIC_1 0x68 -#define DATA_IN 0xc0 -#define DATA_OUT 0x40 -#define VIDEOSIZE_QCIF 0 /* 176x144 */ -#define VIDEOSIZE_CIF 1 /* 352x288 */ -#define SUBSAMPLE_420 0 -#define SUBSAMPLE_422 1 -#define YUVORDER_YUYV 0 -#define YUVORDER_UYVY 1 -#define NOT_COMPRESSED 0 -#define COMPRESSED 1 -#define NO_DECIMATION 0 -#define DECIMATION_ENAB 1 -#define EOI 0xff /* End Of Image */ -#define EOL 0xfd /* End Of Line */ -#define FRAME_HEADER_SIZE 64 - -/* Image grab modes */ -#define CPIA_GRAB_SINGLE 0 -#define CPIA_GRAB_CONTINEOUS 1 - -/* Compression parameters */ -#define CPIA_COMPRESSION_NONE 0 -#define CPIA_COMPRESSION_AUTO 1 -#define CPIA_COMPRESSION_MANUAL 2 -#define CPIA_COMPRESSION_TARGET_QUALITY 0 -#define CPIA_COMPRESSION_TARGET_FRAMERATE 1 - -/* Return offsets for GetCameraState */ -#define SYSTEMSTATE 0 -#define GRABSTATE 1 -#define STREAMSTATE 2 -#define FATALERROR 3 -#define CMDERROR 4 -#define DEBUGFLAGS 5 -#define VPSTATUS 6 -#define ERRORCODE 7 - -/* SystemState */ -#define UNINITIALISED_STATE 0 -#define PASS_THROUGH_STATE 1 -#define LO_POWER_STATE 2 -#define HI_POWER_STATE 3 -#define WARM_BOOT_STATE 4 - -/* GrabState */ -#define GRAB_IDLE 0 -#define GRAB_ACTIVE 1 -#define GRAB_DONE 2 - -/* StreamState */ -#define STREAM_NOT_READY 0 -#define STREAM_READY 1 -#define STREAM_OPEN 2 -#define STREAM_PAUSED 3 -#define STREAM_FINISHED 4 - -/* Fatal Error, CmdError, and DebugFlags */ -#define CPIA_FLAG 1 -#define SYSTEM_FLAG 2 -#define INT_CTRL_FLAG 4 -#define PROCESS_FLAG 8 -#define COM_FLAG 16 -#define VP_CTRL_FLAG 32 -#define CAPTURE_FLAG 64 -#define DEBUG_FLAG 128 - -/* VPStatus */ -#define VP_STATE_OK 0x00 - -#define VP_STATE_FAILED_VIDEOINIT 0x01 -#define VP_STATE_FAILED_AECACBINIT 0x02 -#define VP_STATE_AEC_MAX 0x04 -#define VP_STATE_ACB_BMAX 0x08 - -#define VP_STATE_ACB_RMIN 0x10 -#define VP_STATE_ACB_GMIN 0x20 -#define VP_STATE_ACB_RMAX 0x40 -#define VP_STATE_ACB_GMAX 0x80 - -/* default (minimum) compensation values */ -#define COMP_RED 220 -#define COMP_GREEN1 214 -#define COMP_GREEN2 COMP_GREEN1 -#define COMP_BLUE 230 - -/* exposure status */ -#define EXPOSURE_VERY_LIGHT 0 -#define EXPOSURE_LIGHT 1 -#define EXPOSURE_NORMAL 2 -#define EXPOSURE_DARK 3 -#define EXPOSURE_VERY_DARK 4 - -#define CPIA_MODULE_CPIA (0 << 5) -#define CPIA_MODULE_SYSTEM (1 << 5) -#define CPIA_MODULE_VP_CTRL (5 << 5) -#define CPIA_MODULE_CAPTURE (6 << 5) -#define CPIA_MODULE_DEBUG (7 << 5) - -#define INPUT (DATA_IN << 8) -#define OUTPUT (DATA_OUT << 8) - -#define CPIA_COMMAND_GetCPIAVersion (INPUT | CPIA_MODULE_CPIA | 1) -#define CPIA_COMMAND_GetPnPID (INPUT | CPIA_MODULE_CPIA | 2) -#define CPIA_COMMAND_GetCameraStatus (INPUT | CPIA_MODULE_CPIA | 3) -#define CPIA_COMMAND_GotoHiPower (OUTPUT | CPIA_MODULE_CPIA | 4) -#define CPIA_COMMAND_GotoLoPower (OUTPUT | CPIA_MODULE_CPIA | 5) -#define CPIA_COMMAND_GotoSuspend (OUTPUT | CPIA_MODULE_CPIA | 7) -#define CPIA_COMMAND_GotoPassThrough (OUTPUT | CPIA_MODULE_CPIA | 8) -#define CPIA_COMMAND_ModifyCameraStatus (OUTPUT | CPIA_MODULE_CPIA | 10) - -#define CPIA_COMMAND_ReadVCRegs (INPUT | CPIA_MODULE_SYSTEM | 1) -#define CPIA_COMMAND_WriteVCReg (OUTPUT | CPIA_MODULE_SYSTEM | 2) -#define CPIA_COMMAND_ReadMCPorts (INPUT | CPIA_MODULE_SYSTEM | 3) -#define CPIA_COMMAND_WriteMCPort (OUTPUT | CPIA_MODULE_SYSTEM | 4) -#define CPIA_COMMAND_SetBaudRate (OUTPUT | CPIA_MODULE_SYSTEM | 5) -#define CPIA_COMMAND_SetECPTiming (OUTPUT | CPIA_MODULE_SYSTEM | 6) -#define CPIA_COMMAND_ReadIDATA (INPUT | CPIA_MODULE_SYSTEM | 7) -#define CPIA_COMMAND_WriteIDATA (OUTPUT | CPIA_MODULE_SYSTEM | 8) -#define CPIA_COMMAND_GenericCall (OUTPUT | CPIA_MODULE_SYSTEM | 9) -#define CPIA_COMMAND_I2CStart (OUTPUT | CPIA_MODULE_SYSTEM | 10) -#define CPIA_COMMAND_I2CStop (OUTPUT | CPIA_MODULE_SYSTEM | 11) -#define CPIA_COMMAND_I2CWrite (OUTPUT | CPIA_MODULE_SYSTEM | 12) -#define CPIA_COMMAND_I2CRead (INPUT | CPIA_MODULE_SYSTEM | 13) - -#define CPIA_COMMAND_GetVPVersion (INPUT | CPIA_MODULE_VP_CTRL | 1) -#define CPIA_COMMAND_ResetFrameCounter (INPUT | CPIA_MODULE_VP_CTRL | 2) -#define CPIA_COMMAND_SetColourParams (OUTPUT | CPIA_MODULE_VP_CTRL | 3) -#define CPIA_COMMAND_SetExposure (OUTPUT | CPIA_MODULE_VP_CTRL | 4) -#define CPIA_COMMAND_SetColourBalance (OUTPUT | CPIA_MODULE_VP_CTRL | 6) -#define CPIA_COMMAND_SetSensorFPS (OUTPUT | CPIA_MODULE_VP_CTRL | 7) -#define CPIA_COMMAND_SetVPDefaults (OUTPUT | CPIA_MODULE_VP_CTRL | 8) -#define CPIA_COMMAND_SetApcor (OUTPUT | CPIA_MODULE_VP_CTRL | 9) -#define CPIA_COMMAND_SetFlickerCtrl (OUTPUT | CPIA_MODULE_VP_CTRL | 10) -#define CPIA_COMMAND_SetVLOffset (OUTPUT | CPIA_MODULE_VP_CTRL | 11) -#define CPIA_COMMAND_GetColourParams (INPUT | CPIA_MODULE_VP_CTRL | 16) -#define CPIA_COMMAND_GetColourBalance (INPUT | CPIA_MODULE_VP_CTRL | 17) -#define CPIA_COMMAND_GetExposure (INPUT | CPIA_MODULE_VP_CTRL | 18) -#define CPIA_COMMAND_SetSensorMatrix (OUTPUT | CPIA_MODULE_VP_CTRL | 19) -#define CPIA_COMMAND_ColourBars (OUTPUT | CPIA_MODULE_VP_CTRL | 25) -#define CPIA_COMMAND_ReadVPRegs (INPUT | CPIA_MODULE_VP_CTRL | 30) -#define CPIA_COMMAND_WriteVPReg (OUTPUT | CPIA_MODULE_VP_CTRL | 31) - -#define CPIA_COMMAND_GrabFrame (OUTPUT | CPIA_MODULE_CAPTURE | 1) -#define CPIA_COMMAND_UploadFrame (OUTPUT | CPIA_MODULE_CAPTURE | 2) -#define CPIA_COMMAND_SetGrabMode (OUTPUT | CPIA_MODULE_CAPTURE | 3) -#define CPIA_COMMAND_InitStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 4) -#define CPIA_COMMAND_FiniStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 5) -#define CPIA_COMMAND_StartStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 6) -#define CPIA_COMMAND_EndStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 7) -#define CPIA_COMMAND_SetFormat (OUTPUT | CPIA_MODULE_CAPTURE | 8) -#define CPIA_COMMAND_SetROI (OUTPUT | CPIA_MODULE_CAPTURE | 9) -#define CPIA_COMMAND_SetCompression (OUTPUT | CPIA_MODULE_CAPTURE | 10) -#define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11) -#define CPIA_COMMAND_SetYUVThresh (OUTPUT | CPIA_MODULE_CAPTURE | 12) -#define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13) -#define CPIA_COMMAND_DiscardFrame (OUTPUT | CPIA_MODULE_CAPTURE | 14) -#define CPIA_COMMAND_GrabReset (OUTPUT | CPIA_MODULE_CAPTURE | 15) - -#define CPIA_COMMAND_OutputRS232 (OUTPUT | CPIA_MODULE_DEBUG | 1) -#define CPIA_COMMAND_AbortProcess (OUTPUT | CPIA_MODULE_DEBUG | 4) -#define CPIA_COMMAND_SetDramPage (OUTPUT | CPIA_MODULE_DEBUG | 5) -#define CPIA_COMMAND_StartDramUpload (OUTPUT | CPIA_MODULE_DEBUG | 6) -#define CPIA_COMMAND_StartDummyDtream (OUTPUT | CPIA_MODULE_DEBUG | 8) -#define CPIA_COMMAND_AbortStream (OUTPUT | CPIA_MODULE_DEBUG | 9) -#define CPIA_COMMAND_DownloadDRAM (OUTPUT | CPIA_MODULE_DEBUG | 10) -#define CPIA_COMMAND_Null (OUTPUT | CPIA_MODULE_DEBUG | 11) - -#define ROUND_UP_EXP_FOR_FLICKER 15 - -/* Constants for automatic frame rate adjustment */ -#define MAX_EXP 302 -#define MAX_EXP_102 255 -#define LOW_EXP 140 -#define VERY_LOW_EXP 70 -#define TC 94 -#define EXP_ACC_DARK 50 -#define EXP_ACC_LIGHT 90 -#define HIGH_COMP_102 160 -#define MAX_COMP 239 -#define DARK_TIME 3 -#define LIGHT_TIME 3 - -#define FIRMWARE_VERSION(x, y) (sd->params.version.firmwareVersion == (x) && \ - sd->params.version.firmwareRevision == (y)) - -#define CPIA1_CID_COMP_TARGET (V4L2_CTRL_CLASS_USER + 0x1000) -#define BRIGHTNESS_DEF 50 -#define CONTRAST_DEF 48 -#define SATURATION_DEF 50 -#define FREQ_DEF V4L2_CID_POWER_LINE_FREQUENCY_50HZ -#define ILLUMINATORS_1_DEF 0 -#define ILLUMINATORS_2_DEF 0 -#define COMP_TARGET_DEF CPIA_COMPRESSION_TARGET_QUALITY - -/* Developer's Guide Table 5 p 3-34 - * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/ -static u8 flicker_jumps[2][2][4] = -{ { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } }, - { { 64, 32, 16, 8 }, { 76, 38, 19, 9} } -}; - -struct cam_params { - struct { - u8 firmwareVersion; - u8 firmwareRevision; - u8 vcVersion; - u8 vcRevision; - } version; - struct { - u16 vendor; - u16 product; - u16 deviceRevision; - } pnpID; - struct { - u8 vpVersion; - u8 vpRevision; - u16 cameraHeadID; - } vpVersion; - struct { - u8 systemState; - u8 grabState; - u8 streamState; - u8 fatalError; - u8 cmdError; - u8 debugFlags; - u8 vpStatus; - u8 errorCode; - } status; - struct { - u8 brightness; - u8 contrast; - u8 saturation; - } colourParams; - struct { - u8 gainMode; - u8 expMode; - u8 compMode; - u8 centreWeight; - u8 gain; - u8 fineExp; - u8 coarseExpLo; - u8 coarseExpHi; - u8 redComp; - u8 green1Comp; - u8 green2Comp; - u8 blueComp; - } exposure; - struct { - u8 balanceMode; - u8 redGain; - u8 greenGain; - u8 blueGain; - } colourBalance; - struct { - u8 divisor; - u8 baserate; - } sensorFps; - struct { - u8 gain1; - u8 gain2; - u8 gain4; - u8 gain8; - } apcor; - struct { - u8 disabled; - u8 flickerMode; - u8 coarseJump; - u8 allowableOverExposure; - } flickerControl; - struct { - u8 gain1; - u8 gain2; - u8 gain4; - u8 gain8; - } vlOffset; - struct { - u8 mode; - u8 decimation; - } compression; - struct { - u8 frTargeting; - u8 targetFR; - u8 targetQ; - } compressionTarget; - struct { - u8 yThreshold; - u8 uvThreshold; - } yuvThreshold; - struct { - u8 hysteresis; - u8 threshMax; - u8 smallStep; - u8 largeStep; - u8 decimationHysteresis; - u8 frDiffStepThresh; - u8 qDiffStepThresh; - u8 decimationThreshMod; - } compressionParams; - struct { - u8 videoSize; /* CIF/QCIF */ - u8 subSample; - u8 yuvOrder; - } format; - struct { /* Intel QX3 specific data */ - u8 qx3_detected; /* a QX3 is present */ - u8 toplight; /* top light lit , R/W */ - u8 bottomlight; /* bottom light lit, R/W */ - u8 button; /* snapshot button pressed (R/O) */ - u8 cradled; /* microscope is in cradle (R/O) */ - } qx3; - struct { - u8 colStart; /* skip first 8*colStart pixels */ - u8 colEnd; /* finish at 8*colEnd pixels */ - u8 rowStart; /* skip first 4*rowStart lines */ - u8 rowEnd; /* finish at 4*rowEnd lines */ - } roi; - u8 ecpTiming; - u8 streamStartLine; -}; - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - struct cam_params params; /* camera settings */ - - atomic_t cam_exposure; - atomic_t fps; - int exposure_count; - u8 exposure_status; - struct v4l2_ctrl *freq; - u8 mainsFreq; /* 0 = 50hz, 1 = 60hz */ - u8 first_frame; -}; - -static const struct v4l2_pix_format mode[] = { - {160, 120, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE, - /* The sizeimage is trial and error, as with low framerates - the camera will pad out usb frames, making the image - data larger then strictly necessary */ - .bytesperline = 160, - .sizeimage = 65536, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 3}, - {176, 144, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE, - .bytesperline = 172, - .sizeimage = 65536, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, - {320, 240, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 262144, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {352, 288, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 262144, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; - -/********************************************************************** - * - * General functions - * - **********************************************************************/ - -static int cpia_usb_transferCmd(struct gspca_dev *gspca_dev, u8 *command) -{ - u8 requesttype; - unsigned int pipe; - int ret, databytes = command[6] | (command[7] << 8); - /* Sometimes we see spurious EPIPE errors */ - int retries = 3; - - if (command[0] == DATA_IN) { - pipe = usb_rcvctrlpipe(gspca_dev->dev, 0); - requesttype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; - } else if (command[0] == DATA_OUT) { - pipe = usb_sndctrlpipe(gspca_dev->dev, 0); - requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE; - } else { - PDEBUG(D_ERR, "Unexpected first byte of command: %x", - command[0]); - return -EINVAL; - } - -retry: - ret = usb_control_msg(gspca_dev->dev, pipe, - command[1], - requesttype, - command[2] | (command[3] << 8), - command[4] | (command[5] << 8), - gspca_dev->usb_buf, databytes, 1000); - - if (ret < 0) - pr_err("usb_control_msg %02x, error %d\n", command[1], ret); - - if (ret == -EPIPE && retries > 0) { - retries--; - goto retry; - } - - return (ret < 0) ? ret : 0; -} - -/* send an arbitrary command to the camera */ -static int do_command(struct gspca_dev *gspca_dev, u16 command, - u8 a, u8 b, u8 c, u8 d) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret, datasize; - u8 cmd[8]; - - switch (command) { - case CPIA_COMMAND_GetCPIAVersion: - case CPIA_COMMAND_GetPnPID: - case CPIA_COMMAND_GetCameraStatus: - case CPIA_COMMAND_GetVPVersion: - case CPIA_COMMAND_GetColourParams: - case CPIA_COMMAND_GetColourBalance: - case CPIA_COMMAND_GetExposure: - datasize = 8; - break; - case CPIA_COMMAND_ReadMCPorts: - case CPIA_COMMAND_ReadVCRegs: - datasize = 4; - break; - default: - datasize = 0; - break; - } - - cmd[0] = command >> 8; - cmd[1] = command & 0xff; - cmd[2] = a; - cmd[3] = b; - cmd[4] = c; - cmd[5] = d; - cmd[6] = datasize; - cmd[7] = 0; - - ret = cpia_usb_transferCmd(gspca_dev, cmd); - if (ret) - return ret; - - switch (command) { - case CPIA_COMMAND_GetCPIAVersion: - sd->params.version.firmwareVersion = gspca_dev->usb_buf[0]; - sd->params.version.firmwareRevision = gspca_dev->usb_buf[1]; - sd->params.version.vcVersion = gspca_dev->usb_buf[2]; - sd->params.version.vcRevision = gspca_dev->usb_buf[3]; - break; - case CPIA_COMMAND_GetPnPID: - sd->params.pnpID.vendor = - gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8); - sd->params.pnpID.product = - gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8); - sd->params.pnpID.deviceRevision = - gspca_dev->usb_buf[4] | (gspca_dev->usb_buf[5] << 8); - break; - case CPIA_COMMAND_GetCameraStatus: - sd->params.status.systemState = gspca_dev->usb_buf[0]; - sd->params.status.grabState = gspca_dev->usb_buf[1]; - sd->params.status.streamState = gspca_dev->usb_buf[2]; - sd->params.status.fatalError = gspca_dev->usb_buf[3]; - sd->params.status.cmdError = gspca_dev->usb_buf[4]; - sd->params.status.debugFlags = gspca_dev->usb_buf[5]; - sd->params.status.vpStatus = gspca_dev->usb_buf[6]; - sd->params.status.errorCode = gspca_dev->usb_buf[7]; - break; - case CPIA_COMMAND_GetVPVersion: - sd->params.vpVersion.vpVersion = gspca_dev->usb_buf[0]; - sd->params.vpVersion.vpRevision = gspca_dev->usb_buf[1]; - sd->params.vpVersion.cameraHeadID = - gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8); - break; - case CPIA_COMMAND_GetColourParams: - sd->params.colourParams.brightness = gspca_dev->usb_buf[0]; - sd->params.colourParams.contrast = gspca_dev->usb_buf[1]; - sd->params.colourParams.saturation = gspca_dev->usb_buf[2]; - break; - case CPIA_COMMAND_GetColourBalance: - sd->params.colourBalance.redGain = gspca_dev->usb_buf[0]; - sd->params.colourBalance.greenGain = gspca_dev->usb_buf[1]; - sd->params.colourBalance.blueGain = gspca_dev->usb_buf[2]; - break; - case CPIA_COMMAND_GetExposure: - sd->params.exposure.gain = gspca_dev->usb_buf[0]; - sd->params.exposure.fineExp = gspca_dev->usb_buf[1]; - sd->params.exposure.coarseExpLo = gspca_dev->usb_buf[2]; - sd->params.exposure.coarseExpHi = gspca_dev->usb_buf[3]; - sd->params.exposure.redComp = gspca_dev->usb_buf[4]; - sd->params.exposure.green1Comp = gspca_dev->usb_buf[5]; - sd->params.exposure.green2Comp = gspca_dev->usb_buf[6]; - sd->params.exposure.blueComp = gspca_dev->usb_buf[7]; - break; - - case CPIA_COMMAND_ReadMCPorts: - /* test button press */ - a = ((gspca_dev->usb_buf[1] & 0x02) == 0); - if (a != sd->params.qx3.button) { -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - input_report_key(gspca_dev->input_dev, KEY_CAMERA, a); - input_sync(gspca_dev->input_dev); -#endif - sd->params.qx3.button = a; - } - if (sd->params.qx3.button) { - /* button pressed - unlock the latch */ - do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, - 3, 0xdf, 0xdf, 0); - do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, - 3, 0xff, 0xff, 0); - } - - /* test whether microscope is cradled */ - sd->params.qx3.cradled = ((gspca_dev->usb_buf[2] & 0x40) == 0); - break; - } - - return 0; -} - -/* send a command to the camera with an additional data transaction */ -static int do_command_extended(struct gspca_dev *gspca_dev, u16 command, - u8 a, u8 b, u8 c, u8 d, - u8 e, u8 f, u8 g, u8 h, - u8 i, u8 j, u8 k, u8 l) -{ - u8 cmd[8]; - - cmd[0] = command >> 8; - cmd[1] = command & 0xff; - cmd[2] = a; - cmd[3] = b; - cmd[4] = c; - cmd[5] = d; - cmd[6] = 8; - cmd[7] = 0; - gspca_dev->usb_buf[0] = e; - gspca_dev->usb_buf[1] = f; - gspca_dev->usb_buf[2] = g; - gspca_dev->usb_buf[3] = h; - gspca_dev->usb_buf[4] = i; - gspca_dev->usb_buf[5] = j; - gspca_dev->usb_buf[6] = k; - gspca_dev->usb_buf[7] = l; - - return cpia_usb_transferCmd(gspca_dev, cmd); -} - -/* find_over_exposure - * Finds a suitable value of OverExposure for use with SetFlickerCtrl - * Some calculation is required because this value changes with the brightness - * set with SetColourParameters - * - * Parameters: Brightness - last brightness value set with SetColourParameters - * - * Returns: OverExposure value to use with SetFlickerCtrl - */ -#define FLICKER_MAX_EXPOSURE 250 -#define FLICKER_ALLOWABLE_OVER_EXPOSURE 146 -#define FLICKER_BRIGHTNESS_CONSTANT 59 -static int find_over_exposure(int brightness) -{ - int MaxAllowableOverExposure, OverExposure; - - MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness - - FLICKER_BRIGHTNESS_CONSTANT; - - if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE) - OverExposure = MaxAllowableOverExposure; - else - OverExposure = FLICKER_ALLOWABLE_OVER_EXPOSURE; - - return OverExposure; -} -#undef FLICKER_MAX_EXPOSURE -#undef FLICKER_ALLOWABLE_OVER_EXPOSURE -#undef FLICKER_BRIGHTNESS_CONSTANT - -/* initialise cam_data structure */ -static void reset_camera_params(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam_params *params = &sd->params; - - /* The following parameter values are the defaults from - * "Software Developer's Guide for CPiA Cameras". Any changes - * to the defaults are noted in comments. */ - params->colourParams.brightness = BRIGHTNESS_DEF; - params->colourParams.contrast = CONTRAST_DEF; - params->colourParams.saturation = SATURATION_DEF; - params->exposure.gainMode = 4; - params->exposure.expMode = 2; /* AEC */ - params->exposure.compMode = 1; - params->exposure.centreWeight = 1; - params->exposure.gain = 0; - params->exposure.fineExp = 0; - params->exposure.coarseExpLo = 185; - params->exposure.coarseExpHi = 0; - params->exposure.redComp = COMP_RED; - params->exposure.green1Comp = COMP_GREEN1; - params->exposure.green2Comp = COMP_GREEN2; - params->exposure.blueComp = COMP_BLUE; - params->colourBalance.balanceMode = 2; /* ACB */ - params->colourBalance.redGain = 32; - params->colourBalance.greenGain = 6; - params->colourBalance.blueGain = 92; - params->apcor.gain1 = 0x18; - params->apcor.gain2 = 0x16; - params->apcor.gain4 = 0x24; - params->apcor.gain8 = 0x34; - params->vlOffset.gain1 = 20; - params->vlOffset.gain2 = 24; - params->vlOffset.gain4 = 26; - params->vlOffset.gain8 = 26; - params->compressionParams.hysteresis = 3; - params->compressionParams.threshMax = 11; - params->compressionParams.smallStep = 1; - params->compressionParams.largeStep = 3; - params->compressionParams.decimationHysteresis = 2; - params->compressionParams.frDiffStepThresh = 5; - params->compressionParams.qDiffStepThresh = 3; - params->compressionParams.decimationThreshMod = 2; - /* End of default values from Software Developer's Guide */ - - /* Set Sensor FPS to 15fps. This seems better than 30fps - * for indoor lighting. */ - params->sensorFps.divisor = 1; - params->sensorFps.baserate = 1; - - params->flickerControl.flickerMode = 0; - params->flickerControl.disabled = 1; - params->flickerControl.coarseJump = - flicker_jumps[sd->mainsFreq] - [params->sensorFps.baserate] - [params->sensorFps.divisor]; - params->flickerControl.allowableOverExposure = - find_over_exposure(params->colourParams.brightness); - - params->yuvThreshold.yThreshold = 6; /* From windows driver */ - params->yuvThreshold.uvThreshold = 6; /* From windows driver */ - - params->format.subSample = SUBSAMPLE_420; - params->format.yuvOrder = YUVORDER_YUYV; - - params->compression.mode = CPIA_COMPRESSION_AUTO; - params->compression.decimation = NO_DECIMATION; - - params->compressionTarget.frTargeting = COMP_TARGET_DEF; - params->compressionTarget.targetFR = 15; /* From windows driver */ - params->compressionTarget.targetQ = 5; /* From windows driver */ - - params->qx3.qx3_detected = 0; - params->qx3.toplight = 0; - params->qx3.bottomlight = 0; - params->qx3.button = 0; - params->qx3.cradled = 0; -} - -static void printstatus(struct cam_params *params) -{ - PDEBUG(D_PROBE, "status: %02x %02x %02x %02x %02x %02x %02x %02x", - params->status.systemState, params->status.grabState, - params->status.streamState, params->status.fatalError, - params->status.cmdError, params->status.debugFlags, - params->status.vpStatus, params->status.errorCode); -} - -static int goto_low_power(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret; - - ret = do_command(gspca_dev, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0); - if (ret) - return ret; - - ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); - if (ret) - return ret; - - if (sd->params.status.systemState != LO_POWER_STATE) { - if (sd->params.status.systemState != WARM_BOOT_STATE) { - PDEBUG(D_ERR, - "unexpected state after lo power cmd: %02x", - sd->params.status.systemState); - printstatus(&sd->params); - } - return -EIO; - } - - PDEBUG(D_CONF, "camera now in LOW power state"); - return 0; -} - -static int goto_high_power(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret; - - ret = do_command(gspca_dev, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0); - if (ret) - return ret; - - msleep_interruptible(40); /* windows driver does it too */ - - if (signal_pending(current)) - return -EINTR; - - do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); - if (ret) - return ret; - - if (sd->params.status.systemState != HI_POWER_STATE) { - PDEBUG(D_ERR, "unexpected state after hi power cmd: %02x", - sd->params.status.systemState); - printstatus(&sd->params); - return -EIO; - } - - PDEBUG(D_CONF, "camera now in HIGH power state"); - return 0; -} - -static int get_version_information(struct gspca_dev *gspca_dev) -{ - int ret; - - /* GetCPIAVersion */ - ret = do_command(gspca_dev, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0); - if (ret) - return ret; - - /* GetPnPID */ - return do_command(gspca_dev, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0); -} - -static int save_camera_state(struct gspca_dev *gspca_dev) -{ - int ret; - - ret = do_command(gspca_dev, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0); - if (ret) - return ret; - - return do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); -} - -static int command_setformat(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret; - - ret = do_command(gspca_dev, CPIA_COMMAND_SetFormat, - sd->params.format.videoSize, - sd->params.format.subSample, - sd->params.format.yuvOrder, 0); - if (ret) - return ret; - - return do_command(gspca_dev, CPIA_COMMAND_SetROI, - sd->params.roi.colStart, sd->params.roi.colEnd, - sd->params.roi.rowStart, sd->params.roi.rowEnd); -} - -static int command_setcolourparams(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - return do_command(gspca_dev, CPIA_COMMAND_SetColourParams, - sd->params.colourParams.brightness, - sd->params.colourParams.contrast, - sd->params.colourParams.saturation, 0); -} - -static int command_setapcor(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - return do_command(gspca_dev, CPIA_COMMAND_SetApcor, - sd->params.apcor.gain1, - sd->params.apcor.gain2, - sd->params.apcor.gain4, - sd->params.apcor.gain8); -} - -static int command_setvloffset(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - return do_command(gspca_dev, CPIA_COMMAND_SetVLOffset, - sd->params.vlOffset.gain1, - sd->params.vlOffset.gain2, - sd->params.vlOffset.gain4, - sd->params.vlOffset.gain8); -} - -static int command_setexposure(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret; - - ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure, - sd->params.exposure.gainMode, - 1, - sd->params.exposure.compMode, - sd->params.exposure.centreWeight, - sd->params.exposure.gain, - sd->params.exposure.fineExp, - sd->params.exposure.coarseExpLo, - sd->params.exposure.coarseExpHi, - sd->params.exposure.redComp, - sd->params.exposure.green1Comp, - sd->params.exposure.green2Comp, - sd->params.exposure.blueComp); - if (ret) - return ret; - - if (sd->params.exposure.expMode != 1) { - ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure, - 0, - sd->params.exposure.expMode, - 0, 0, - sd->params.exposure.gain, - sd->params.exposure.fineExp, - sd->params.exposure.coarseExpLo, - sd->params.exposure.coarseExpHi, - 0, 0, 0, 0); - } - - return ret; -} - -static int command_setcolourbalance(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->params.colourBalance.balanceMode == 1) { - int ret; - - ret = do_command(gspca_dev, CPIA_COMMAND_SetColourBalance, - 1, - sd->params.colourBalance.redGain, - sd->params.colourBalance.greenGain, - sd->params.colourBalance.blueGain); - if (ret) - return ret; - - return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance, - 3, 0, 0, 0); - } - if (sd->params.colourBalance.balanceMode == 2) { - return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance, - 2, 0, 0, 0); - } - if (sd->params.colourBalance.balanceMode == 3) { - return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance, - 3, 0, 0, 0); - } - - return -EINVAL; -} - -static int command_setcompressiontarget(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - return do_command(gspca_dev, CPIA_COMMAND_SetCompressionTarget, - sd->params.compressionTarget.frTargeting, - sd->params.compressionTarget.targetFR, - sd->params.compressionTarget.targetQ, 0); -} - -static int command_setyuvtresh(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - return do_command(gspca_dev, CPIA_COMMAND_SetYUVThresh, - sd->params.yuvThreshold.yThreshold, - sd->params.yuvThreshold.uvThreshold, 0, 0); -} - -static int command_setcompressionparams(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - return do_command_extended(gspca_dev, - CPIA_COMMAND_SetCompressionParams, - 0, 0, 0, 0, - sd->params.compressionParams.hysteresis, - sd->params.compressionParams.threshMax, - sd->params.compressionParams.smallStep, - sd->params.compressionParams.largeStep, - sd->params.compressionParams.decimationHysteresis, - sd->params.compressionParams.frDiffStepThresh, - sd->params.compressionParams.qDiffStepThresh, - sd->params.compressionParams.decimationThreshMod); -} - -static int command_setcompression(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - return do_command(gspca_dev, CPIA_COMMAND_SetCompression, - sd->params.compression.mode, - sd->params.compression.decimation, 0, 0); -} - -static int command_setsensorfps(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - return do_command(gspca_dev, CPIA_COMMAND_SetSensorFPS, - sd->params.sensorFps.divisor, - sd->params.sensorFps.baserate, 0, 0); -} - -static int command_setflickerctrl(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - return do_command(gspca_dev, CPIA_COMMAND_SetFlickerCtrl, - sd->params.flickerControl.flickerMode, - sd->params.flickerControl.coarseJump, - sd->params.flickerControl.allowableOverExposure, - 0); -} - -static int command_setecptiming(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - return do_command(gspca_dev, CPIA_COMMAND_SetECPTiming, - sd->params.ecpTiming, 0, 0, 0); -} - -static int command_pause(struct gspca_dev *gspca_dev) -{ - return do_command(gspca_dev, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0); -} - -static int command_resume(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - return do_command(gspca_dev, CPIA_COMMAND_InitStreamCap, - 0, sd->params.streamStartLine, 0, 0); -} - -static int command_setlights(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret, p1, p2; - - p1 = (sd->params.qx3.bottomlight == 0) << 1; - p2 = (sd->params.qx3.toplight == 0) << 3; - - ret = do_command(gspca_dev, CPIA_COMMAND_WriteVCReg, - 0x90, 0x8f, 0x50, 0); - if (ret) - return ret; - - return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0, - p1 | p2 | 0xe0, 0); -} - -static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply) -{ - /* Everything in here is from the Windows driver */ -/* define for compgain calculation */ -#if 0 -#define COMPGAIN(base, curexp, newexp) \ - (u8) ((((float) base - 128.0) * ((float) curexp / (float) newexp)) + 128.5) -#define EXP_FROM_COMP(basecomp, curcomp, curexp) \ - (u16)((float)curexp * (float)(u8)(curcomp + 128) / \ - (float)(u8)(basecomp - 128)) -#else - /* equivalent functions without floating point math */ -#define COMPGAIN(base, curexp, newexp) \ - (u8)(128 + (((u32)(2*(base-128)*curexp + newexp)) / (2 * newexp))) -#define EXP_FROM_COMP(basecomp, curcomp, curexp) \ - (u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128))) -#endif - - struct sd *sd = (struct sd *) gspca_dev; - int currentexp = sd->params.exposure.coarseExpLo + - sd->params.exposure.coarseExpHi * 256; - int ret, startexp; - - if (on) { - int cj = sd->params.flickerControl.coarseJump; - sd->params.flickerControl.flickerMode = 1; - sd->params.flickerControl.disabled = 0; - if (sd->params.exposure.expMode != 2) { - sd->params.exposure.expMode = 2; - sd->exposure_status = EXPOSURE_NORMAL; - } - currentexp = currentexp << sd->params.exposure.gain; - sd->params.exposure.gain = 0; - /* round down current exposure to nearest value */ - startexp = (currentexp + ROUND_UP_EXP_FOR_FLICKER) / cj; - if (startexp < 1) - startexp = 1; - startexp = (startexp * cj) - 1; - if (FIRMWARE_VERSION(1, 2)) - while (startexp > MAX_EXP_102) - startexp -= cj; - else - while (startexp > MAX_EXP) - startexp -= cj; - sd->params.exposure.coarseExpLo = startexp & 0xff; - sd->params.exposure.coarseExpHi = startexp >> 8; - if (currentexp > startexp) { - if (currentexp > (2 * startexp)) - currentexp = 2 * startexp; - sd->params.exposure.redComp = - COMPGAIN(COMP_RED, currentexp, startexp); - sd->params.exposure.green1Comp = - COMPGAIN(COMP_GREEN1, currentexp, startexp); - sd->params.exposure.green2Comp = - COMPGAIN(COMP_GREEN2, currentexp, startexp); - sd->params.exposure.blueComp = - COMPGAIN(COMP_BLUE, currentexp, startexp); - } else { - sd->params.exposure.redComp = COMP_RED; - sd->params.exposure.green1Comp = COMP_GREEN1; - sd->params.exposure.green2Comp = COMP_GREEN2; - sd->params.exposure.blueComp = COMP_BLUE; - } - if (FIRMWARE_VERSION(1, 2)) - sd->params.exposure.compMode = 0; - else - sd->params.exposure.compMode = 1; - - sd->params.apcor.gain1 = 0x18; - sd->params.apcor.gain2 = 0x18; - sd->params.apcor.gain4 = 0x16; - sd->params.apcor.gain8 = 0x14; - } else { - sd->params.flickerControl.flickerMode = 0; - sd->params.flickerControl.disabled = 1; - /* Average equivalent coarse for each comp channel */ - startexp = EXP_FROM_COMP(COMP_RED, - sd->params.exposure.redComp, currentexp); - startexp += EXP_FROM_COMP(COMP_GREEN1, - sd->params.exposure.green1Comp, currentexp); - startexp += EXP_FROM_COMP(COMP_GREEN2, - sd->params.exposure.green2Comp, currentexp); - startexp += EXP_FROM_COMP(COMP_BLUE, - sd->params.exposure.blueComp, currentexp); - startexp = startexp >> 2; - while (startexp > MAX_EXP && sd->params.exposure.gain < - sd->params.exposure.gainMode - 1) { - startexp = startexp >> 1; - ++sd->params.exposure.gain; - } - if (FIRMWARE_VERSION(1, 2) && startexp > MAX_EXP_102) - startexp = MAX_EXP_102; - if (startexp > MAX_EXP) - startexp = MAX_EXP; - sd->params.exposure.coarseExpLo = startexp & 0xff; - sd->params.exposure.coarseExpHi = startexp >> 8; - sd->params.exposure.redComp = COMP_RED; - sd->params.exposure.green1Comp = COMP_GREEN1; - sd->params.exposure.green2Comp = COMP_GREEN2; - sd->params.exposure.blueComp = COMP_BLUE; - sd->params.exposure.compMode = 1; - sd->params.apcor.gain1 = 0x18; - sd->params.apcor.gain2 = 0x16; - sd->params.apcor.gain4 = 0x24; - sd->params.apcor.gain8 = 0x34; - } - sd->params.vlOffset.gain1 = 20; - sd->params.vlOffset.gain2 = 24; - sd->params.vlOffset.gain4 = 26; - sd->params.vlOffset.gain8 = 26; - - if (apply) { - ret = command_setexposure(gspca_dev); - if (ret) - return ret; - - ret = command_setapcor(gspca_dev); - if (ret) - return ret; - - ret = command_setvloffset(gspca_dev); - if (ret) - return ret; - - ret = command_setflickerctrl(gspca_dev); - if (ret) - return ret; - } - - return 0; -#undef EXP_FROM_COMP -#undef COMPGAIN -} - -/* monitor the exposure and adjust the sensor frame rate if needed */ -static void monitor_exposure(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 exp_acc, bcomp, cmd[8]; - int ret, light_exp, dark_exp, very_dark_exp; - int old_exposure, new_exposure, framerate; - int setfps = 0, setexp = 0, setflicker = 0; - - /* get necessary stats and register settings from camera */ - /* do_command can't handle this, so do it ourselves */ - cmd[0] = CPIA_COMMAND_ReadVPRegs >> 8; - cmd[1] = CPIA_COMMAND_ReadVPRegs & 0xff; - cmd[2] = 30; - cmd[3] = 4; - cmd[4] = 9; - cmd[5] = 8; - cmd[6] = 8; - cmd[7] = 0; - ret = cpia_usb_transferCmd(gspca_dev, cmd); - if (ret) { - pr_err("ReadVPRegs(30,4,9,8) - failed: %d\n", ret); - return; - } - exp_acc = gspca_dev->usb_buf[0]; - bcomp = gspca_dev->usb_buf[1]; - - light_exp = sd->params.colourParams.brightness + - TC - 50 + EXP_ACC_LIGHT; - if (light_exp > 255) - light_exp = 255; - dark_exp = sd->params.colourParams.brightness + - TC - 50 - EXP_ACC_DARK; - if (dark_exp < 0) - dark_exp = 0; - very_dark_exp = dark_exp / 2; - - old_exposure = sd->params.exposure.coarseExpHi * 256 + - sd->params.exposure.coarseExpLo; - - if (!sd->params.flickerControl.disabled) { - /* Flicker control on */ - int max_comp = FIRMWARE_VERSION(1, 2) ? MAX_COMP : - HIGH_COMP_102; - bcomp += 128; /* decode */ - if (bcomp >= max_comp && exp_acc < dark_exp) { - /* dark */ - if (exp_acc < very_dark_exp) { - /* very dark */ - if (sd->exposure_status == EXPOSURE_VERY_DARK) - ++sd->exposure_count; - else { - sd->exposure_status = - EXPOSURE_VERY_DARK; - sd->exposure_count = 1; - } - } else { - /* just dark */ - if (sd->exposure_status == EXPOSURE_DARK) - ++sd->exposure_count; - else { - sd->exposure_status = EXPOSURE_DARK; - sd->exposure_count = 1; - } - } - } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) { - /* light */ - if (old_exposure <= VERY_LOW_EXP) { - /* very light */ - if (sd->exposure_status == EXPOSURE_VERY_LIGHT) - ++sd->exposure_count; - else { - sd->exposure_status = - EXPOSURE_VERY_LIGHT; - sd->exposure_count = 1; - } - } else { - /* just light */ - if (sd->exposure_status == EXPOSURE_LIGHT) - ++sd->exposure_count; - else { - sd->exposure_status = EXPOSURE_LIGHT; - sd->exposure_count = 1; - } - } - } else { - /* not dark or light */ - sd->exposure_status = EXPOSURE_NORMAL; - } - } else { - /* Flicker control off */ - if (old_exposure >= MAX_EXP && exp_acc < dark_exp) { - /* dark */ - if (exp_acc < very_dark_exp) { - /* very dark */ - if (sd->exposure_status == EXPOSURE_VERY_DARK) - ++sd->exposure_count; - else { - sd->exposure_status = - EXPOSURE_VERY_DARK; - sd->exposure_count = 1; - } - } else { - /* just dark */ - if (sd->exposure_status == EXPOSURE_DARK) - ++sd->exposure_count; - else { - sd->exposure_status = EXPOSURE_DARK; - sd->exposure_count = 1; - } - } - } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) { - /* light */ - if (old_exposure <= VERY_LOW_EXP) { - /* very light */ - if (sd->exposure_status == EXPOSURE_VERY_LIGHT) - ++sd->exposure_count; - else { - sd->exposure_status = - EXPOSURE_VERY_LIGHT; - sd->exposure_count = 1; - } - } else { - /* just light */ - if (sd->exposure_status == EXPOSURE_LIGHT) - ++sd->exposure_count; - else { - sd->exposure_status = EXPOSURE_LIGHT; - sd->exposure_count = 1; - } - } - } else { - /* not dark or light */ - sd->exposure_status = EXPOSURE_NORMAL; - } - } - - framerate = atomic_read(&sd->fps); - if (framerate > 30 || framerate < 1) - framerate = 1; - - if (!sd->params.flickerControl.disabled) { - /* Flicker control on */ - if ((sd->exposure_status == EXPOSURE_VERY_DARK || - sd->exposure_status == EXPOSURE_DARK) && - sd->exposure_count >= DARK_TIME * framerate && - sd->params.sensorFps.divisor < 2) { - - /* dark for too long */ - ++sd->params.sensorFps.divisor; - setfps = 1; - - sd->params.flickerControl.coarseJump = - flicker_jumps[sd->mainsFreq] - [sd->params.sensorFps.baserate] - [sd->params.sensorFps.divisor]; - setflicker = 1; - - new_exposure = sd->params.flickerControl.coarseJump-1; - while (new_exposure < old_exposure / 2) - new_exposure += - sd->params.flickerControl.coarseJump; - sd->params.exposure.coarseExpLo = new_exposure & 0xff; - sd->params.exposure.coarseExpHi = new_exposure >> 8; - setexp = 1; - sd->exposure_status = EXPOSURE_NORMAL; - PDEBUG(D_CONF, "Automatically decreasing sensor_fps"); - - } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT || - sd->exposure_status == EXPOSURE_LIGHT) && - sd->exposure_count >= LIGHT_TIME * framerate && - sd->params.sensorFps.divisor > 0) { - - /* light for too long */ - int max_exp = FIRMWARE_VERSION(1, 2) ? MAX_EXP_102 : - MAX_EXP; - --sd->params.sensorFps.divisor; - setfps = 1; - - sd->params.flickerControl.coarseJump = - flicker_jumps[sd->mainsFreq] - [sd->params.sensorFps.baserate] - [sd->params.sensorFps.divisor]; - setflicker = 1; - - new_exposure = sd->params.flickerControl.coarseJump-1; - while (new_exposure < 2 * old_exposure && - new_exposure + - sd->params.flickerControl.coarseJump < max_exp) - new_exposure += - sd->params.flickerControl.coarseJump; - sd->params.exposure.coarseExpLo = new_exposure & 0xff; - sd->params.exposure.coarseExpHi = new_exposure >> 8; - setexp = 1; - sd->exposure_status = EXPOSURE_NORMAL; - PDEBUG(D_CONF, "Automatically increasing sensor_fps"); - } - } else { - /* Flicker control off */ - if ((sd->exposure_status == EXPOSURE_VERY_DARK || - sd->exposure_status == EXPOSURE_DARK) && - sd->exposure_count >= DARK_TIME * framerate && - sd->params.sensorFps.divisor < 2) { - - /* dark for too long */ - ++sd->params.sensorFps.divisor; - setfps = 1; - - if (sd->params.exposure.gain > 0) { - --sd->params.exposure.gain; - setexp = 1; - } - sd->exposure_status = EXPOSURE_NORMAL; - PDEBUG(D_CONF, "Automatically decreasing sensor_fps"); - - } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT || - sd->exposure_status == EXPOSURE_LIGHT) && - sd->exposure_count >= LIGHT_TIME * framerate && - sd->params.sensorFps.divisor > 0) { - - /* light for too long */ - --sd->params.sensorFps.divisor; - setfps = 1; - - if (sd->params.exposure.gain < - sd->params.exposure.gainMode - 1) { - ++sd->params.exposure.gain; - setexp = 1; - } - sd->exposure_status = EXPOSURE_NORMAL; - PDEBUG(D_CONF, "Automatically increasing sensor_fps"); - } - } - - if (setexp) - command_setexposure(gspca_dev); - - if (setfps) - command_setsensorfps(gspca_dev); - - if (setflicker) - command_setflickerctrl(gspca_dev); -} - -/*-----------------------------------------------------------------*/ -/* if flicker is switched off, this function switches it back on.It checks, - however, that conditions are suitable before restarting it. - This should only be called for firmware version 1.2. - - It also adjust the colour balance when an exposure step is detected - as - long as flicker is running -*/ -static void restart_flicker(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int cam_exposure, old_exp; - - if (!FIRMWARE_VERSION(1, 2)) - return; - - cam_exposure = atomic_read(&sd->cam_exposure); - - if (sd->params.flickerControl.flickerMode == 0 || - cam_exposure == 0) - return; - - old_exp = sd->params.exposure.coarseExpLo + - sd->params.exposure.coarseExpHi*256; - /* - see how far away camera exposure is from a valid - flicker exposure value - */ - cam_exposure %= sd->params.flickerControl.coarseJump; - if (!sd->params.flickerControl.disabled && - cam_exposure <= sd->params.flickerControl.coarseJump - 3) { - /* Flicker control auto-disabled */ - sd->params.flickerControl.disabled = 1; - } - - if (sd->params.flickerControl.disabled && - old_exp > sd->params.flickerControl.coarseJump + - ROUND_UP_EXP_FOR_FLICKER) { - /* exposure is now high enough to switch - flicker control back on */ - set_flicker(gspca_dev, 1, 1); - } -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - - sd->mainsFreq = FREQ_DEF == V4L2_CID_POWER_LINE_FREQUENCY_60HZ; - reset_camera_params(gspca_dev); - - PDEBUG(D_PROBE, "cpia CPiA camera detected (vid/pid 0x%04X:0x%04X)", - id->idVendor, id->idProduct); - - cam = &gspca_dev->cam; - cam->cam_mode = mode; - cam->nmodes = ARRAY_SIZE(mode); - - goto_low_power(gspca_dev); - /* Check the firmware version. */ - sd->params.version.firmwareVersion = 0; - get_version_information(gspca_dev); - if (sd->params.version.firmwareVersion != 1) { - PDEBUG(D_ERR, "only firmware version 1 is supported (got: %d)", - sd->params.version.firmwareVersion); - return -ENODEV; - } - - /* A bug in firmware 1-02 limits gainMode to 2 */ - if (sd->params.version.firmwareRevision <= 2 && - sd->params.exposure.gainMode > 2) { - sd->params.exposure.gainMode = 2; - } - - /* set QX3 detected flag */ - sd->params.qx3.qx3_detected = (sd->params.pnpID.vendor == 0x0813 && - sd->params.pnpID.product == 0x0001); - return 0; -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int priv, ret; - - /* Start the camera in low power mode */ - if (goto_low_power(gspca_dev)) { - if (sd->params.status.systemState != WARM_BOOT_STATE) { - PDEBUG(D_ERR, "unexpected systemstate: %02x", - sd->params.status.systemState); - printstatus(&sd->params); - return -ENODEV; - } - - /* FIXME: this is just dirty trial and error */ - ret = goto_high_power(gspca_dev); - if (ret) - return ret; - - ret = do_command(gspca_dev, CPIA_COMMAND_DiscardFrame, - 0, 0, 0, 0); - if (ret) - return ret; - - ret = goto_low_power(gspca_dev); - if (ret) - return ret; - } - - /* procedure described in developer's guide p3-28 */ - - /* Check the firmware version. */ - sd->params.version.firmwareVersion = 0; - get_version_information(gspca_dev); - - /* The fatal error checking should be done after - * the camera powers up (developer's guide p 3-38) */ - - /* Set streamState before transition to high power to avoid bug - * in firmware 1-02 */ - ret = do_command(gspca_dev, CPIA_COMMAND_ModifyCameraStatus, - STREAMSTATE, 0, STREAM_NOT_READY, 0); - if (ret) - return ret; - - /* GotoHiPower */ - ret = goto_high_power(gspca_dev); - if (ret) - return ret; - - /* Check the camera status */ - ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); - if (ret) - return ret; - - if (sd->params.status.fatalError) { - PDEBUG(D_ERR, "fatal_error: %04x, vp_status: %04x", - sd->params.status.fatalError, - sd->params.status.vpStatus); - return -EIO; - } - - /* VPVersion can't be retrieved before the camera is in HiPower, - * so get it here instead of in get_version_information. */ - ret = do_command(gspca_dev, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0); - if (ret) - return ret; - - /* Determine video mode settings */ - sd->params.streamStartLine = 120; - - priv = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - if (priv & 0x01) { /* crop */ - sd->params.roi.colStart = 2; - sd->params.roi.rowStart = 6; - } else { - sd->params.roi.colStart = 0; - sd->params.roi.rowStart = 0; - } - - if (priv & 0x02) { /* quarter */ - sd->params.format.videoSize = VIDEOSIZE_QCIF; - sd->params.roi.colStart /= 2; - sd->params.roi.rowStart /= 2; - sd->params.streamStartLine /= 2; - } else - sd->params.format.videoSize = VIDEOSIZE_CIF; - - sd->params.roi.colEnd = sd->params.roi.colStart + - (gspca_dev->width >> 3); - sd->params.roi.rowEnd = sd->params.roi.rowStart + - (gspca_dev->height >> 2); - - /* And now set the camera to a known state */ - ret = do_command(gspca_dev, CPIA_COMMAND_SetGrabMode, - CPIA_GRAB_CONTINEOUS, 0, 0, 0); - if (ret) - return ret; - /* We start with compression disabled, as we need one uncompressed - frame to handle later compressed frames */ - ret = do_command(gspca_dev, CPIA_COMMAND_SetCompression, - CPIA_COMPRESSION_NONE, - NO_DECIMATION, 0, 0); - if (ret) - return ret; - ret = command_setcompressiontarget(gspca_dev); - if (ret) - return ret; - ret = command_setcolourparams(gspca_dev); - if (ret) - return ret; - ret = command_setformat(gspca_dev); - if (ret) - return ret; - ret = command_setyuvtresh(gspca_dev); - if (ret) - return ret; - ret = command_setecptiming(gspca_dev); - if (ret) - return ret; - ret = command_setcompressionparams(gspca_dev); - if (ret) - return ret; - ret = command_setexposure(gspca_dev); - if (ret) - return ret; - ret = command_setcolourbalance(gspca_dev); - if (ret) - return ret; - ret = command_setsensorfps(gspca_dev); - if (ret) - return ret; - ret = command_setapcor(gspca_dev); - if (ret) - return ret; - ret = command_setflickerctrl(gspca_dev); - if (ret) - return ret; - ret = command_setvloffset(gspca_dev); - if (ret) - return ret; - - /* Start stream */ - ret = command_resume(gspca_dev); - if (ret) - return ret; - - /* Wait 6 frames before turning compression on for the sensor to get - all settings and AEC/ACB to settle */ - sd->first_frame = 6; - sd->exposure_status = EXPOSURE_NORMAL; - sd->exposure_count = 0; - atomic_set(&sd->cam_exposure, 0); - atomic_set(&sd->fps, 0); - - return 0; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - command_pause(gspca_dev); - - /* save camera state for later open (developers guide ch 3.5.3) */ - save_camera_state(gspca_dev); - - /* GotoLoPower */ - goto_low_power(gspca_dev); - - /* Update the camera status */ - do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - /* If the last button state is pressed, release it now! */ - if (sd->params.qx3.button) { - /* The camera latch will hold the pressed state until we reset - the latch, so we do not reset sd->params.qx3.button now, to - avoid a false keypress being reported the next sd_start */ - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); - input_sync(gspca_dev->input_dev); - } -#endif -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret; - - /* Start / Stop the camera to make sure we are talking to - a supported camera, and to get some information from it - to print. */ - ret = sd_start(gspca_dev); - if (ret) - return ret; - - /* Ensure the QX3 illuminators' states are restored upon resume, - or disable the illuminator controls, if this isn't a QX3 */ - if (sd->params.qx3.qx3_detected) - command_setlights(gspca_dev); - - sd_stopN(gspca_dev); - - PDEBUG(D_PROBE, "CPIA Version: %d.%02d (%d.%d)", - sd->params.version.firmwareVersion, - sd->params.version.firmwareRevision, - sd->params.version.vcVersion, - sd->params.version.vcRevision); - PDEBUG(D_PROBE, "CPIA PnP-ID: %04x:%04x:%04x", - sd->params.pnpID.vendor, sd->params.pnpID.product, - sd->params.pnpID.deviceRevision); - PDEBUG(D_PROBE, "VP-Version: %d.%d %04x", - sd->params.vpVersion.vpVersion, - sd->params.vpVersion.vpRevision, - sd->params.vpVersion.cameraHeadID); - - return 0; -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, - int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* Check for SOF */ - if (len >= 64 && - data[0] == MAGIC_0 && data[1] == MAGIC_1 && - data[16] == sd->params.format.videoSize && - data[17] == sd->params.format.subSample && - data[18] == sd->params.format.yuvOrder && - data[24] == sd->params.roi.colStart && - data[25] == sd->params.roi.colEnd && - data[26] == sd->params.roi.rowStart && - data[27] == sd->params.roi.rowEnd) { - u8 *image; - - atomic_set(&sd->cam_exposure, data[39] * 2); - atomic_set(&sd->fps, data[41]); - - /* Check for proper EOF for last frame */ - image = gspca_dev->image; - if (image != NULL && - gspca_dev->image_len > 4 && - image[gspca_dev->image_len - 4] == 0xff && - image[gspca_dev->image_len - 3] == 0xff && - image[gspca_dev->image_len - 2] == 0xff && - image[gspca_dev->image_len - 1] == 0xff) - gspca_frame_add(gspca_dev, LAST_PACKET, - NULL, 0); - - gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); - return; - } - - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -static void sd_dq_callback(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* Set the normal compression settings once we have captured a - few uncompressed frames (and AEC has hopefully settled) */ - if (sd->first_frame) { - sd->first_frame--; - if (sd->first_frame == 0) - command_setcompression(gspca_dev); - } - - /* Switch flicker control back on if it got turned off */ - restart_flicker(gspca_dev); - - /* If AEC is enabled, monitor the exposure and - adjust the sensor frame rate if needed */ - if (sd->params.exposure.expMode == 2) - monitor_exposure(gspca_dev); - - /* Update our knowledge of the camera state */ - do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); - do_command(gspca_dev, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0); -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming && ctrl->id != V4L2_CID_POWER_LINE_FREQUENCY) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - sd->params.colourParams.brightness = ctrl->val; - sd->params.flickerControl.allowableOverExposure = - find_over_exposure(sd->params.colourParams.brightness); - gspca_dev->usb_err = command_setcolourparams(gspca_dev); - if (!gspca_dev->usb_err) - gspca_dev->usb_err = command_setflickerctrl(gspca_dev); - break; - case V4L2_CID_CONTRAST: - sd->params.colourParams.contrast = ctrl->val; - gspca_dev->usb_err = command_setcolourparams(gspca_dev); - break; - case V4L2_CID_SATURATION: - sd->params.colourParams.saturation = ctrl->val; - gspca_dev->usb_err = command_setcolourparams(gspca_dev); - break; - case V4L2_CID_POWER_LINE_FREQUENCY: - sd->mainsFreq = ctrl->val == V4L2_CID_POWER_LINE_FREQUENCY_60HZ; - sd->params.flickerControl.coarseJump = - flicker_jumps[sd->mainsFreq] - [sd->params.sensorFps.baserate] - [sd->params.sensorFps.divisor]; - - gspca_dev->usb_err = set_flicker(gspca_dev, - ctrl->val != V4L2_CID_POWER_LINE_FREQUENCY_DISABLED, - gspca_dev->streaming); - break; - case V4L2_CID_ILLUMINATORS_1: - sd->params.qx3.bottomlight = ctrl->val; - gspca_dev->usb_err = command_setlights(gspca_dev); - break; - case V4L2_CID_ILLUMINATORS_2: - sd->params.qx3.toplight = ctrl->val; - gspca_dev->usb_err = command_setlights(gspca_dev); - break; - case CPIA1_CID_COMP_TARGET: - sd->params.compressionTarget.frTargeting = ctrl->val; - gspca_dev->usb_err = command_setcompressiontarget(gspca_dev); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - static const char * const comp_target_menu[] = { - "Quality", - "Framerate", - NULL - }; - static const struct v4l2_ctrl_config comp_target = { - .ops = &sd_ctrl_ops, - .id = CPIA1_CID_COMP_TARGET, - .type = V4L2_CTRL_TYPE_MENU, - .name = "Compression Target", - .qmenu = comp_target_menu, - .max = 1, - .def = COMP_TARGET_DEF, - }; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 7); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 100, 1, BRIGHTNESS_DEF); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 96, 8, CONTRAST_DEF); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SATURATION, 0, 100, 1, SATURATION_DEF); - sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, - V4L2_CID_POWER_LINE_FREQUENCY, - V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, - FREQ_DEF); - if (sd->params.qx3.qx3_detected) { - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_ILLUMINATORS_1, 0, 1, 1, - ILLUMINATORS_1_DEF); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_ILLUMINATORS_2, 0, 1, 1, - ILLUMINATORS_2_DEF); - } - v4l2_ctrl_new_custom(hdl, &comp_target, NULL); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .dq_callback = sd_dq_callback, - .pkt_scan = sd_pkt_scan, -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .other_input = 1, -#endif -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x0553, 0x0002)}, - {USB_DEVICE(0x0813, 0x0001)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c deleted file mode 100644 index 38f68e11c3a2..000000000000 --- a/drivers/media/video/gspca/etoms.c +++ /dev/null @@ -1,799 +0,0 @@ -/* - * Etoms Et61x151 GPL Linux driver by Michel Xhaard (09/09/2004) - * - * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "etoms" - -#include "gspca.h" - -MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); -MODULE_DESCRIPTION("Etoms USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - unsigned char autogain; - - char sensor; -#define SENSOR_PAS106 0 -#define SENSOR_TAS5130CXX 1 - signed char ag_cnt; -#define AG_CNT_START 13 -}; - -static const struct v4l2_pix_format vga_mode[] = { - {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, -/* {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, */ -}; - -static const struct v4l2_pix_format sif_mode[] = { - {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; - -#define ETOMS_ALT_SIZE_1000 12 - -#define ET_GPIO_DIR_CTRL 0x04 /* Control IO bit[0..5] (0 in 1 out) */ -#define ET_GPIO_OUT 0x05 /* Only IO data */ -#define ET_GPIO_IN 0x06 /* Read Only IO data */ -#define ET_RESET_ALL 0x03 -#define ET_ClCK 0x01 -#define ET_CTRL 0x02 /* enable i2c OutClck Powerdown mode */ - -#define ET_COMP 0x12 /* Compression register */ -#define ET_MAXQt 0x13 -#define ET_MINQt 0x14 -#define ET_COMP_VAL0 0x02 -#define ET_COMP_VAL1 0x03 - -#define ET_REG1d 0x1d -#define ET_REG1e 0x1e -#define ET_REG1f 0x1f -#define ET_REG20 0x20 -#define ET_REG21 0x21 -#define ET_REG22 0x22 -#define ET_REG23 0x23 -#define ET_REG24 0x24 -#define ET_REG25 0x25 -/* base registers for luma calculation */ -#define ET_LUMA_CENTER 0x39 - -#define ET_G_RED 0x4d -#define ET_G_GREEN1 0x4e -#define ET_G_BLUE 0x4f -#define ET_G_GREEN2 0x50 -#define ET_G_GR_H 0x51 -#define ET_G_GB_H 0x52 - -#define ET_O_RED 0x34 -#define ET_O_GREEN1 0x35 -#define ET_O_BLUE 0x36 -#define ET_O_GREEN2 0x37 - -#define ET_SYNCHRO 0x68 -#define ET_STARTX 0x69 -#define ET_STARTY 0x6a -#define ET_WIDTH_LOW 0x6b -#define ET_HEIGTH_LOW 0x6c -#define ET_W_H_HEIGTH 0x6d - -#define ET_REG6e 0x6e /* OBW */ -#define ET_REG6f 0x6f /* OBW */ -#define ET_REG70 0x70 /* OBW_AWB */ -#define ET_REG71 0x71 /* OBW_AWB */ -#define ET_REG72 0x72 /* OBW_AWB */ -#define ET_REG73 0x73 /* Clkdelay ns */ -#define ET_REG74 0x74 /* test pattern */ -#define ET_REG75 0x75 /* test pattern */ - -#define ET_I2C_CLK 0x8c -#define ET_PXL_CLK 0x60 - -#define ET_I2C_BASE 0x89 -#define ET_I2C_COUNT 0x8a -#define ET_I2C_PREFETCH 0x8b -#define ET_I2C_REG 0x88 -#define ET_I2C_DATA7 0x87 -#define ET_I2C_DATA6 0x86 -#define ET_I2C_DATA5 0x85 -#define ET_I2C_DATA4 0x84 -#define ET_I2C_DATA3 0x83 -#define ET_I2C_DATA2 0x82 -#define ET_I2C_DATA1 0x81 -#define ET_I2C_DATA0 0x80 - -#define PAS106_REG2 0x02 /* pxlClk = systemClk/(reg2) */ -#define PAS106_REG3 0x03 /* line/frame H [11..4] */ -#define PAS106_REG4 0x04 /* line/frame L [3..0] */ -#define PAS106_REG5 0x05 /* exposure time line offset(default 5) */ -#define PAS106_REG6 0x06 /* exposure time pixel offset(default 6) */ -#define PAS106_REG7 0x07 /* signbit Dac (default 0) */ -#define PAS106_REG9 0x09 -#define PAS106_REG0e 0x0e /* global gain [4..0](default 0x0e) */ -#define PAS106_REG13 0x13 /* end i2c write */ - -static const __u8 GainRGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 }; - -static const __u8 I2c2[] = { 0x08, 0x08, 0x08, 0x08, 0x0d }; - -static const __u8 I2c3[] = { 0x12, 0x05 }; - -static const __u8 I2c4[] = { 0x41, 0x08 }; - -/* read 'len' bytes to gspca_dev->usb_buf */ -static void reg_r(struct gspca_dev *gspca_dev, - __u16 index, - __u16 len) -{ - struct usb_device *dev = gspca_dev->dev; - -#ifdef GSPCA_DEBUG - if (len > USB_BUF_SZ) { - pr_err("reg_r: buffer overflow\n"); - return; - } -#endif - usb_control_msg(dev, - usb_rcvctrlpipe(dev, 0), - 0, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0, - index, gspca_dev->usb_buf, len, 500); - PDEBUG(D_USBI, "reg read [%02x] -> %02x ..", - index, gspca_dev->usb_buf[0]); -} - -static void reg_w_val(struct gspca_dev *gspca_dev, - __u16 index, - __u8 val) -{ - struct usb_device *dev = gspca_dev->dev; - - gspca_dev->usb_buf[0] = val; - usb_control_msg(dev, - usb_sndctrlpipe(dev, 0), - 0, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0, - index, gspca_dev->usb_buf, 1, 500); -} - -static void reg_w(struct gspca_dev *gspca_dev, - __u16 index, - const __u8 *buffer, - __u16 len) -{ - struct usb_device *dev = gspca_dev->dev; - -#ifdef GSPCA_DEBUG - if (len > USB_BUF_SZ) { - pr_err("reg_w: buffer overflow\n"); - return; - } - PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer); -#endif - memcpy(gspca_dev->usb_buf, buffer, len); - usb_control_msg(dev, - usb_sndctrlpipe(dev, 0), - 0, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0, index, gspca_dev->usb_buf, len, 500); -} - -static int i2c_w(struct gspca_dev *gspca_dev, - __u8 reg, - const __u8 *buffer, - int len, __u8 mode) -{ - /* buffer should be [D0..D7] */ - __u8 ptchcount; - - /* set the base address */ - reg_w_val(gspca_dev, ET_I2C_BASE, 0x40); - /* sensor base for the pas106 */ - /* set count and prefetch */ - ptchcount = ((len & 0x07) << 4) | (mode & 0x03); - reg_w_val(gspca_dev, ET_I2C_COUNT, ptchcount); - /* set the register base */ - reg_w_val(gspca_dev, ET_I2C_REG, reg); - while (--len >= 0) - reg_w_val(gspca_dev, ET_I2C_DATA0 + len, buffer[len]); - return 0; -} - -static int i2c_r(struct gspca_dev *gspca_dev, - __u8 reg) -{ - /* set the base address */ - reg_w_val(gspca_dev, ET_I2C_BASE, 0x40); - /* sensor base for the pas106 */ - /* set count and prefetch (cnd: 4 bits - mode: 4 bits) */ - reg_w_val(gspca_dev, ET_I2C_COUNT, 0x11); - reg_w_val(gspca_dev, ET_I2C_REG, reg); /* set the register base */ - reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x02); /* prefetch */ - reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x00); - reg_r(gspca_dev, ET_I2C_DATA0, 1); /* read one byte */ - return 0; -} - -static int Et_WaitStatus(struct gspca_dev *gspca_dev) -{ - int retry = 10; - - while (retry--) { - reg_r(gspca_dev, ET_ClCK, 1); - if (gspca_dev->usb_buf[0] != 0) - return 1; - } - return 0; -} - -static int et_video(struct gspca_dev *gspca_dev, - int on) -{ - int ret; - - reg_w_val(gspca_dev, ET_GPIO_OUT, - on ? 0x10 /* startvideo - set Bit5 */ - : 0); /* stopvideo */ - ret = Et_WaitStatus(gspca_dev); - if (ret != 0) - PDEBUG(D_ERR, "timeout video on/off"); - return ret; -} - -static void Et_init2(struct gspca_dev *gspca_dev) -{ - __u8 value; - static const __u8 FormLine[] = { 0x84, 0x03, 0x14, 0xf4, 0x01, 0x05 }; - - PDEBUG(D_STREAM, "Open Init2 ET"); - reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 0x2f); - reg_w_val(gspca_dev, ET_GPIO_OUT, 0x10); - reg_r(gspca_dev, ET_GPIO_IN, 1); - reg_w_val(gspca_dev, ET_ClCK, 0x14); /* 0x14 // 0x16 enabled pattern */ - reg_w_val(gspca_dev, ET_CTRL, 0x1b); - - /* compression et subsampling */ - if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) - value = ET_COMP_VAL1; /* 320 */ - else - value = ET_COMP_VAL0; /* 640 */ - reg_w_val(gspca_dev, ET_COMP, value); - reg_w_val(gspca_dev, ET_MAXQt, 0x1f); - reg_w_val(gspca_dev, ET_MINQt, 0x04); - /* undocumented registers */ - reg_w_val(gspca_dev, ET_REG1d, 0xff); - reg_w_val(gspca_dev, ET_REG1e, 0xff); - reg_w_val(gspca_dev, ET_REG1f, 0xff); - reg_w_val(gspca_dev, ET_REG20, 0x35); - reg_w_val(gspca_dev, ET_REG21, 0x01); - reg_w_val(gspca_dev, ET_REG22, 0x00); - reg_w_val(gspca_dev, ET_REG23, 0xff); - reg_w_val(gspca_dev, ET_REG24, 0xff); - reg_w_val(gspca_dev, ET_REG25, 0x0f); - /* colors setting */ - reg_w_val(gspca_dev, 0x30, 0x11); /* 0x30 */ - reg_w_val(gspca_dev, 0x31, 0x40); - reg_w_val(gspca_dev, 0x32, 0x00); - reg_w_val(gspca_dev, ET_O_RED, 0x00); /* 0x34 */ - reg_w_val(gspca_dev, ET_O_GREEN1, 0x00); - reg_w_val(gspca_dev, ET_O_BLUE, 0x00); - reg_w_val(gspca_dev, ET_O_GREEN2, 0x00); - /*************/ - reg_w_val(gspca_dev, ET_G_RED, 0x80); /* 0x4d */ - reg_w_val(gspca_dev, ET_G_GREEN1, 0x80); - reg_w_val(gspca_dev, ET_G_BLUE, 0x80); - reg_w_val(gspca_dev, ET_G_GREEN2, 0x80); - reg_w_val(gspca_dev, ET_G_GR_H, 0x00); - reg_w_val(gspca_dev, ET_G_GB_H, 0x00); /* 0x52 */ - /* Window control registers */ - reg_w_val(gspca_dev, 0x61, 0x80); /* use cmc_out */ - reg_w_val(gspca_dev, 0x62, 0x02); - reg_w_val(gspca_dev, 0x63, 0x03); - reg_w_val(gspca_dev, 0x64, 0x14); - reg_w_val(gspca_dev, 0x65, 0x0e); - reg_w_val(gspca_dev, 0x66, 0x02); - reg_w_val(gspca_dev, 0x67, 0x02); - - /**************************************/ - reg_w_val(gspca_dev, ET_SYNCHRO, 0x8f); /* 0x68 */ - reg_w_val(gspca_dev, ET_STARTX, 0x69); /* 0x6a //0x69 */ - reg_w_val(gspca_dev, ET_STARTY, 0x0d); /* 0x0d //0x0c */ - reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x80); - reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0xe0); - reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x60); /* 6d */ - reg_w_val(gspca_dev, ET_REG6e, 0x86); - reg_w_val(gspca_dev, ET_REG6f, 0x01); - reg_w_val(gspca_dev, ET_REG70, 0x26); - reg_w_val(gspca_dev, ET_REG71, 0x7a); - reg_w_val(gspca_dev, ET_REG72, 0x01); - /* Clock Pattern registers ***************** */ - reg_w_val(gspca_dev, ET_REG73, 0x00); - reg_w_val(gspca_dev, ET_REG74, 0x18); /* 0x28 */ - reg_w_val(gspca_dev, ET_REG75, 0x0f); /* 0x01 */ - /**********************************************/ - reg_w_val(gspca_dev, 0x8a, 0x20); - reg_w_val(gspca_dev, 0x8d, 0x0f); - reg_w_val(gspca_dev, 0x8e, 0x08); - /**************************************/ - reg_w_val(gspca_dev, 0x03, 0x08); - reg_w_val(gspca_dev, ET_PXL_CLK, 0x03); - reg_w_val(gspca_dev, 0x81, 0xff); - reg_w_val(gspca_dev, 0x80, 0x00); - reg_w_val(gspca_dev, 0x81, 0xff); - reg_w_val(gspca_dev, 0x80, 0x20); - reg_w_val(gspca_dev, 0x03, 0x01); - reg_w_val(gspca_dev, 0x03, 0x00); - reg_w_val(gspca_dev, 0x03, 0x08); - /********************************************/ - -/* reg_r(gspca_dev, ET_I2C_BASE, 1); - always 0x40 as the pas106 ??? */ - /* set the sensor */ - if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) - value = 0x04; /* 320 */ - else /* 640 */ - value = 0x1e; /* 0x17 * setting PixelClock - * 0x03 mean 24/(3+1) = 6 Mhz - * 0x05 -> 24/(5+1) = 4 Mhz - * 0x0b -> 24/(11+1) = 2 Mhz - * 0x17 -> 24/(23+1) = 1 Mhz - */ - reg_w_val(gspca_dev, ET_PXL_CLK, value); - /* now set by fifo the FormatLine setting */ - reg_w(gspca_dev, 0x62, FormLine, 6); - - /* set exposure times [ 0..0x78] 0->longvalue 0x78->shortvalue */ - reg_w_val(gspca_dev, 0x81, 0x47); /* 0x47; */ - reg_w_val(gspca_dev, 0x80, 0x40); /* 0x40; */ - /* Pedro change */ - /* Brightness change Brith+ decrease value */ - /* Brigth- increase value */ - /* original value = 0x70; */ - reg_w_val(gspca_dev, 0x81, 0x30); /* 0x20; - set brightness */ - reg_w_val(gspca_dev, 0x80, 0x20); /* 0x20; */ -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 val) -{ - int i; - - for (i = 0; i < 4; i++) - reg_w_val(gspca_dev, ET_O_RED + i, val); -} - -static void setcontrast(struct gspca_dev *gspca_dev, s32 val) -{ - __u8 RGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 }; - - memset(RGBG, val, sizeof(RGBG) - 2); - reg_w(gspca_dev, ET_G_RED, RGBG, 6); -} - -static void setcolors(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - __u8 I2cc[] = { 0x05, 0x02, 0x02, 0x05, 0x0d }; - __u8 i2cflags = 0x01; - /* __u8 green = 0; */ - - I2cc[3] = val; /* red */ - I2cc[0] = 15 - val; /* blue */ - /* green = 15 - ((((7*I2cc[0]) >> 2 ) + I2cc[3]) >> 1); */ - /* I2cc[1] = I2cc[2] = green; */ - if (sd->sensor == SENSOR_PAS106) { - i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3); - i2c_w(gspca_dev, PAS106_REG9, I2cc, sizeof I2cc, 1); - } -/* PDEBUG(D_CONF , "Etoms red %d blue %d green %d", - I2cc[3], I2cc[0], green); */ -} - -static s32 getcolors(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_PAS106) { -/* i2c_r(gspca_dev, PAS106_REG9); * blue */ - i2c_r(gspca_dev, PAS106_REG9 + 3); /* red */ - return gspca_dev->usb_buf[0] & 0x0f; - } - return 0; -} - -static void setautogain(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->autogain) - sd->ag_cnt = AG_CNT_START; - else - sd->ag_cnt = -1; -} - -static void Et_init1(struct gspca_dev *gspca_dev) -{ - __u8 value; -/* __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0x22, 0xac, 0x00, 0x01, 0x00}; */ - __u8 I2c0[] = { 0x0a, 0x12, 0x05, 0x6d, 0xcd, 0x00, 0x01, 0x00 }; - /* try 1/120 0x6d 0xcd 0x40 */ -/* __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0xfe, 0xfe, 0xc0, 0x01, 0x00}; - * 1/60000 hmm ?? */ - - PDEBUG(D_STREAM, "Open Init1 ET"); - reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 7); - reg_r(gspca_dev, ET_GPIO_IN, 1); - reg_w_val(gspca_dev, ET_RESET_ALL, 1); - reg_w_val(gspca_dev, ET_RESET_ALL, 0); - reg_w_val(gspca_dev, ET_ClCK, 0x10); - reg_w_val(gspca_dev, ET_CTRL, 0x19); - /* compression et subsampling */ - if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) - value = ET_COMP_VAL1; - else - value = ET_COMP_VAL0; - PDEBUG(D_STREAM, "Open mode %d Compression %d", - gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv, - value); - reg_w_val(gspca_dev, ET_COMP, value); - reg_w_val(gspca_dev, ET_MAXQt, 0x1d); - reg_w_val(gspca_dev, ET_MINQt, 0x02); - /* undocumented registers */ - reg_w_val(gspca_dev, ET_REG1d, 0xff); - reg_w_val(gspca_dev, ET_REG1e, 0xff); - reg_w_val(gspca_dev, ET_REG1f, 0xff); - reg_w_val(gspca_dev, ET_REG20, 0x35); - reg_w_val(gspca_dev, ET_REG21, 0x01); - reg_w_val(gspca_dev, ET_REG22, 0x00); - reg_w_val(gspca_dev, ET_REG23, 0xf7); - reg_w_val(gspca_dev, ET_REG24, 0xff); - reg_w_val(gspca_dev, ET_REG25, 0x07); - /* colors setting */ - reg_w_val(gspca_dev, ET_G_RED, 0x80); - reg_w_val(gspca_dev, ET_G_GREEN1, 0x80); - reg_w_val(gspca_dev, ET_G_BLUE, 0x80); - reg_w_val(gspca_dev, ET_G_GREEN2, 0x80); - reg_w_val(gspca_dev, ET_G_GR_H, 0x00); - reg_w_val(gspca_dev, ET_G_GB_H, 0x00); - /* Window control registers */ - reg_w_val(gspca_dev, ET_SYNCHRO, 0xf0); - reg_w_val(gspca_dev, ET_STARTX, 0x56); /* 0x56 */ - reg_w_val(gspca_dev, ET_STARTY, 0x05); /* 0x04 */ - reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x60); - reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0x20); - reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x50); - reg_w_val(gspca_dev, ET_REG6e, 0x86); - reg_w_val(gspca_dev, ET_REG6f, 0x01); - reg_w_val(gspca_dev, ET_REG70, 0x86); - reg_w_val(gspca_dev, ET_REG71, 0x14); - reg_w_val(gspca_dev, ET_REG72, 0x00); - /* Clock Pattern registers */ - reg_w_val(gspca_dev, ET_REG73, 0x00); - reg_w_val(gspca_dev, ET_REG74, 0x00); - reg_w_val(gspca_dev, ET_REG75, 0x0a); - reg_w_val(gspca_dev, ET_I2C_CLK, 0x04); - reg_w_val(gspca_dev, ET_PXL_CLK, 0x01); - /* set the sensor */ - if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { - I2c0[0] = 0x06; - i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1); - i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1); - value = 0x06; - i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1); - i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1); - /* value = 0x1f; */ - value = 0x04; - i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1); - } else { - I2c0[0] = 0x0a; - - i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1); - i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1); - value = 0x0a; - i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1); - i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1); - value = 0x04; - /* value = 0x10; */ - i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1); - /* bit 2 enable bit 1:2 select 0 1 2 3 - value = 0x07; * curve 0 * - i2c_w(gspca_dev, PAS106_REG0f, &value, 1, 1); - */ - } - -/* value = 0x01; */ -/* value = 0x22; */ -/* i2c_w(gspca_dev, PAS106_REG5, &value, 1, 1); */ - /* magnetude and sign bit for DAC */ - i2c_w(gspca_dev, PAS106_REG7, I2c4, sizeof I2c4, 1); - /* now set by fifo the whole colors setting */ - reg_w(gspca_dev, ET_G_RED, GainRGBG, 6); - setcolors(gspca_dev, getcolors(gspca_dev)); -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - - cam = &gspca_dev->cam; - sd->sensor = id->driver_info; - if (sd->sensor == SENSOR_PAS106) { - cam->cam_mode = sif_mode; - cam->nmodes = ARRAY_SIZE(sif_mode); - } else { - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - } - sd->ag_cnt = -1; - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_PAS106) - Et_init1(gspca_dev); - else - Et_init2(gspca_dev); - reg_w_val(gspca_dev, ET_RESET_ALL, 0x08); - et_video(gspca_dev, 0); /* video off */ - return 0; -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_PAS106) - Et_init1(gspca_dev); - else - Et_init2(gspca_dev); - - setautogain(gspca_dev); - - reg_w_val(gspca_dev, ET_RESET_ALL, 0x08); - et_video(gspca_dev, 1); /* video on */ - return 0; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - et_video(gspca_dev, 0); /* video off */ -} - -static __u8 Et_getgainG(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_PAS106) { - i2c_r(gspca_dev, PAS106_REG0e); - PDEBUG(D_CONF, "Etoms gain G %d", gspca_dev->usb_buf[0]); - return gspca_dev->usb_buf[0]; - } - return 0x1f; -} - -static void Et_setgainG(struct gspca_dev *gspca_dev, __u8 gain) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_PAS106) { - __u8 i2cflags = 0x01; - - i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3); - i2c_w(gspca_dev, PAS106_REG0e, &gain, 1, 1); - } -} - -#define BLIMIT(bright) \ - (u8)((bright > 0x1f) ? 0x1f : ((bright < 4) ? 3 : bright)) -#define LIMIT(color) \ - (u8)((color > 0xff) ? 0xff : ((color < 0) ? 0 : color)) - -static void do_autogain(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - __u8 luma; - __u8 luma_mean = 128; - __u8 luma_delta = 20; - __u8 spring = 4; - int Gbright; - __u8 r, g, b; - - if (sd->ag_cnt < 0) - return; - if (--sd->ag_cnt >= 0) - return; - sd->ag_cnt = AG_CNT_START; - - Gbright = Et_getgainG(gspca_dev); - reg_r(gspca_dev, ET_LUMA_CENTER, 4); - g = (gspca_dev->usb_buf[0] + gspca_dev->usb_buf[3]) >> 1; - r = gspca_dev->usb_buf[1]; - b = gspca_dev->usb_buf[2]; - r = ((r << 8) - (r << 4) - (r << 3)) >> 10; - b = ((b << 7) >> 10); - g = ((g << 9) + (g << 7) + (g << 5)) >> 10; - luma = LIMIT(r + g + b); - PDEBUG(D_FRAM, "Etoms luma G %d", luma); - if (luma < luma_mean - luma_delta || luma > luma_mean + luma_delta) { - Gbright += (luma_mean - luma) >> spring; - Gbright = BLIMIT(Gbright); - PDEBUG(D_FRAM, "Etoms Gbright %d", Gbright); - Et_setgainG(gspca_dev, (__u8) Gbright); - } -} - -#undef BLIMIT -#undef LIMIT - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - int seqframe; - - seqframe = data[0] & 0x3f; - len = (int) (((data[0] & 0xc0) << 2) | data[1]); - if (seqframe == 0x3f) { - PDEBUG(D_FRAM, - "header packet found datalength %d !!", len); - PDEBUG(D_FRAM, "G %d R %d G %d B %d", - data[2], data[3], data[4], data[5]); - data += 30; - /* don't change datalength as the chips provided it */ - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); - return; - } - if (len) { - data += 8; - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); - } else { /* Drop Packet */ - gspca_dev->last_packet_type = DISCARD_PACKET; - } -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_CONTRAST: - setcontrast(gspca_dev, ctrl->val); - break; - case V4L2_CID_SATURATION: - setcolors(gspca_dev, ctrl->val); - break; - case V4L2_CID_AUTOGAIN: - sd->autogain = ctrl->val; - setautogain(gspca_dev); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 4); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 1, 127, 1, 63); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 255, 1, 127); - if (sd->sensor == SENSOR_PAS106) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SATURATION, 0, 15, 1, 7); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, - .dq_callback = do_autogain, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106}, -#if !defined CONFIG_USB_ET61X251 && !defined CONFIG_USB_ET61X251_MODULE - {USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX}, -#endif - {} -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c deleted file mode 100644 index c8f2201cc35a..000000000000 --- a/drivers/media/video/gspca/finepix.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Fujifilm Finepix subdriver - * - * Copyright (C) 2008 Frank Zago - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "finepix" - -#include "gspca.h" - -MODULE_AUTHOR("Frank Zago <frank@zago.net>"); -MODULE_DESCRIPTION("Fujifilm FinePix USB V4L2 driver"); -MODULE_LICENSE("GPL"); - -/* Default timeout, in ms */ -#define FPIX_TIMEOUT 250 - -/* Maximum transfer size to use. The windows driver reads by chunks of - * 0x2000 bytes, so do the same. Note: reading more seems to work - * too. */ -#define FPIX_MAX_TRANSFER 0x2000 - -/* Structure to hold all of our device specific stuff */ -struct usb_fpix { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - struct work_struct work_struct; - struct workqueue_struct *work_thread; -}; - -/* Delay after which claim the next frame. If the delay is too small, - * the camera will return old frames. On the 4800Z, 20ms is bad, 25ms - * will fail every 4 or 5 frames, but 30ms is perfect. On the A210, - * 30ms is bad while 35ms is perfect. */ -#define NEXT_FRAME_DELAY 35 - -/* These cameras only support 320x200. */ -static const struct v4l2_pix_format fpix_mode[1] = { - { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0} -}; - -/* send a command to the webcam */ -static int command(struct gspca_dev *gspca_dev, - int order) /* 0: reset, 1: frame request */ -{ - static u8 order_values[2][12] = { - {0xc6, 0, 0, 0, 0, 0, 0, 0, 0x20, 0, 0, 0}, /* reset */ - {0xd3, 0, 0, 0, 0, 0, 0, 0x01, 0, 0, 0, 0}, /* fr req */ - }; - - memcpy(gspca_dev->usb_buf, order_values[order], 12); - return usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - USB_REQ_GET_STATUS, - USB_DIR_OUT | USB_TYPE_CLASS | - USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf, - 12, FPIX_TIMEOUT); -} - -/* workqueue */ -static void dostream(struct work_struct *work) -{ - struct usb_fpix *dev = container_of(work, struct usb_fpix, work_struct); - struct gspca_dev *gspca_dev = &dev->gspca_dev; - struct urb *urb = gspca_dev->urb[0]; - u8 *data = urb->transfer_buffer; - int ret = 0; - int len; - - /* synchronize with the main driver */ - mutex_lock(&gspca_dev->usb_lock); - mutex_unlock(&gspca_dev->usb_lock); - PDEBUG(D_STREAM, "dostream started"); - - /* loop reading a frame */ -again: - while (gspca_dev->dev && gspca_dev->streaming) { -#ifdef CONFIG_PM - if (gspca_dev->frozen) - break; -#endif - - /* request a frame */ - mutex_lock(&gspca_dev->usb_lock); - ret = command(gspca_dev, 1); - mutex_unlock(&gspca_dev->usb_lock); - if (ret < 0) - break; -#ifdef CONFIG_PM - if (gspca_dev->frozen) - break; -#endif - if (!gspca_dev->dev || !gspca_dev->streaming) - break; - - /* the frame comes in parts */ - for (;;) { - ret = usb_bulk_msg(gspca_dev->dev, - urb->pipe, - data, - FPIX_MAX_TRANSFER, - &len, FPIX_TIMEOUT); - if (ret < 0) { - /* Most of the time we get a timeout - * error. Just restart. */ - goto again; - } -#ifdef CONFIG_PM - if (gspca_dev->frozen) - goto out; -#endif - if (!gspca_dev->dev || !gspca_dev->streaming) - goto out; - if (len < FPIX_MAX_TRANSFER || - (data[len - 2] == 0xff && - data[len - 1] == 0xd9)) { - - /* If the result is less than what was asked - * for, then it's the end of the - * frame. Sometimes the jpeg is not complete, - * but there's nothing we can do. We also end - * here if the the jpeg ends right at the end - * of the frame. */ - gspca_frame_add(gspca_dev, LAST_PACKET, - data, len); - break; - } - - /* got a partial image */ - gspca_frame_add(gspca_dev, - gspca_dev->last_packet_type - == LAST_PACKET - ? FIRST_PACKET : INTER_PACKET, - data, len); - } - - /* We must wait before trying reading the next - * frame. If we don't, or if the delay is too short, - * the camera will disconnect. */ - msleep(NEXT_FRAME_DELAY); - } - -out: - PDEBUG(D_STREAM, "dostream stopped"); -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; - struct cam *cam = &gspca_dev->cam; - - cam->cam_mode = fpix_mode; - cam->nmodes = 1; - cam->bulk = 1; - cam->bulk_size = FPIX_MAX_TRANSFER; - - INIT_WORK(&dev->work_struct, dostream); - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - return 0; -} - -/* start the camera */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; - int ret, len; - - /* Init the device */ - ret = command(gspca_dev, 0); - if (ret < 0) { - pr_err("init failed %d\n", ret); - return ret; - } - - /* Read the result of the command. Ignore the result, for it - * varies with the device. */ - ret = usb_bulk_msg(gspca_dev->dev, - gspca_dev->urb[0]->pipe, - gspca_dev->urb[0]->transfer_buffer, - FPIX_MAX_TRANSFER, &len, - FPIX_TIMEOUT); - if (ret < 0) { - pr_err("usb_bulk_msg failed %d\n", ret); - return ret; - } - - /* Request a frame, but don't read it */ - ret = command(gspca_dev, 1); - if (ret < 0) { - pr_err("frame request failed %d\n", ret); - return ret; - } - - /* Again, reset bulk in endpoint */ - usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe); - - /* Start the workqueue function to do the streaming */ - dev->work_thread = create_singlethread_workqueue(MODULE_NAME); - queue_work(dev->work_thread, &dev->work_struct); - - return 0; -} - -/* called on streamoff with alt==0 and on disconnect */ -/* the usb_lock is held at entry - restore on exit */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; - - /* wait for the work queue to terminate */ - mutex_unlock(&gspca_dev->usb_lock); - destroy_workqueue(dev->work_thread); - mutex_lock(&gspca_dev->usb_lock); - dev->work_thread = NULL; -} - -/* Table of supported USB devices */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x04cb, 0x0104)}, - {USB_DEVICE(0x04cb, 0x0109)}, - {USB_DEVICE(0x04cb, 0x010b)}, - {USB_DEVICE(0x04cb, 0x010f)}, - {USB_DEVICE(0x04cb, 0x0111)}, - {USB_DEVICE(0x04cb, 0x0113)}, - {USB_DEVICE(0x04cb, 0x0115)}, - {USB_DEVICE(0x04cb, 0x0117)}, - {USB_DEVICE(0x04cb, 0x0119)}, - {USB_DEVICE(0x04cb, 0x011b)}, - {USB_DEVICE(0x04cb, 0x011d)}, - {USB_DEVICE(0x04cb, 0x0121)}, - {USB_DEVICE(0x04cb, 0x0123)}, - {USB_DEVICE(0x04cb, 0x0125)}, - {USB_DEVICE(0x04cb, 0x0127)}, - {USB_DEVICE(0x04cb, 0x0129)}, - {USB_DEVICE(0x04cb, 0x012b)}, - {USB_DEVICE(0x04cb, 0x012d)}, - {USB_DEVICE(0x04cb, 0x012f)}, - {USB_DEVICE(0x04cb, 0x0131)}, - {USB_DEVICE(0x04cb, 0x013b)}, - {USB_DEVICE(0x04cb, 0x013d)}, - {USB_DEVICE(0x04cb, 0x013f)}, - {} -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .start = sd_start, - .stop0 = sd_stop0, -}; - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, - &sd_desc, - sizeof(struct usb_fpix), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/gl860/Kconfig b/drivers/media/video/gspca/gl860/Kconfig deleted file mode 100644 index 22772f53ec7b..000000000000 --- a/drivers/media/video/gspca/gl860/Kconfig +++ /dev/null @@ -1,8 +0,0 @@ -config USB_GL860 - tristate "GL860 USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the GL860 chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_gl860. diff --git a/drivers/media/video/gspca/gl860/Makefile b/drivers/media/video/gspca/gl860/Makefile deleted file mode 100644 index 773ea3426561..000000000000 --- a/drivers/media/video/gspca/gl860/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -obj-$(CONFIG_USB_GL860) += gspca_gl860.o - -gspca_gl860-objs := gl860.o \ - gl860-mi1320.o \ - gl860-ov2640.o \ - gl860-ov9655.o \ - gl860-mi2020.o - -ccflags-y += -I$(srctree)/drivers/media/video/gspca - diff --git a/drivers/media/video/gspca/gl860/gl860-mi1320.c b/drivers/media/video/gspca/gl860/gl860-mi1320.c deleted file mode 100644 index b57160e04866..000000000000 --- a/drivers/media/video/gspca/gl860/gl860-mi1320.c +++ /dev/null @@ -1,536 +0,0 @@ -/* Subdriver for the GL860 chip with the MI1320 sensor - * Author Olivier LORIN from own logs - * - * 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 - * 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, see <http://www.gnu.org/licenses/>. - */ - -/* Sensor : MI1320 */ - -#include "gl860.h" - -static struct validx tbl_common[] = { - {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba51, 0x0066}, {0xba02, 0x00f1}, - {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1}, - {0xffff, 0xffff}, - {0xba00, 0x00f0}, {0xba02, 0x00f1}, {0xbafa, 0x0028}, {0xba02, 0x00f1}, - {0xba00, 0x00f0}, {0xba01, 0x00f1}, {0xbaf0, 0x0006}, {0xba0e, 0x00f1}, - {0xba70, 0x0006}, {0xba0e, 0x00f1}, - {0xffff, 0xffff}, - {0xba74, 0x0006}, {0xba0e, 0x00f1}, - {0xffff, 0xffff}, - {0x0061, 0x0000}, {0x0068, 0x000d}, -}; - -static struct validx tbl_init_at_startup[] = { - {0x0000, 0x0000}, {0x0010, 0x0010}, - {35, 0xffff}, - {0x0008, 0x00c0}, {0x0001, 0x00c1}, {0x0001, 0x00c2}, {0x0020, 0x0006}, - {0x006a, 0x000d}, -}; - -static struct validx tbl_sensor_settings_common[] = { - {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2}, {0x0040, 0x0000}, - {0x006a, 0x0007}, {0x006a, 0x000d}, {0x0063, 0x0006}, -}; -static struct validx tbl_sensor_settings_1280[] = { - {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba5a, 0x0066}, {0xba02, 0x00f1}, - {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xba20, 0x0065}, {0xba00, 0x00f1}, -}; -static struct validx tbl_sensor_settings_800[] = { - {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba5a, 0x0066}, {0xba02, 0x00f1}, - {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xba20, 0x0065}, {0xba00, 0x00f1}, -}; -static struct validx tbl_sensor_settings_640[] = { - {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1}, - {0xba51, 0x0066}, {0xba02, 0x00f1}, {0xba05, 0x0067}, {0xba05, 0x00f1}, - {0xba20, 0x0065}, {0xba00, 0x00f1}, -}; -static struct validx tbl_post_unset_alt[] = { - {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1}, - {0x0061, 0x0000}, {0x0068, 0x000d}, -}; - -static u8 *tbl_1280[] = { - "\x0d\x80\xf1\x08\x03\x04\xf1\x00" "\x04\x05\xf1\x02\x05\x00\xf1\xf1" - "\x06\x00\xf1\x0d\x20\x01\xf1\x00" "\x21\x84\xf1\x00\x0d\x00\xf1\x08" - "\xf0\x00\xf1\x01\x34\x00\xf1\x00" "\x9b\x43\xf1\x00\xa6\x05\xf1\x00" - "\xa9\x04\xf1\x00\xa1\x05\xf1\x00" "\xa4\x04\xf1\x00\xae\x0a\xf1\x08" - , - "\xf0\x00\xf1\x02\x3a\x05\xf1\xf1" "\x3c\x05\xf1\xf1\x59\x01\xf1\x47" - "\x5a\x01\xf1\x88\x5c\x0a\xf1\x06" "\x5d\x0e\xf1\x0a\x64\x5e\xf1\x1c" - "\xd2\x00\xf1\xcf\xcb\x00\xf1\x01" - , - "\xd3\x02\xd4\x28\xd5\x01\xd0\x02" "\xd1\x18\xd2\xc1" -}; - -static u8 *tbl_800[] = { - "\x0d\x80\xf1\x08\x03\x03\xf1\xc0" "\x04\x05\xf1\x02\x05\x00\xf1\xf1" - "\x06\x00\xf1\x0d\x20\x01\xf1\x00" "\x21\x84\xf1\x00\x0d\x00\xf1\x08" - "\xf0\x00\xf1\x01\x34\x00\xf1\x00" "\x9b\x43\xf1\x00\xa6\x05\xf1\x00" - "\xa9\x03\xf1\xc0\xa1\x03\xf1\x20" "\xa4\x02\xf1\x5a\xae\x0a\xf1\x08" - , - "\xf0\x00\xf1\x02\x3a\x05\xf1\xf1" "\x3c\x05\xf1\xf1\x59\x01\xf1\x47" - "\x5a\x01\xf1\x88\x5c\x0a\xf1\x06" "\x5d\x0e\xf1\x0a\x64\x5e\xf1\x1c" - "\xd2\x00\xf1\xcf\xcb\x00\xf1\x01" - , - "\xd3\x02\xd4\x18\xd5\x21\xd0\x02" "\xd1\x10\xd2\x59" -}; - -static u8 *tbl_640[] = { - "\x0d\x80\xf1\x08\x03\x04\xf1\x04" "\x04\x05\xf1\x02\x07\x01\xf1\x7c" - "\x08\x00\xf1\x0e\x21\x80\xf1\x00" "\x0d\x00\xf1\x08\xf0\x00\xf1\x01" - "\x34\x10\xf1\x10\x3a\x43\xf1\x00" "\xa6\x05\xf1\x02\xa9\x04\xf1\x04" - "\xa7\x02\xf1\x81\xaa\x01\xf1\xe2" "\xae\x0c\xf1\x09" - , - "\xf0\x00\xf1\x02\x39\x03\xf1\xfc" "\x3b\x04\xf1\x04\x57\x01\xf1\xb6" - "\x58\x02\xf1\x0d\x5c\x1f\xf1\x19" "\x5d\x24\xf1\x1e\x64\x5e\xf1\x1c" - "\xd2\x00\xf1\x00\xcb\x00\xf1\x01" - , - "\xd3\x02\xd4\x10\xd5\x81\xd0\x02" "\xd1\x08\xd2\xe1" -}; - -static s32 tbl_sat[] = {0x25, 0x1d, 0x15, 0x0d, 0x05, 0x4d, 0x55, 0x5d, 0x2d}; -static s32 tbl_bright[] = {0, 8, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70}; -static s32 tbl_backlight[] = {0x0e, 0x06, 0x02}; - -static s32 tbl_cntr1[] = { - 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, 0xe0, 0xf0}; -static s32 tbl_cntr2[] = { - 0x70, 0x68, 0x60, 0x58, 0x50, 0x48, 0x40, 0x38, 0x30, 0x20, 0x10}; - -static u8 dat_wbalNL[] = - "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x3b\x04\xf1\x2a\x47\x10\xf1\x10" - "\x9d\x3c\xf1\xae\xaf\x10\xf1\x00" "\xf0\x00\xf1\x02\x2f\x91\xf1\x20" - "\x9c\x91\xf1\x20\x37\x03\xf1\x00" "\x9d\xc5\xf1\x0f\xf0\x00\xf1\x00"; - -static u8 dat_wbalLL[] = - "\xf0\x00\xf1\x01\x05\x00\xf1\x0c" "\x3b\x04\xf1\x2a\x47\x40\xf1\x40" - "\x9d\x20\xf1\xae\xaf\x10\xf1\x00" "\xf0\x00\xf1\x02\x2f\xd1\xf1\x00" - "\x9c\xd1\xf1\x00\x37\x03\xf1\x00" "\x9d\xc5\xf1\x3f\xf0\x00\xf1\x00"; - -static u8 dat_wbalBL[] = - "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x47\x10\xf1\x30\x9d\x3c\xf1\xae" - "\xaf\x10\xf1\x00\xf0\x00\xf1\x02" "\x2f\x91\xf1\x20\x9c\x91\xf1\x20" - "\x37\x03\xf1\x00\x9d\xc5\xf1\x2f" "\xf0\x00\xf1\x00"; - -static u8 dat_hvflip1[] = {0xf0, 0x00, 0xf1, 0x00}; - -static u8 dat_common00[] = - "\x00\x01\x07\x6a\x06\x63\x0d\x6a" "\xc0\x00\x10\x10\xc1\x03\xc2\x42" - "\xd8\x04\x58\x00\x04\x02"; -static u8 dat_common01[] = - "\x0d\x00\xf1\x0b\x0d\x00\xf1\x08" "\x35\x00\xf1\x22\x68\x00\xf1\x5d" - "\xf0\x00\xf1\x01\x06\x70\xf1\x0e" "\xf0\x00\xf1\x02\xdd\x18\xf1\xe0"; -static u8 dat_common02[] = - "\x05\x01\xf1\x84\x06\x00\xf1\x44" "\x07\x00\xf1\xbe\x08\x00\xf1\x1e" - "\x20\x01\xf1\x03\x21\x84\xf1\x00" "\x22\x0d\xf1\x0f\x24\x80\xf1\x00" - "\x34\x18\xf1\x2d\x35\x00\xf1\x22" "\x43\x83\xf1\x83\x59\x00\xf1\xff"; -static u8 dat_common03[] = - "\xf0\x00\xf1\x02\x39\x06\xf1\x8c" "\x3a\x06\xf1\x8c\x3b\x03\xf1\xda" - "\x3c\x05\xf1\x30\x57\x01\xf1\x0c" "\x58\x01\xf1\x42\x59\x01\xf1\x0c" - "\x5a\x01\xf1\x42\x5c\x13\xf1\x0e" "\x5d\x17\xf1\x12\x64\x1e\xf1\x1c"; -static u8 dat_common04[] = - "\xf0\x00\xf1\x02\x24\x5f\xf1\x20" "\x28\xea\xf1\x02\x5f\x41\xf1\x43"; -static u8 dat_common05[] = - "\x02\x00\xf1\xee\x03\x29\xf1\x1a" "\x04\x02\xf1\xa4\x09\x00\xf1\x68" - "\x0a\x00\xf1\x2a\x0b\x00\xf1\x04" "\x0c\x00\xf1\x93\x0d\x00\xf1\x82" - "\x0e\x00\xf1\x40\x0f\x00\xf1\x5f" "\x10\x00\xf1\x4e\x11\x00\xf1\x5b"; -static u8 dat_common06[] = - "\x15\x00\xf1\xc9\x16\x00\xf1\x5e" "\x17\x00\xf1\x9d\x18\x00\xf1\x06" - "\x19\x00\xf1\x89\x1a\x00\xf1\x12" "\x1b\x00\xf1\xa1\x1c\x00\xf1\xe4" - "\x1d\x00\xf1\x7a\x1e\x00\xf1\x64" "\xf6\x00\xf1\x5f"; -static u8 dat_common07[] = - "\xf0\x00\xf1\x01\x53\x09\xf1\x03" "\x54\x3d\xf1\x1c\x55\x99\xf1\x72" - "\x56\xc1\xf1\xb1\x57\xd8\xf1\xce" "\x58\xe0\xf1\x00\xdc\x0a\xf1\x03" - "\xdd\x45\xf1\x20\xde\xae\xf1\x82" "\xdf\xdc\xf1\xc9\xe0\xf6\xf1\xea" - "\xe1\xff\xf1\x00"; -static u8 dat_common08[] = - "\xf0\x00\xf1\x01\x80\x00\xf1\x06" "\x81\xf6\xf1\x08\x82\xfb\xf1\xf7" - "\x83\x00\xf1\xfe\xb6\x07\xf1\x03" "\xb7\x18\xf1\x0c\x84\xfb\xf1\x06" - "\x85\xfb\xf1\xf9\x86\x00\xf1\xff" "\xb8\x07\xf1\x04\xb9\x16\xf1\x0a"; -static u8 dat_common09[] = - "\x87\xfa\xf1\x05\x88\xfc\xf1\xf9" "\x89\x00\xf1\xff\xba\x06\xf1\x03" - "\xbb\x17\xf1\x09\x8a\xe8\xf1\x14" "\x8b\xf7\xf1\xf0\x8c\xfd\xf1\xfa" - "\x8d\x00\xf1\x00\xbc\x05\xf1\x01" "\xbd\x0c\xf1\x08\xbe\x00\xf1\x14"; -static u8 dat_common10[] = - "\x8e\xea\xf1\x13\x8f\xf7\xf1\xf2" "\x90\xfd\xf1\xfa\x91\x00\xf1\x00" - "\xbf\x05\xf1\x01\xc0\x0a\xf1\x08" "\xc1\x00\xf1\x0c\x92\xed\xf1\x0f" - "\x93\xf9\xf1\xf4\x94\xfe\xf1\xfb" "\x95\x00\xf1\x00\xc2\x04\xf1\x01" - "\xc3\x0a\xf1\x07\xc4\x00\xf1\x10"; -static u8 dat_common11[] = - "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x25\x00\xf1\x55\x34\x10\xf1\x10" - "\x35\xf0\xf1\x10\x3a\x02\xf1\x03" "\x3b\x04\xf1\x2a\x9b\x43\xf1\x00" - "\xa4\x03\xf1\xc0\xa7\x02\xf1\x81"; - -static int mi1320_init_at_startup(struct gspca_dev *gspca_dev); -static int mi1320_configure_alt(struct gspca_dev *gspca_dev); -static int mi1320_init_pre_alt(struct gspca_dev *gspca_dev); -static int mi1320_init_post_alt(struct gspca_dev *gspca_dev); -static void mi1320_post_unset_alt(struct gspca_dev *gspca_dev); -static int mi1320_sensor_settings(struct gspca_dev *gspca_dev); -static int mi1320_camera_settings(struct gspca_dev *gspca_dev); -/*==========================================================================*/ - -void mi1320_init_settings(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->vcur.backlight = 0; - sd->vcur.brightness = 0; - sd->vcur.sharpness = 6; - sd->vcur.contrast = 10; - sd->vcur.gamma = 20; - sd->vcur.hue = 0; - sd->vcur.saturation = 6; - sd->vcur.whitebal = 0; - sd->vcur.mirror = 0; - sd->vcur.flip = 0; - sd->vcur.AC50Hz = 1; - - sd->vmax.backlight = 2; - sd->vmax.brightness = 8; - sd->vmax.sharpness = 7; - sd->vmax.contrast = 0; /* 10 but not working with this driver */ - sd->vmax.gamma = 40; - sd->vmax.hue = 5 + 1; - sd->vmax.saturation = 8; - sd->vmax.whitebal = 2; - sd->vmax.mirror = 1; - sd->vmax.flip = 1; - sd->vmax.AC50Hz = 1; - - sd->dev_camera_settings = mi1320_camera_settings; - sd->dev_init_at_startup = mi1320_init_at_startup; - sd->dev_configure_alt = mi1320_configure_alt; - sd->dev_init_pre_alt = mi1320_init_pre_alt; - sd->dev_post_unset_alt = mi1320_post_unset_alt; -} - -/*==========================================================================*/ - -static void common(struct gspca_dev *gspca_dev) -{ - s32 n; /* reserved for FETCH functions */ - - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 22, dat_common00); - ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 32, dat_common01); - n = fetch_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common)); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common02); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common03); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 16, dat_common04); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common05); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 44, dat_common06); - keep_on_fetching_validx(gspca_dev, tbl_common, - ARRAY_SIZE(tbl_common), n); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 52, dat_common07); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common08); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common09); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 56, dat_common10); - keep_on_fetching_validx(gspca_dev, tbl_common, - ARRAY_SIZE(tbl_common), n); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, dat_common11); - keep_on_fetching_validx(gspca_dev, tbl_common, - ARRAY_SIZE(tbl_common), n); -} - -static int mi1320_init_at_startup(struct gspca_dev *gspca_dev) -{ - fetch_validx(gspca_dev, tbl_init_at_startup, - ARRAY_SIZE(tbl_init_at_startup)); - - common(gspca_dev); - -/* ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */ - - return 0; -} - -static int mi1320_init_pre_alt(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->mirrorMask = 0; - - sd->vold.backlight = -1; - sd->vold.brightness = -1; - sd->vold.sharpness = -1; - sd->vold.contrast = -1; - sd->vold.saturation = -1; - sd->vold.gamma = -1; - sd->vold.hue = -1; - sd->vold.whitebal = -1; - sd->vold.mirror = -1; - sd->vold.flip = -1; - sd->vold.AC50Hz = -1; - - common(gspca_dev); - - mi1320_sensor_settings(gspca_dev); - - mi1320_init_post_alt(gspca_dev); - - return 0; -} - -static int mi1320_init_post_alt(struct gspca_dev *gspca_dev) -{ - mi1320_camera_settings(gspca_dev); - - return 0; -} - -static int mi1320_sensor_settings(struct gspca_dev *gspca_dev) -{ - s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; - - ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL); - - fetch_validx(gspca_dev, tbl_sensor_settings_common, - ARRAY_SIZE(tbl_sensor_settings_common)); - - switch (reso) { - case IMAGE_1280: - fetch_validx(gspca_dev, tbl_sensor_settings_1280, - ARRAY_SIZE(tbl_sensor_settings_1280)); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 64, tbl_1280[0]); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_1280[1]); - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_1280[2]); - break; - - case IMAGE_800: - fetch_validx(gspca_dev, tbl_sensor_settings_800, - ARRAY_SIZE(tbl_sensor_settings_800)); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 64, tbl_800[0]); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_800[1]); - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_800[2]); - break; - - default: - fetch_validx(gspca_dev, tbl_sensor_settings_640, - ARRAY_SIZE(tbl_sensor_settings_640)); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 60, tbl_640[0]); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_640[1]); - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_640[2]); - break; - } - return 0; -} - -static int mi1320_configure_alt(struct gspca_dev *gspca_dev) -{ - s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; - - switch (reso) { - case IMAGE_640: - gspca_dev->alt = 3 + 1; - break; - - case IMAGE_800: - case IMAGE_1280: - gspca_dev->alt = 1 + 1; - break; - } - return 0; -} - -static int mi1320_camera_settings(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - s32 backlight = sd->vcur.backlight; - s32 bright = sd->vcur.brightness; - s32 sharp = sd->vcur.sharpness; - s32 cntr = sd->vcur.contrast; - s32 gam = sd->vcur.gamma; - s32 hue = sd->vcur.hue; - s32 sat = sd->vcur.saturation; - s32 wbal = sd->vcur.whitebal; - s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0); - s32 flip = (((sd->vcur.flip > 0) ^ sd->mirrorMask) > 0); - s32 freq = (sd->vcur.AC50Hz > 0); - s32 i; - - if (freq != sd->vold.AC50Hz) { - sd->vold.AC50Hz = freq; - - freq = 2 * (freq == 0); - ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba02, 0x00f1, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba00 , 0x005b, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba01 + freq, 0x00f1, 0, NULL); - } - - if (wbal != sd->vold.whitebal) { - sd->vold.whitebal = wbal; - if (wbal < 0 || wbal > sd->vmax.whitebal) - wbal = 0; - - for (i = 0; i < 2; i++) { - if (wbal == 0) { /* Normal light */ - ctrl_out(gspca_dev, 0x40, 1, - 0x0010, 0x0010, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, - 0x0003, 0x00c1, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, - 0x0042, 0x00c2, 0, NULL); - ctrl_out(gspca_dev, 0x40, 3, - 0xba00, 0x0200, 48, dat_wbalNL); - } - - if (wbal == 1) { /* Low light */ - ctrl_out(gspca_dev, 0x40, 1, - 0x0010, 0x0010, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, - 0x0004, 0x00c1, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, - 0x0043, 0x00c2, 0, NULL); - ctrl_out(gspca_dev, 0x40, 3, - 0xba00, 0x0200, 48, dat_wbalLL); - } - - if (wbal == 2) { /* Back light */ - ctrl_out(gspca_dev, 0x40, 1, - 0x0010, 0x0010, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, - 0x0003, 0x00c1, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, - 0x0042, 0x00c2, 0, NULL); - ctrl_out(gspca_dev, 0x40, 3, - 0xba00, 0x0200, 44, dat_wbalBL); - } - } - } - - if (bright != sd->vold.brightness) { - sd->vold.brightness = bright; - if (bright < 0 || bright > sd->vmax.brightness) - bright = 0; - - bright = tbl_bright[bright]; - ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba00 + bright, 0x0034, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba00 + bright, 0x00f1, 0, NULL); - } - - if (sat != sd->vold.saturation) { - sd->vold.saturation = sat; - if (sat < 0 || sat > sd->vmax.saturation) - sat = 0; - - sat = tbl_sat[sat]; - ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba00 , 0x0025, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba00 + sat, 0x00f1, 0, NULL); - } - - if (sharp != sd->vold.sharpness) { - sd->vold.sharpness = sharp; - if (sharp < 0 || sharp > sd->vmax.sharpness) - sharp = 0; - - ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba00 , 0x0005, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba00 + sharp, 0x00f1, 0, NULL); - } - - if (hue != sd->vold.hue) { - /* 0=normal 1=NB 2="sepia" 3=negative 4=other 5=other2 */ - if (hue < 0 || hue > sd->vmax.hue) - hue = 0; - if (hue == sd->vmax.hue) - sd->swapRB = 1; - else - sd->swapRB = 0; - - ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba70, 0x00e2, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba00 + hue * (hue < 6), 0x00f1, - 0, NULL); - } - - if (backlight != sd->vold.backlight) { - sd->vold.backlight = backlight; - if (backlight < 0 || backlight > sd->vmax.backlight) - backlight = 0; - - backlight = tbl_backlight[backlight]; - for (i = 0; i < 2; i++) { - ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba74, 0x0006, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba80 + backlight, 0x00f1, - 0, NULL); - } - } - - if (hue != sd->vold.hue) { - sd->vold.hue = hue; - - ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba70, 0x00e2, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba00 + hue * (hue < 6), 0x00f1, - 0, NULL); - } - - if (mirror != sd->vold.mirror || flip != sd->vold.flip) { - u8 dat_hvflip2[4] = {0x20, 0x01, 0xf1, 0x00}; - sd->vold.mirror = mirror; - sd->vold.flip = flip; - - dat_hvflip2[3] = flip + 2 * mirror; - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 4, dat_hvflip1); - ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 4, dat_hvflip2); - } - - if (gam != sd->vold.gamma) { - sd->vold.gamma = gam; - if (gam < 0 || gam > sd->vmax.gamma) - gam = 0; - - gam = 2 * gam; - ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba04 , 0x003b, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba02 + gam, 0x00f1, 0, NULL); - } - - if (cntr != sd->vold.contrast) { - sd->vold.contrast = cntr; - if (cntr < 0 || cntr > sd->vmax.contrast) - cntr = 0; - - ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba00 + tbl_cntr1[cntr], 0x0035, - 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0xba00 + tbl_cntr2[cntr], 0x00f1, - 0, NULL); - } - - return 0; -} - -static void mi1320_post_unset_alt(struct gspca_dev *gspca_dev) -{ - ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL); - - fetch_validx(gspca_dev, tbl_post_unset_alt, - ARRAY_SIZE(tbl_post_unset_alt)); -} diff --git a/drivers/media/video/gspca/gl860/gl860-mi2020.c b/drivers/media/video/gspca/gl860/gl860-mi2020.c deleted file mode 100644 index 2edda6b7d653..000000000000 --- a/drivers/media/video/gspca/gl860/gl860-mi2020.c +++ /dev/null @@ -1,733 +0,0 @@ -/* Subdriver for the GL860 chip with the MI2020 sensor - * Author Olivier LORIN, from logs by Iceman/Soro2005 + Fret_saw/Hulkie/Tricid - * with the help of Kytrix/BUGabundo/Blazercist. - * Driver achieved thanks to a webcam gift by Kytrix. - * - * 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 - * 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, see <http://www.gnu.org/licenses/>. - */ - -/* Sensor : MI2020 */ - -#include "gl860.h" - -static u8 dat_wbal1[] = {0x8c, 0xa2, 0x0c}; - -static u8 dat_bright1[] = {0x8c, 0xa2, 0x06}; -static u8 dat_bright3[] = {0x8c, 0xa1, 0x02}; -static u8 dat_bright4[] = {0x90, 0x00, 0x0f}; -static u8 dat_bright5[] = {0x8c, 0xa1, 0x03}; -static u8 dat_bright6[] = {0x90, 0x00, 0x05}; - -static u8 dat_hvflip1[] = {0x8c, 0x27, 0x19}; -static u8 dat_hvflip3[] = {0x8c, 0x27, 0x3b}; -static u8 dat_hvflip5[] = {0x8c, 0xa1, 0x03}; -static u8 dat_hvflip6[] = {0x90, 0x00, 0x06}; - -static struct idxdata tbl_middle_hvflip_low[] = { - {0x33, "\x90\x00\x06"}, - {6, "\xff\xff\xff"}, - {0x33, "\x90\x00\x06"}, - {6, "\xff\xff\xff"}, - {0x33, "\x90\x00\x06"}, - {6, "\xff\xff\xff"}, - {0x33, "\x90\x00\x06"}, - {6, "\xff\xff\xff"}, -}; - -static struct idxdata tbl_middle_hvflip_big[] = { - {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa1\x20"}, - {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"}, - {102, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa1\x20"}, - {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"}, -}; - -static struct idxdata tbl_end_hvflip[] = { - {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"}, - {6, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"}, - {6, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"}, - {6, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"}, -}; - -static u8 dat_freq1[] = { 0x8c, 0xa4, 0x04 }; - -static u8 dat_multi5[] = { 0x8c, 0xa1, 0x03 }; -static u8 dat_multi6[] = { 0x90, 0x00, 0x05 }; - -static struct validx tbl_init_at_startup[] = { - {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1}, - {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d}, - {53, 0xffff}, - {0x0040, 0x0000}, {0x0063, 0x0006}, -}; - -static struct validx tbl_common_0B[] = { - {0x0002, 0x0004}, {0x006a, 0x0007}, {0x00ef, 0x0006}, {0x006a, 0x000d}, - {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2}, - {0x0004, 0x00d8}, {0x0000, 0x0058}, {0x0041, 0x0000}, -}; - -static struct idxdata tbl_common_3B[] = { - {0x33, "\x86\x25\x01"}, {0x33, "\x86\x25\x00"}, - {2, "\xff\xff\xff"}, - {0x30, "\x1a\x0a\xcc"}, {0x32, "\x02\x00\x08"}, {0x33, "\xf4\x03\x1d"}, - {6, "\xff\xff\xff"}, /* 12 */ - {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"}, - {2, "\xff\xff\xff"}, /* - */ - {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\x22\x23"}, - {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa2\x0f"}, {0x33, "\x90\x00\x0d"}, - {0x33, "\x8c\xa2\x10"}, {0x33, "\x90\x00\x0b"}, {0x33, "\x8c\xa2\x11"}, - {0x33, "\x90\x00\x07"}, {0x33, "\xf4\x03\x1d"}, {0x35, "\xa2\x00\xe2"}, - {0x33, "\x8c\xab\x05"}, {0x33, "\x90\x00\x01"}, {0x32, "\x6e\x00\x86"}, - {0x32, "\x70\x0f\xaa"}, {0x32, "\x72\x0f\xe4"}, {0x33, "\x8c\xa3\x4a"}, - {0x33, "\x90\x00\x5a"}, {0x33, "\x8c\xa3\x4b"}, {0x33, "\x90\x00\xa6"}, - {0x33, "\x8c\xa3\x61"}, {0x33, "\x90\x00\xc8"}, {0x33, "\x8c\xa3\x62"}, - {0x33, "\x90\x00\xe1"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"}, - {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"}, - {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"}, - {0x34, "\xde\x01\x5b"}, {0x34, "\xe6\x01\x13"}, {0x34, "\xee\x0b\xf0"}, - {0x34, "\xf6\x0b\xa4"}, {0x35, "\x00\xf6\xe7"}, {0x35, "\x08\x0d\xfd"}, - {0x35, "\x10\x25\x63"}, {0x35, "\x18\x35\x6c"}, {0x35, "\x20\x42\x7e"}, - {0x35, "\x28\x19\x44"}, {0x35, "\x30\x39\xd4"}, {0x35, "\x38\xf5\xa8"}, - {0x35, "\x4c\x07\x90"}, {0x35, "\x44\x07\xb8"}, {0x35, "\x5c\x06\x88"}, - {0x35, "\x54\x07\xff"}, {0x34, "\xe0\x01\x52"}, {0x34, "\xe8\x00\xcc"}, - {0x34, "\xf0\x0d\x83"}, {0x34, "\xf8\x0c\xb3"}, {0x35, "\x02\xfe\xba"}, - {0x35, "\x0a\x04\xe0"}, {0x35, "\x12\x1c\x63"}, {0x35, "\x1a\x2b\x5a"}, - {0x35, "\x22\x32\x5e"}, {0x35, "\x2a\x0d\x28"}, {0x35, "\x32\x2c\x02"}, - {0x35, "\x3a\xf4\xfa"}, {0x35, "\x4e\x07\xef"}, {0x35, "\x46\x07\x88"}, - {0x35, "\x5e\x07\xc1"}, {0x35, "\x56\x04\x64"}, {0x34, "\xe4\x01\x15"}, - {0x34, "\xec\x00\x82"}, {0x34, "\xf4\x0c\xce"}, {0x34, "\xfc\x0c\xba"}, - {0x35, "\x06\x1f\x02"}, {0x35, "\x0e\x02\xe3"}, {0x35, "\x16\x1a\x50"}, - {0x35, "\x1e\x24\x39"}, {0x35, "\x26\x23\x4c"}, {0x35, "\x2e\xf9\x1b"}, - {0x35, "\x36\x23\x19"}, {0x35, "\x3e\x12\x08"}, {0x35, "\x52\x07\x22"}, - {0x35, "\x4a\x03\xd3"}, {0x35, "\x62\x06\x54"}, {0x35, "\x5a\x04\x5d"}, - {0x34, "\xe2\x01\x04"}, {0x34, "\xea\x00\xa0"}, {0x34, "\xf2\x0c\xbc"}, - {0x34, "\xfa\x0c\x5b"}, {0x35, "\x04\x17\xf2"}, {0x35, "\x0c\x02\x08"}, - {0x35, "\x14\x28\x43"}, {0x35, "\x1c\x28\x62"}, {0x35, "\x24\x2b\x60"}, - {0x35, "\x2c\x07\x33"}, {0x35, "\x34\x1f\xb0"}, {0x35, "\x3c\xed\xcd"}, - {0x35, "\x50\x00\x06"}, {0x35, "\x48\x07\xff"}, {0x35, "\x60\x05\x89"}, - {0x35, "\x58\x07\xff"}, {0x35, "\x40\x00\xa0"}, {0x35, "\x42\x00\x00"}, - {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"}, - {0x33, "\x78\x00\x00"}, - {2, "\xff\xff\xff"}, - {0x35, "\xb8\x1f\x20"}, {0x33, "\x8c\xa2\x06"}, {0x33, "\x90\x00\x10"}, - {0x33, "\x8c\xa2\x07"}, {0x33, "\x90\x00\x08"}, {0x33, "\x8c\xa2\x42"}, - {0x33, "\x90\x00\x0b"}, {0x33, "\x8c\xa2\x4a"}, {0x33, "\x90\x00\x8c"}, - {0x35, "\xba\xfa\x08"}, {0x33, "\x8c\xa2\x02"}, {0x33, "\x90\x00\x22"}, - {0x33, "\x8c\xa2\x03"}, {0x33, "\x90\x00\xbb"}, {0x33, "\x8c\xa4\x04"}, - {0x33, "\x90\x00\x80"}, {0x33, "\x8c\xa7\x9d"}, {0x33, "\x90\x00\x00"}, - {0x33, "\x8c\xa7\x9e"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa2\x0c"}, - {0x33, "\x90\x00\x17"}, {0x33, "\x8c\xa2\x15"}, {0x33, "\x90\x00\x04"}, - {0x33, "\x8c\xa2\x14"}, {0x33, "\x90\x00\x20"}, {0x33, "\x8c\xa1\x03"}, - {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x17"}, {0x33, "\x90\x21\x11"}, - {0x33, "\x8c\x27\x1b"}, {0x33, "\x90\x02\x4f"}, {0x33, "\x8c\x27\x25"}, - {0x33, "\x90\x06\x0f"}, {0x33, "\x8c\x27\x39"}, {0x33, "\x90\x21\x11"}, - {0x33, "\x8c\x27\x3d"}, {0x33, "\x90\x01\x20"}, {0x33, "\x8c\x27\x47"}, - {0x33, "\x90\x09\x4c"}, {0x33, "\x8c\x27\x03"}, {0x33, "\x90\x02\x84"}, - {0x33, "\x8c\x27\x05"}, {0x33, "\x90\x01\xe2"}, {0x33, "\x8c\x27\x07"}, - {0x33, "\x90\x06\x40"}, {0x33, "\x8c\x27\x09"}, {0x33, "\x90\x04\xb0"}, - {0x33, "\x8c\x27\x0d"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x0f"}, - {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x11"}, {0x33, "\x90\x04\xbd"}, - {0x33, "\x8c\x27\x13"}, {0x33, "\x90\x06\x4d"}, {0x33, "\x8c\x27\x15"}, - {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x17"}, {0x33, "\x90\x21\x11"}, - {0x33, "\x8c\x27\x19"}, {0x33, "\x90\x04\x6c"}, {0x33, "\x8c\x27\x1b"}, - {0x33, "\x90\x02\x4f"}, {0x33, "\x8c\x27\x1d"}, {0x33, "\x90\x01\x02"}, - {0x33, "\x8c\x27\x1f"}, {0x33, "\x90\x02\x79"}, {0x33, "\x8c\x27\x21"}, - {0x33, "\x90\x01\x55"}, {0x33, "\x8c\x27\x23"}, {0x33, "\x90\x02\x85"}, - {0x33, "\x8c\x27\x25"}, {0x33, "\x90\x06\x0f"}, {0x33, "\x8c\x27\x27"}, - {0x33, "\x90\x20\x20"}, {0x33, "\x8c\x27\x29"}, {0x33, "\x90\x20\x20"}, - {0x33, "\x8c\x27\x2b"}, {0x33, "\x90\x10\x20"}, {0x33, "\x8c\x27\x2d"}, - {0x33, "\x90\x20\x07"}, {0x33, "\x8c\x27\x2f"}, {0x33, "\x90\x00\x04"}, - {0x33, "\x8c\x27\x31"}, {0x33, "\x90\x00\x04"}, {0x33, "\x8c\x27\x33"}, - {0x33, "\x90\x04\xbb"}, {0x33, "\x8c\x27\x35"}, {0x33, "\x90\x06\x4b"}, - {0x33, "\x8c\x27\x37"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x39"}, - {0x33, "\x90\x21\x11"}, {0x33, "\x8c\x27\x3b"}, {0x33, "\x90\x00\x24"}, - {0x33, "\x8c\x27\x3d"}, {0x33, "\x90\x01\x20"}, {0x33, "\x8c\x27\x41"}, - {0x33, "\x90\x01\x69"}, {0x33, "\x8c\x27\x45"}, {0x33, "\x90\x04\xed"}, - {0x33, "\x8c\x27\x47"}, {0x33, "\x90\x09\x4c"}, {0x33, "\x8c\x27\x51"}, - {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x53"}, {0x33, "\x90\x03\x20"}, - {0x33, "\x8c\x27\x55"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x57"}, - {0x33, "\x90\x02\x58"}, {0x33, "\x8c\x27\x5f"}, {0x33, "\x90\x00\x00"}, - {0x33, "\x8c\x27\x61"}, {0x33, "\x90\x06\x40"}, {0x33, "\x8c\x27\x63"}, - {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x65"}, {0x33, "\x90\x04\xb0"}, - {0x33, "\x8c\x22\x2e"}, {0x33, "\x90\x00\xa1"}, {0x33, "\x8c\xa4\x08"}, - {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x21"}, - {0x33, "\x8c\xa4\x0a"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\xa4\x0b"}, - {0x33, "\x90\x00\x27"}, {0x33, "\x8c\x24\x11"}, {0x33, "\x90\x00\xa1"}, - {0x33, "\x8c\x24\x13"}, {0x33, "\x90\x00\xc1"}, {0x33, "\x8c\x24\x15"}, - {0x33, "\x90\x00\x6a"}, {0x33, "\x8c\x24\x17"}, {0x33, "\x90\x00\x80"}, - {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, - {2, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, - {3, "\xff\xff\xff"}, -}; - -static struct idxdata tbl_init_post_alt_low1[] = { - {0x33, "\x8c\x27\x15"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\x22\x2e"}, - {0x33, "\x90\x00\x81"}, {0x33, "\x8c\xa4\x08"}, {0x33, "\x90\x00\x17"}, - {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x1a"}, {0x33, "\x8c\xa4\x0a"}, - {0x33, "\x90\x00\x1d"}, {0x33, "\x8c\xa4\x0b"}, {0x33, "\x90\x00\x20"}, - {0x33, "\x8c\x24\x11"}, {0x33, "\x90\x00\x81"}, {0x33, "\x8c\x24\x13"}, - {0x33, "\x90\x00\x9b"}, -}; - -static struct idxdata tbl_init_post_alt_low2[] = { - {0x33, "\x8c\x27\x03"}, {0x33, "\x90\x03\x24"}, {0x33, "\x8c\x27\x05"}, - {0x33, "\x90\x02\x58"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, - {2, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, - {2, "\xff\xff\xff"}, -}; - -static struct idxdata tbl_init_post_alt_low3[] = { - {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"}, - {2, "\xff\xff\xff"}, - {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x20"}, - {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x01"}, - {0x33, "\x2e\x01\x00"}, {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"}, - {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x95"}, {0x33, "\x90\x01\x00"}, - {2, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x03"}, - {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"}, - {2, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"}, - {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"}, - {2, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, - {2, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, - {2, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, - {2, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, -}; - -static struct idxdata tbl_init_post_alt_big[] = { - {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, - {2, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, - {2, "\xff\xff\xff"}, - {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"}, - {2, "\xff\xff\xff"}, - {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x03"}, - {0x33, "\x90\x00\x05"}, - {2, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, - {2, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"}, - {2, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, {0x33, "\x8c\xa1\x20"}, - {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x30"}, {0x33, "\x90\x00\x03"}, - {0x33, "\x8c\xa1\x31"}, {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa1\x32"}, - {0x33, "\x90\x00\x03"}, {0x33, "\x8c\xa1\x34"}, {0x33, "\x90\x00\x03"}, - {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x02"}, {0x33, "\x2e\x01\x00"}, - {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"}, - {0x33, "\x8c\x27\x97"}, {0x33, "\x90\x01\x00"}, - {51, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"}, - {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"}, - {51, "\xff\xff\xff"}, - {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x03"}, - {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"}, - {51, "\xff\xff\xff"}, -}; - -static struct idxdata tbl_init_post_alt_3B[] = { - {0x32, "\x10\x01\xf8"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"}, - {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"}, - {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"}, - {0x34, "\xde\x01\x5b"}, {0x34, "\xe6\x01\x13"}, {0x34, "\xee\x0b\xf0"}, - {0x34, "\xf6\x0b\xa4"}, {0x35, "\x00\xf6\xe7"}, {0x35, "\x08\x0d\xfd"}, - {0x35, "\x10\x25\x63"}, {0x35, "\x18\x35\x6c"}, {0x35, "\x20\x42\x7e"}, - {0x35, "\x28\x19\x44"}, {0x35, "\x30\x39\xd4"}, {0x35, "\x38\xf5\xa8"}, - {0x35, "\x4c\x07\x90"}, {0x35, "\x44\x07\xb8"}, {0x35, "\x5c\x06\x88"}, - {0x35, "\x54\x07\xff"}, {0x34, "\xe0\x01\x52"}, {0x34, "\xe8\x00\xcc"}, - {0x34, "\xf0\x0d\x83"}, {0x34, "\xf8\x0c\xb3"}, {0x35, "\x02\xfe\xba"}, - {0x35, "\x0a\x04\xe0"}, {0x35, "\x12\x1c\x63"}, {0x35, "\x1a\x2b\x5a"}, - {0x35, "\x22\x32\x5e"}, {0x35, "\x2a\x0d\x28"}, {0x35, "\x32\x2c\x02"}, - {0x35, "\x3a\xf4\xfa"}, {0x35, "\x4e\x07\xef"}, {0x35, "\x46\x07\x88"}, - {0x35, "\x5e\x07\xc1"}, {0x35, "\x56\x04\x64"}, {0x34, "\xe4\x01\x15"}, - {0x34, "\xec\x00\x82"}, {0x34, "\xf4\x0c\xce"}, {0x34, "\xfc\x0c\xba"}, - {0x35, "\x06\x1f\x02"}, {0x35, "\x0e\x02\xe3"}, {0x35, "\x16\x1a\x50"}, - {0x35, "\x1e\x24\x39"}, {0x35, "\x26\x23\x4c"}, {0x35, "\x2e\xf9\x1b"}, - {0x35, "\x36\x23\x19"}, {0x35, "\x3e\x12\x08"}, {0x35, "\x52\x07\x22"}, - {0x35, "\x4a\x03\xd3"}, {0x35, "\x62\x06\x54"}, {0x35, "\x5a\x04\x5d"}, - {0x34, "\xe2\x01\x04"}, {0x34, "\xea\x00\xa0"}, {0x34, "\xf2\x0c\xbc"}, - {0x34, "\xfa\x0c\x5b"}, {0x35, "\x04\x17\xf2"}, {0x35, "\x0c\x02\x08"}, - {0x35, "\x14\x28\x43"}, {0x35, "\x1c\x28\x62"}, {0x35, "\x24\x2b\x60"}, - {0x35, "\x2c\x07\x33"}, {0x35, "\x34\x1f\xb0"}, {0x35, "\x3c\xed\xcd"}, - {0x35, "\x50\x00\x06"}, {0x35, "\x48\x07\xff"}, {0x35, "\x60\x05\x89"}, - {0x35, "\x58\x07\xff"}, {0x35, "\x40\x00\xa0"}, {0x35, "\x42\x00\x00"}, - {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"}, -}; - -static u8 *dat_640 = "\xd0\x02\xd1\x08\xd2\xe1\xd3\x02\xd4\x10\xd5\x81"; -static u8 *dat_800 = "\xd0\x02\xd1\x10\xd2\x57\xd3\x02\xd4\x18\xd5\x21"; -static u8 *dat_1280 = "\xd0\x02\xd1\x20\xd2\x01\xd3\x02\xd4\x28\xd5\x01"; -static u8 *dat_1600 = "\xd0\x02\xd1\x20\xd2\xaf\xd3\x02\xd4\x30\xd5\x41"; - -static int mi2020_init_at_startup(struct gspca_dev *gspca_dev); -static int mi2020_configure_alt(struct gspca_dev *gspca_dev); -static int mi2020_init_pre_alt(struct gspca_dev *gspca_dev); -static int mi2020_init_post_alt(struct gspca_dev *gspca_dev); -static void mi2020_post_unset_alt(struct gspca_dev *gspca_dev); -static int mi2020_camera_settings(struct gspca_dev *gspca_dev); -/*==========================================================================*/ - -void mi2020_init_settings(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->vcur.backlight = 0; - sd->vcur.brightness = 70; - sd->vcur.sharpness = 20; - sd->vcur.contrast = 0; - sd->vcur.gamma = 0; - sd->vcur.hue = 0; - sd->vcur.saturation = 60; - sd->vcur.whitebal = 0; /* 50, not done by hardware */ - sd->vcur.mirror = 0; - sd->vcur.flip = 0; - sd->vcur.AC50Hz = 1; - - sd->vmax.backlight = 64; - sd->vmax.brightness = 128; - sd->vmax.sharpness = 40; - sd->vmax.contrast = 3; - sd->vmax.gamma = 2; - sd->vmax.hue = 0 + 1; /* 200, not done by hardware */ - sd->vmax.saturation = 0; /* 100, not done by hardware */ - sd->vmax.whitebal = 2; /* 100, not done by hardware */ - sd->vmax.mirror = 1; - sd->vmax.flip = 1; - sd->vmax.AC50Hz = 1; - - sd->dev_camera_settings = mi2020_camera_settings; - sd->dev_init_at_startup = mi2020_init_at_startup; - sd->dev_configure_alt = mi2020_configure_alt; - sd->dev_init_pre_alt = mi2020_init_pre_alt; - sd->dev_post_unset_alt = mi2020_post_unset_alt; -} - -/*==========================================================================*/ - -static void common(struct gspca_dev *gspca_dev) -{ - fetch_validx(gspca_dev, tbl_common_0B, ARRAY_SIZE(tbl_common_0B)); - fetch_idxdata(gspca_dev, tbl_common_3B, ARRAY_SIZE(tbl_common_3B)); - ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL); -} - -static int mi2020_init_at_startup(struct gspca_dev *gspca_dev) -{ - u8 c; - - ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &c); - ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &c); - - fetch_validx(gspca_dev, tbl_init_at_startup, - ARRAY_SIZE(tbl_init_at_startup)); - - ctrl_out(gspca_dev, 0x40, 1, 0x7a00, 0x8030, 0, NULL); - ctrl_in(gspca_dev, 0xc0, 2, 0x7a00, 0x8030, 1, &c); - - common(gspca_dev); - - msleep(61); -/* ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */ -/* msleep(36); */ - ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0000, 0, NULL); - - return 0; -} - -static int mi2020_init_pre_alt(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->mirrorMask = 0; - sd->vold.hue = -1; - - /* These controls need to be reset */ - sd->vold.brightness = -1; - sd->vold.sharpness = -1; - - /* If not different from default, they do not need to be set */ - sd->vold.contrast = 0; - sd->vold.gamma = 0; - sd->vold.backlight = 0; - - mi2020_init_post_alt(gspca_dev); - - return 0; -} - -static int mi2020_init_post_alt(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; - - s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0); - s32 flip = (((sd->vcur.flip > 0) ^ sd->mirrorMask) > 0); - s32 freq = (sd->vcur.AC50Hz > 0); - s32 wbal = sd->vcur.whitebal; - - u8 dat_freq2[] = {0x90, 0x00, 0x80}; - u8 dat_multi1[] = {0x8c, 0xa7, 0x00}; - u8 dat_multi2[] = {0x90, 0x00, 0x00}; - u8 dat_multi3[] = {0x8c, 0xa7, 0x00}; - u8 dat_multi4[] = {0x90, 0x00, 0x00}; - u8 dat_hvflip2[] = {0x90, 0x04, 0x6c}; - u8 dat_hvflip4[] = {0x90, 0x00, 0x24}; - u8 dat_wbal2[] = {0x90, 0x00, 0x00}; - u8 c; - - sd->nbIm = -1; - - dat_freq2[2] = freq ? 0xc0 : 0x80; - dat_multi1[2] = 0x9d; - dat_multi3[2] = dat_multi1[2] + 1; - if (wbal == 0) { - dat_multi4[2] = dat_multi2[2] = 0; - dat_wbal2[2] = 0x17; - } else if (wbal == 1) { - dat_multi4[2] = dat_multi2[2] = 0; - dat_wbal2[2] = 0x35; - } else if (wbal == 2) { - dat_multi4[2] = dat_multi2[2] = 0x20; - dat_wbal2[2] = 0x17; - } - dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror); - dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror); - - msleep(200); - ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL); - msleep(2); - - common(gspca_dev); - - msleep(142); - ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x0003, 0x00c1, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x0042, 0x00c2, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x006a, 0x000d, 0, NULL); - - switch (reso) { - case IMAGE_640: - case IMAGE_800: - if (reso != IMAGE_800) - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, - 12, dat_640); - else - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, - 12, dat_800); - - fetch_idxdata(gspca_dev, tbl_init_post_alt_low1, - ARRAY_SIZE(tbl_init_post_alt_low1)); - - if (reso == IMAGE_800) - fetch_idxdata(gspca_dev, tbl_init_post_alt_low2, - ARRAY_SIZE(tbl_init_post_alt_low2)); - - fetch_idxdata(gspca_dev, tbl_init_post_alt_low3, - ARRAY_SIZE(tbl_init_post_alt_low3)); - - ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL); - msleep(120); - break; - - case IMAGE_1280: - case IMAGE_1600: - if (reso == IMAGE_1280) { - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, - 12, dat_1280); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, - 3, "\x8c\x27\x07"); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, - 3, "\x90\x05\x04"); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, - 3, "\x8c\x27\x09"); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, - 3, "\x90\x04\x02"); - } else { - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, - 12, dat_1600); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, - 3, "\x8c\x27\x07"); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, - 3, "\x90\x06\x40"); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, - 3, "\x8c\x27\x09"); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, - 3, "\x90\x04\xb0"); - } - - fetch_idxdata(gspca_dev, tbl_init_post_alt_big, - ARRAY_SIZE(tbl_init_post_alt_big)); - - ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL); - msleep(1850); - } - - ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL); - msleep(40); - - /* AC power frequency */ - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2); - msleep(33); - /* light source */ - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal1); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal2); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6); - msleep(7); - ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, &c); - - fetch_idxdata(gspca_dev, tbl_init_post_alt_3B, - ARRAY_SIZE(tbl_init_post_alt_3B)); - - /* hvflip */ - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6); - msleep(250); - - if (reso == IMAGE_640 || reso == IMAGE_800) - fetch_idxdata(gspca_dev, tbl_middle_hvflip_low, - ARRAY_SIZE(tbl_middle_hvflip_low)); - else - fetch_idxdata(gspca_dev, tbl_middle_hvflip_big, - ARRAY_SIZE(tbl_middle_hvflip_big)); - - fetch_idxdata(gspca_dev, tbl_end_hvflip, - ARRAY_SIZE(tbl_end_hvflip)); - - sd->nbIm = 0; - - sd->vold.mirror = mirror; - sd->vold.flip = flip; - sd->vold.AC50Hz = freq; - sd->vold.whitebal = wbal; - - mi2020_camera_settings(gspca_dev); - - return 0; -} - -static int mi2020_configure_alt(struct gspca_dev *gspca_dev) -{ - s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; - - switch (reso) { - case IMAGE_640: - gspca_dev->alt = 3 + 1; - break; - - case IMAGE_800: - case IMAGE_1280: - case IMAGE_1600: - gspca_dev->alt = 1 + 1; - break; - } - return 0; -} - -static int mi2020_camera_settings(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; - - s32 backlight = sd->vcur.backlight; - s32 bright = sd->vcur.brightness; - s32 sharp = sd->vcur.sharpness; - s32 cntr = sd->vcur.contrast; - s32 gam = sd->vcur.gamma; - s32 hue = (sd->vcur.hue > 0); - s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0); - s32 flip = (((sd->vcur.flip > 0) ^ sd->mirrorMask) > 0); - s32 freq = (sd->vcur.AC50Hz > 0); - s32 wbal = sd->vcur.whitebal; - - u8 dat_sharp[] = {0x6c, 0x00, 0x08}; - u8 dat_bright2[] = {0x90, 0x00, 0x00}; - u8 dat_freq2[] = {0x90, 0x00, 0x80}; - u8 dat_multi1[] = {0x8c, 0xa7, 0x00}; - u8 dat_multi2[] = {0x90, 0x00, 0x00}; - u8 dat_multi3[] = {0x8c, 0xa7, 0x00}; - u8 dat_multi4[] = {0x90, 0x00, 0x00}; - u8 dat_hvflip2[] = {0x90, 0x04, 0x6c}; - u8 dat_hvflip4[] = {0x90, 0x00, 0x24}; - u8 dat_wbal2[] = {0x90, 0x00, 0x00}; - - /* Less than 4 images received -> too early to set the settings */ - if (sd->nbIm < 4) { - sd->waitSet = 1; - return 0; - } - sd->waitSet = 0; - - if (freq != sd->vold.AC50Hz) { - sd->vold.AC50Hz = freq; - - dat_freq2[2] = freq ? 0xc0 : 0x80; - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2); - msleep(20); - } - - if (wbal != sd->vold.whitebal) { - sd->vold.whitebal = wbal; - if (wbal < 0 || wbal > sd->vmax.whitebal) - wbal = 0; - - dat_multi1[2] = 0x9d; - dat_multi3[2] = dat_multi1[2] + 1; - if (wbal == 0) { - dat_multi4[2] = dat_multi2[2] = 0; - dat_wbal2[2] = 0x17; - } else if (wbal == 1) { - dat_multi4[2] = dat_multi2[2] = 0; - dat_wbal2[2] = 0x35; - } else if (wbal == 2) { - dat_multi4[2] = dat_multi2[2] = 0x20; - dat_wbal2[2] = 0x17; - } - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal1); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal2); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6); - } - - if (mirror != sd->vold.mirror || flip != sd->vold.flip) { - sd->vold.mirror = mirror; - sd->vold.flip = flip; - - dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror); - dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror); - - fetch_idxdata(gspca_dev, tbl_init_post_alt_3B, - ARRAY_SIZE(tbl_init_post_alt_3B)); - - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6); - msleep(40); - - if (reso == IMAGE_640 || reso == IMAGE_800) - fetch_idxdata(gspca_dev, tbl_middle_hvflip_low, - ARRAY_SIZE(tbl_middle_hvflip_low)); - else - fetch_idxdata(gspca_dev, tbl_middle_hvflip_big, - ARRAY_SIZE(tbl_middle_hvflip_big)); - - fetch_idxdata(gspca_dev, tbl_end_hvflip, - ARRAY_SIZE(tbl_end_hvflip)); - } - - if (bright != sd->vold.brightness) { - sd->vold.brightness = bright; - if (bright < 0 || bright > sd->vmax.brightness) - bright = 0; - - dat_bright2[2] = bright; - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright1); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright2); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright3); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright4); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright5); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright6); - } - - if (cntr != sd->vold.contrast || gam != sd->vold.gamma) { - sd->vold.contrast = cntr; - if (cntr < 0 || cntr > sd->vmax.contrast) - cntr = 0; - sd->vold.gamma = gam; - if (gam < 0 || gam > sd->vmax.gamma) - gam = 0; - - dat_multi1[2] = 0x6d; - dat_multi3[2] = dat_multi1[2] + 1; - if (cntr == 0) - cntr = 4; - dat_multi4[2] = dat_multi2[2] = cntr * 0x10 + 2 - gam; - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6); - } - - if (backlight != sd->vold.backlight) { - sd->vold.backlight = backlight; - if (backlight < 0 || backlight > sd->vmax.backlight) - backlight = 0; - - dat_multi1[2] = 0x9d; - dat_multi3[2] = dat_multi1[2] + 1; - dat_multi4[2] = dat_multi2[2] = backlight; - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5); - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6); - } - - if (sharp != sd->vold.sharpness) { - sd->vold.sharpness = sharp; - if (sharp < 0 || sharp > sd->vmax.sharpness) - sharp = 0; - - dat_sharp[1] = sharp; - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0032, 3, dat_sharp); - } - - if (hue != sd->vold.hue) { - sd->swapRB = hue; - sd->vold.hue = hue; - } - - return 0; -} - -static void mi2020_post_unset_alt(struct gspca_dev *gspca_dev) -{ - ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL); - msleep(40); - ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0000, 0, NULL); -} diff --git a/drivers/media/video/gspca/gl860/gl860-ov2640.c b/drivers/media/video/gspca/gl860/gl860-ov2640.c deleted file mode 100644 index 768cac5cd72b..000000000000 --- a/drivers/media/video/gspca/gl860/gl860-ov2640.c +++ /dev/null @@ -1,489 +0,0 @@ -/* Subdriver for the GL860 chip with the OV2640 sensor - * Author Olivier LORIN, from Malmostoso's logs - * - * 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 - * 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, see <http://www.gnu.org/licenses/>. - */ - -/* Sensor : OV2640 */ - -#include "gl860.h" - -static u8 dat_init1[] = "\x00\x41\x07\x6a\x06\x61\x0d\x6a" "\x10\x10\xc1\x01"; - -static u8 c61[] = {0x61}; /* expected */ -static u8 c51[] = {0x51}; /* expected */ -static u8 c50[] = {0x50}; /* expected */ -static u8 c28[] = {0x28}; /* expected */ -static u8 ca8[] = {0xa8}; /* expected */ - -static u8 dat_post[] = - "\x00\x41\x07\x6a\x06\xef\x0d\x6a" "\x10\x10\xc1\x01"; - -static u8 dat_640[] = "\xd0\x01\xd1\x08\xd2\xe0\xd3\x02\xd4\x10\xd5\x81"; -static u8 dat_800[] = "\xd0\x01\xd1\x10\xd2\x58\xd3\x02\xd4\x18\xd5\x21"; -static u8 dat_1280[] = "\xd0\x01\xd1\x18\xd2\xc0\xd3\x02\xd4\x28\xd5\x01"; -static u8 dat_1600[] = "\xd0\x01\xd1\x20\xd2\xb0\xd3\x02\xd4\x30\xd5\x41"; - -static struct validx tbl_init_at_startup[] = { - {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1}, - {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d}, - {0x0050, 0x0000}, {0x0041, 0x0000}, {0x006a, 0x0007}, {0x0061, 0x0006}, - {0x006a, 0x000d}, {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1}, - {0x0041, 0x00c2}, {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058}, - {0x0041, 0x0000}, {0x0061, 0x0000}, -}; - -static struct validx tbl_common[] = { - {0x6000, 0x00ff}, {0x60ff, 0x002c}, {0x60df, 0x002e}, {0x6001, 0x00ff}, - {0x6080, 0x0012}, {0x6000, 0x0000}, {0x6000, 0x0045}, {0x6000, 0x0010}, - {0x6035, 0x003c}, {0x6000, 0x0011}, {0x6028, 0x0004}, {0x60e5, 0x0013}, - {0x6088, 0x0014}, {0x600c, 0x002c}, {0x6078, 0x0033}, {0x60f7, 0x003b}, - {0x6000, 0x003e}, {0x6011, 0x0043}, {0x6010, 0x0016}, {0x6082, 0x0039}, - {0x6088, 0x0035}, {0x600a, 0x0022}, {0x6040, 0x0037}, {0x6000, 0x0023}, - {0x60a0, 0x0034}, {0x601a, 0x0036}, {0x6002, 0x0006}, {0x60c0, 0x0007}, - {0x60b7, 0x000d}, {0x6001, 0x000e}, {0x6000, 0x004c}, {0x6081, 0x004a}, - {0x6099, 0x0021}, {0x6002, 0x0009}, {0x603e, 0x0024}, {0x6034, 0x0025}, - {0x6081, 0x0026}, {0x6000, 0x0000}, {0x6000, 0x0045}, {0x6000, 0x0010}, - {0x6000, 0x005c}, {0x6000, 0x0063}, {0x6000, 0x007c}, {0x6070, 0x0061}, - {0x6080, 0x0062}, {0x6080, 0x0020}, {0x6030, 0x0028}, {0x6000, 0x006c}, - {0x6000, 0x006e}, {0x6002, 0x0070}, {0x6094, 0x0071}, {0x60c1, 0x0073}, - {0x6034, 0x003d}, {0x6057, 0x005a}, {0x60bb, 0x004f}, {0x609c, 0x0050}, - {0x6080, 0x006d}, {0x6002, 0x0039}, {0x6033, 0x003a}, {0x60f1, 0x003b}, - {0x6031, 0x003c}, {0x6000, 0x00ff}, {0x6014, 0x00e0}, {0x60ff, 0x0076}, - {0x60a0, 0x0033}, {0x6020, 0x0042}, {0x6018, 0x0043}, {0x6000, 0x004c}, - {0x60d0, 0x0087}, {0x600f, 0x0088}, {0x6003, 0x00d7}, {0x6010, 0x00d9}, - {0x6005, 0x00da}, {0x6082, 0x00d3}, {0x60c0, 0x00f9}, {0x6006, 0x0044}, - {0x6007, 0x00d1}, {0x6002, 0x00d2}, {0x6000, 0x00d2}, {0x6011, 0x00d8}, - {0x6008, 0x00c8}, {0x6080, 0x00c9}, {0x6008, 0x007c}, {0x6020, 0x007d}, - {0x6020, 0x007d}, {0x6000, 0x0090}, {0x600e, 0x0091}, {0x601a, 0x0091}, - {0x6031, 0x0091}, {0x605a, 0x0091}, {0x6069, 0x0091}, {0x6075, 0x0091}, - {0x607e, 0x0091}, {0x6088, 0x0091}, {0x608f, 0x0091}, {0x6096, 0x0091}, - {0x60a3, 0x0091}, {0x60af, 0x0091}, {0x60c4, 0x0091}, {0x60d7, 0x0091}, - {0x60e8, 0x0091}, {0x6020, 0x0091}, {0x6000, 0x0092}, {0x6006, 0x0093}, - {0x60e3, 0x0093}, {0x6005, 0x0093}, {0x6005, 0x0093}, {0x6000, 0x0093}, - {0x6004, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093}, - {0x6000, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093}, - {0x6000, 0x0096}, {0x6008, 0x0097}, {0x6019, 0x0097}, {0x6002, 0x0097}, - {0x600c, 0x0097}, {0x6024, 0x0097}, {0x6030, 0x0097}, {0x6028, 0x0097}, - {0x6026, 0x0097}, {0x6002, 0x0097}, {0x6098, 0x0097}, {0x6080, 0x0097}, - {0x6000, 0x0097}, {0x6000, 0x0097}, {0x60ed, 0x00c3}, {0x609a, 0x00c4}, - {0x6000, 0x00a4}, {0x6011, 0x00c5}, {0x6051, 0x00c6}, {0x6010, 0x00c7}, - {0x6066, 0x00b6}, {0x60a5, 0x00b8}, {0x6064, 0x00b7}, {0x607c, 0x00b9}, - {0x60af, 0x00b3}, {0x6097, 0x00b4}, {0x60ff, 0x00b5}, {0x60c5, 0x00b0}, - {0x6094, 0x00b1}, {0x600f, 0x00b2}, {0x605c, 0x00c4}, {0x6000, 0x00a8}, - {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x601d, 0x0086}, {0x6000, 0x0050}, - {0x6090, 0x0051}, {0x6018, 0x0052}, {0x6000, 0x0053}, {0x6000, 0x0054}, - {0x6088, 0x0055}, {0x6000, 0x0057}, {0x6090, 0x005a}, {0x6018, 0x005b}, - {0x6005, 0x005c}, {0x60ed, 0x00c3}, {0x6000, 0x007f}, {0x6005, 0x00da}, - {0x601f, 0x00e5}, {0x6067, 0x00e1}, {0x6000, 0x00e0}, {0x60ff, 0x00dd}, - {0x6000, 0x0005}, {0x6001, 0x00ff}, {0x6000, 0x0000}, {0x6000, 0x0045}, - {0x6000, 0x0010}, -}; - -static struct validx tbl_sensor_settings_common1[] = { - {0x0041, 0x0000}, {0x006a, 0x0007}, {0x00ef, 0x0006}, {0x006a, 0x000d}, - {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1}, {0x0041, 0x00c2}, - {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058}, {0x0041, 0x0000}, - {50, 0xffff}, - {0x0061, 0x0000}, - {0xffff, 0xffff}, - {0x6000, 0x00ff}, {0x6000, 0x007c}, {0x6007, 0x007d}, - {30, 0xffff}, - {0x0040, 0x0000}, -}; - -static struct validx tbl_sensor_settings_common2[] = { - {0x6001, 0x00ff}, {0x6038, 0x000c}, - {10, 0xffff}, - {0x6000, 0x0011}, -}; - -static struct validx tbl_640[] = { - {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, {0x6067, 0x00e1}, - {0x6004, 0x00da}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, - {0x6001, 0x00ff}, {0x6000, 0x0012}, {0x6000, 0x0011}, {0x6011, 0x0017}, - {0x6075, 0x0018}, {0x6001, 0x0019}, {0x6097, 0x001a}, {0x6036, 0x0032}, - {0x60bb, 0x004f}, {0x6057, 0x005a}, {0x609c, 0x0050}, {0x6080, 0x006d}, - {0x6092, 0x0026}, {0x60ff, 0x0020}, {0x6000, 0x0027}, {0x6000, 0x00ff}, - {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x6000, 0x008c}, {0x603d, 0x0086}, - {0x6089, 0x0050}, {0x6090, 0x0051}, {0x602c, 0x0052}, {0x6000, 0x0053}, - {0x6000, 0x0054}, {0x6088, 0x0055}, {0x6000, 0x0057}, {0x60a0, 0x005a}, - {0x6078, 0x005b}, {0x6000, 0x005c}, {0x6004, 0x00d3}, {0x6000, 0x00e0}, - {0x60ff, 0x00dd}, {0x60a1, 0x005a}, -}; - -static struct validx tbl_800[] = { - {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, {0x6067, 0x00e1}, - {0x6004, 0x00da}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, - {0x6001, 0x00ff}, {0x6040, 0x0012}, {0x6000, 0x0011}, {0x6011, 0x0017}, - {0x6043, 0x0018}, {0x6000, 0x0019}, {0x604b, 0x001a}, {0x6009, 0x0032}, - {0x60ca, 0x004f}, {0x60a8, 0x0050}, {0x6000, 0x006d}, {0x6038, 0x003d}, - {0x60c8, 0x0035}, {0x6000, 0x0022}, {0x6092, 0x0026}, {0x60ff, 0x0020}, - {0x6000, 0x0027}, {0x6000, 0x00ff}, {0x6064, 0x00c0}, {0x604b, 0x00c1}, - {0x6000, 0x008c}, {0x601d, 0x0086}, {0x6082, 0x00d3}, {0x6000, 0x00e0}, - {0x60ff, 0x00dd}, {0x6020, 0x008c}, {0x6001, 0x00ff}, {0x6044, 0x0018}, -}; - -static struct validx tbl_big1[] = { - {0x0002, 0x00c1}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, - {0x6001, 0x00ff}, {0x6000, 0x0012}, {0x6000, 0x0000}, {0x6000, 0x0045}, - {0x6000, 0x0010}, {0x6000, 0x0011}, {0x6011, 0x0017}, {0x6075, 0x0018}, - {0x6001, 0x0019}, {0x6097, 0x001a}, {0x6036, 0x0032}, {0x60bb, 0x004f}, - {0x609c, 0x0050}, {0x6057, 0x005a}, {0x6080, 0x006d}, {0x6043, 0x000f}, - {0x608f, 0x0003}, {0x6005, 0x007c}, {0x6081, 0x0026}, {0x6000, 0x00ff}, - {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x6000, 0x008c}, -}; - -static struct validx tbl_big2[] = { - {0x603d, 0x0086}, {0x6000, 0x0050}, {0x6090, 0x0051}, {0x602c, 0x0052}, - {0x6000, 0x0053}, {0x6000, 0x0054}, {0x6088, 0x0055}, {0x6000, 0x0057}, - {0x6040, 0x005a}, {0x60f0, 0x005b}, {0x6001, 0x005c}, {0x6082, 0x00d3}, - {0x6000, 0x008e}, -}; - -static struct validx tbl_big3[] = { - {0x6004, 0x00da}, {0x6000, 0x00e0}, {0x6067, 0x00e1}, {0x60ff, 0x00dd}, - {0x6001, 0x00ff}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, - {0x6001, 0x00ff}, {0x6000, 0x0011}, {0x6000, 0x00ff}, {0x6010, 0x00c7}, - {0x6000, 0x0092}, {0x6006, 0x0093}, {0x60e3, 0x0093}, {0x6005, 0x0093}, - {0x6005, 0x0093}, {0x60ed, 0x00c3}, {0x6000, 0x00a4}, {0x60d0, 0x0087}, - {0x6003, 0x0096}, {0x600c, 0x0097}, {0x6024, 0x0097}, {0x6030, 0x0097}, - {0x6028, 0x0097}, {0x6026, 0x0097}, {0x6002, 0x0097}, {0x6001, 0x00ff}, - {0x6043, 0x000f}, {0x608f, 0x0003}, {0x6000, 0x002d}, {0x6000, 0x002e}, - {0x600a, 0x0022}, {0x6002, 0x0070}, {0x6008, 0x0014}, {0x6048, 0x0014}, - {0x6000, 0x00ff}, {0x6000, 0x00e0}, {0x60ff, 0x00dd}, -}; - -static struct validx tbl_post_unset_alt[] = { - {0x006a, 0x000d}, {0x6001, 0x00ff}, {0x6081, 0x0026}, {0x6000, 0x0000}, - {0x6000, 0x0045}, {0x6000, 0x0010}, {0x6068, 0x000d}, - {50, 0xffff}, - {0x0021, 0x0000}, -}; - -static int ov2640_init_at_startup(struct gspca_dev *gspca_dev); -static int ov2640_configure_alt(struct gspca_dev *gspca_dev); -static int ov2640_init_pre_alt(struct gspca_dev *gspca_dev); -static int ov2640_init_post_alt(struct gspca_dev *gspca_dev); -static void ov2640_post_unset_alt(struct gspca_dev *gspca_dev); -static int ov2640_camera_settings(struct gspca_dev *gspca_dev); -/*==========================================================================*/ - -void ov2640_init_settings(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->vcur.backlight = 32; - sd->vcur.brightness = 0; - sd->vcur.sharpness = 6; - sd->vcur.contrast = 0; - sd->vcur.gamma = 32; - sd->vcur.hue = 0; - sd->vcur.saturation = 128; - sd->vcur.whitebal = 64; - sd->vcur.mirror = 0; - sd->vcur.flip = 0; - - sd->vmax.backlight = 64; - sd->vmax.brightness = 255; - sd->vmax.sharpness = 31; - sd->vmax.contrast = 255; - sd->vmax.gamma = 64; - sd->vmax.hue = 254 + 2; - sd->vmax.saturation = 255; - sd->vmax.whitebal = 128; - sd->vmax.mirror = 1; - sd->vmax.flip = 1; - sd->vmax.AC50Hz = 0; - - sd->dev_camera_settings = ov2640_camera_settings; - sd->dev_init_at_startup = ov2640_init_at_startup; - sd->dev_configure_alt = ov2640_configure_alt; - sd->dev_init_pre_alt = ov2640_init_pre_alt; - sd->dev_post_unset_alt = ov2640_post_unset_alt; -} - -/*==========================================================================*/ - -static void common(struct gspca_dev *gspca_dev) -{ - fetch_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common)); -} - -static int ov2640_init_at_startup(struct gspca_dev *gspca_dev) -{ - fetch_validx(gspca_dev, tbl_init_at_startup, - ARRAY_SIZE(tbl_init_at_startup)); - - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_init1); - - common(gspca_dev); - - ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0006, 1, c61); - - ctrl_out(gspca_dev, 0x40, 1, 0x00ef, 0x0006, 0, NULL); - - ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c51); - - ctrl_out(gspca_dev, 0x40, 1, 0x0051, 0x0000, 0, NULL); -/* ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */ - - return 0; -} - -static int ov2640_init_pre_alt(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->mirrorMask = 0; - - sd->vold.backlight = -1; - sd->vold.brightness = -1; - sd->vold.sharpness = -1; - sd->vold.contrast = -1; - sd->vold.saturation = -1; - sd->vold.gamma = -1; - sd->vold.hue = -1; - sd->vold.whitebal = -1; - sd->vold.mirror = -1; - sd->vold.flip = -1; - - ov2640_init_post_alt(gspca_dev); - - return 0; -} - -static int ov2640_init_post_alt(struct gspca_dev *gspca_dev) -{ - s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; - s32 n; /* reserved for FETCH functions */ - - ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL); - - n = fetch_validx(gspca_dev, tbl_sensor_settings_common1, - ARRAY_SIZE(tbl_sensor_settings_common1)); - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_post); - common(gspca_dev); - keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common1, - ARRAY_SIZE(tbl_sensor_settings_common1), n); - - switch (reso) { - case IMAGE_640: - n = fetch_validx(gspca_dev, tbl_640, ARRAY_SIZE(tbl_640)); - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_640); - break; - - case IMAGE_800: - n = fetch_validx(gspca_dev, tbl_800, ARRAY_SIZE(tbl_800)); - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_800); - break; - - case IMAGE_1600: - case IMAGE_1280: - n = fetch_validx(gspca_dev, tbl_big1, ARRAY_SIZE(tbl_big1)); - - if (reso == IMAGE_1280) { - n = fetch_validx(gspca_dev, tbl_big2, - ARRAY_SIZE(tbl_big2)); - } else { - ctrl_out(gspca_dev, 0x40, 1, 0x601d, 0x0086, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00d7, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6082, 0x00d3, 0, NULL); - } - - n = fetch_validx(gspca_dev, tbl_big3, ARRAY_SIZE(tbl_big3)); - - if (reso == IMAGE_1280) { - ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, - 12, dat_1280); - } else { - ctrl_out(gspca_dev, 0x40, 1, 0x6020, 0x008c, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6076, 0x0018, 0, NULL); - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, - 12, dat_1600); - } - break; - } - - n = fetch_validx(gspca_dev, tbl_sensor_settings_common2, - ARRAY_SIZE(tbl_sensor_settings_common2)); - - ov2640_camera_settings(gspca_dev); - - return 0; -} - -static int ov2640_configure_alt(struct gspca_dev *gspca_dev) -{ - s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; - - switch (reso) { - case IMAGE_640: - gspca_dev->alt = 3 + 1; - break; - - case IMAGE_800: - case IMAGE_1280: - case IMAGE_1600: - gspca_dev->alt = 1 + 1; - break; - } - return 0; -} - -static int ov2640_camera_settings(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - s32 backlight = sd->vcur.backlight; - s32 bright = sd->vcur.brightness; - s32 sharp = sd->vcur.sharpness; - s32 gam = sd->vcur.gamma; - s32 cntr = sd->vcur.contrast; - s32 sat = sd->vcur.saturation; - s32 hue = sd->vcur.hue; - s32 wbal = sd->vcur.whitebal; - s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) == 0); - s32 flip = (((sd->vcur.flip > 0) ^ sd->mirrorMask) == 0); - - if (backlight != sd->vold.backlight) { - /* No sd->vold.backlight=backlight; (to be done again later) */ - if (backlight < 0 || backlight > sd->vmax.backlight) - backlight = 0; - - ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x00ff, - 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight , 0x0024, - 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025, - 0, NULL); - } - - if (bright != sd->vold.brightness) { - sd->vold.brightness = bright; - if (bright < 0 || bright > sd->vmax.brightness) - bright = 0; - - ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6009 , 0x007c, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6000 + bright, 0x007d, 0, NULL); - } - - if (wbal != sd->vold.whitebal) { - sd->vold.whitebal = wbal; - if (wbal < 0 || wbal > sd->vmax.whitebal) - wbal = 0; - - ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6003 , 0x007c, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6000 + wbal, 0x007d, 0, NULL); - } - - if (cntr != sd->vold.contrast) { - sd->vold.contrast = cntr; - if (cntr < 0 || cntr > sd->vmax.contrast) - cntr = 0; - - ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6007 , 0x007c, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6000 + cntr, 0x007d, 0, NULL); - } - - if (sat != sd->vold.saturation) { - sd->vold.saturation = sat; - if (sat < 0 || sat > sd->vmax.saturation) - sat = 0; - - ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x007c, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6000 + sat, 0x007d, 0, NULL); - } - - if (sharp != sd->vold.sharpness) { - sd->vold.sharpness = sharp; - if (sharp < 0 || sharp > sd->vmax.sharpness) - sharp = 0; - - ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x0092, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x60c0 + sharp, 0x0093, 0, NULL); - } - - if (hue != sd->vold.hue) { - sd->vold.hue = hue; - if (hue < 0 || hue > sd->vmax.hue) - hue = 0; - - ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6002 , 0x007c, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6000 + hue * (hue < 255), 0x007d, - 0, NULL); - if (hue >= 255) - sd->swapRB = 1; - else - sd->swapRB = 0; - } - - if (gam != sd->vold.gamma) { - sd->vold.gamma = gam; - if (gam < 0 || gam > sd->vmax.gamma) - gam = 0; - - ctrl_out(gspca_dev, 0x40, 1, 0x6000 , 0x00ff, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6008 , 0x007c, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6000 + gam, 0x007d, 0, NULL); - } - - if (mirror != sd->vold.mirror || flip != sd->vold.flip) { - sd->vold.mirror = mirror; - sd->vold.flip = flip; - - mirror = 0x80 * mirror; - ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL); - ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, c28); - ctrl_out(gspca_dev, 0x40, 1, 0x6028 + mirror, 0x0004, 0, NULL); - - flip = 0x50 * flip + mirror; - ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL); - ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, ca8); - ctrl_out(gspca_dev, 0x40, 1, 0x6028 + flip, 0x0004, 0, NULL); - - ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50); - } - - if (backlight != sd->vold.backlight) { - sd->vold.backlight = backlight; - - ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x00ff, - 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight , 0x0024, - 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025, - 0, NULL); - } - - return 0; -} - -static void ov2640_post_unset_alt(struct gspca_dev *gspca_dev) -{ - ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL); - msleep(20); - fetch_validx(gspca_dev, tbl_post_unset_alt, - ARRAY_SIZE(tbl_post_unset_alt)); -} diff --git a/drivers/media/video/gspca/gl860/gl860-ov9655.c b/drivers/media/video/gspca/gl860/gl860-ov9655.c deleted file mode 100644 index 5ae9619d72a5..000000000000 --- a/drivers/media/video/gspca/gl860/gl860-ov9655.c +++ /dev/null @@ -1,336 +0,0 @@ -/* Subdriver for the GL860 chip with the OV9655 sensor - * Author Olivier LORIN, from logs done by Simon (Sur3) and Almighurt - * on dsd's weblog - * - * 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 - * 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, see <http://www.gnu.org/licenses/>. - */ - -/* Sensor : OV9655 */ - -#include "gl860.h" - -static struct validx tbl_init_at_startup[] = { - {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1}, - {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d}, - - {0x0040, 0x0000}, -}; - -static struct validx tbl_commmon[] = { - {0x0041, 0x0000}, {0x006a, 0x0007}, {0x0063, 0x0006}, {0x006a, 0x000d}, - {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1}, {0x0041, 0x00c2}, - {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058}, {0x0040, 0x0000}, - {0x00f3, 0x0006}, {0x0058, 0x0000}, {0x0048, 0x0000}, {0x0061, 0x0000}, -}; - -static s32 tbl_length[] = {12, 56, 52, 54, 56, 42, 32, 12}; - -static u8 *tbl_640[] = { - "\x00\x40\x07\x6a\x06\xf3\x0d\x6a" "\x10\x10\xc1\x01" - , - "\x12\x80\x00\x00\x01\x98\x02\x80" "\x03\x12\x04\x03\x0b\x57\x0e\x61" - "\x0f\x42\x11\x01\x12\x60\x13\x00" "\x14\x3a\x16\x24\x17\x14\x18\x00" - "\x19\x01\x1a\x3d\x1e\x04\x24\x3c" "\x25\x36\x26\x72\x27\x08\x28\x08" - "\x29\x15\x2a\x00\x2b\x00\x2c\x08" - , - "\x32\xff\x33\x00\x34\x3d\x35\x00" "\x36\xfa\x38\x72\x39\x57\x3a\x00" - "\x3b\x0c\x3d\x99\x3e\x0c\x3f\xc1" "\x40\xc0\x41\x00\x42\xc0\x43\x0a" - "\x44\xf0\x45\x46\x46\x62\x47\x2a" "\x48\x3c\x4a\xee\x4b\xe7\x4c\xe7" - "\x4d\xe7\x4e\xe7" - , - "\x4f\x98\x50\x98\x51\x00\x52\x28" "\x53\x70\x54\x98\x58\x1a\x59\x85" - "\x5a\xa9\x5b\x64\x5c\x84\x5d\x53" "\x5e\x0e\x5f\xf0\x60\xf0\x61\xf0" - "\x62\x00\x63\x00\x64\x02\x65\x20" "\x66\x00\x69\x0a\x6b\x5a\x6c\x04" - "\x6d\x55\x6e\x00\x6f\x9d" - , - "\x70\x15\x71\x78\x72\x00\x73\x00" "\x74\x3a\x75\x35\x76\x01\x77\x02" - "\x7a\x24\x7b\x04\x7c\x07\x7d\x10" "\x7e\x28\x7f\x36\x80\x44\x81\x52" - "\x82\x60\x83\x6c\x84\x78\x85\x8c" "\x86\x9e\x87\xbb\x88\xd2\x89\xe5" - "\x8a\x23\x8c\x8d\x90\x7c\x91\x7b" - , - "\x9d\x02\x9e\x02\x9f\x74\xa0\x73" "\xa1\x40\xa4\x50\xa5\x68\xa6\x70" - "\xa8\xc1\xa9\xef\xaa\x92\xab\x04" "\xac\x80\xad\x80\xae\x80\xaf\x80" - "\xb2\xf2\xb3\x20\xb4\x20\xb5\x00" "\xb6\xaf" - , - "\xbb\xae\xbc\x4f\xbd\x4e\xbe\x6a" "\xbf\x68\xc0\xaa\xc1\xc0\xc2\x01" - "\xc3\x4e\xc6\x85\xc7\x81\xc9\xe0" "\xca\xe8\xcb\xf0\xcc\xd8\xcd\x93" - , - "\xd0\x01\xd1\x08\xd2\xe0\xd3\x01" "\xd4\x10\xd5\x80" -}; - -static u8 *tbl_1280[] = { - "\x00\x40\x07\x6a\x06\xf3\x0d\x6a" "\x10\x10\xc1\x01" - , - "\x12\x80\x00\x00\x01\x98\x02\x80" "\x03\x12\x04\x01\x0b\x57\x0e\x61" - "\x0f\x42\x11\x00\x12\x00\x13\x00" "\x14\x3a\x16\x24\x17\x1b\x18\xbb" - "\x19\x01\x1a\x81\x1e\x04\x24\x3c" "\x25\x36\x26\x72\x27\x08\x28\x08" - "\x29\x15\x2a\x00\x2b\x00\x2c\x08" - , - "\x32\xa4\x33\x00\x34\x3d\x35\x00" "\x36\xf8\x38\x72\x39\x57\x3a\x00" - "\x3b\x0c\x3d\x99\x3e\x0c\x3f\xc2" "\x40\xc0\x41\x00\x42\xc0\x43\x0a" - "\x44\xf0\x45\x46\x46\x62\x47\x2a" "\x48\x3c\x4a\xec\x4b\xe8\x4c\xe8" - "\x4d\xe8\x4e\xe8" - , - "\x4f\x98\x50\x98\x51\x00\x52\x28" "\x53\x70\x54\x98\x58\x1a\x59\x85" - "\x5a\xa9\x5b\x64\x5c\x84\x5d\x53" "\x5e\x0e\x5f\xf0\x60\xf0\x61\xf0" - "\x62\x00\x63\x00\x64\x02\x65\x20" "\x66\x00\x69\x02\x6b\x5a\x6c\x04" - "\x6d\x55\x6e\x00\x6f\x9d" - , - "\x70\x08\x71\x78\x72\x00\x73\x01" "\x74\x3a\x75\x35\x76\x01\x77\x02" - "\x7a\x24\x7b\x04\x7c\x07\x7d\x10" "\x7e\x28\x7f\x36\x80\x44\x81\x52" - "\x82\x60\x83\x6c\x84\x78\x85\x8c" "\x86\x9e\x87\xbb\x88\xd2\x89\xe5" - "\x8a\x23\x8c\x0d\x90\x90\x91\x90" - , - "\x9d\x02\x9e\x02\x9f\x94\xa0\x94" "\xa1\x01\xa4\x50\xa5\x68\xa6\x70" - "\xa8\xc1\xa9\xef\xaa\x92\xab\x04" "\xac\x80\xad\x80\xae\x80\xaf\x80" - "\xb2\xf2\xb3\x20\xb4\x20\xb5\x00" "\xb6\xaf" - , - "\xbb\xae\xbc\x38\xbd\x39\xbe\x01" "\xbf\x01\xc0\xe2\xc1\xc0\xc2\x01" - "\xc3\x4e\xc6\x85\xc7\x81\xc9\xe0" "\xca\xe8\xcb\xf0\xcc\xd8\xcd\x93" - , - "\xd0\x21\xd1\x18\xd2\xe0\xd3\x01" "\xd4\x28\xd5\x00" -}; - -static u8 c04[] = {0x04}; -static u8 dat_post1[] = "\x04\x00\x10\x20\xa1\x00\x00\x02"; -static u8 dat_post2[] = "\x10\x10\xc1\x02"; -static u8 dat_post3[] = "\x04\x00\x10\x7c\xa1\x00\x00\x04"; -static u8 dat_post4[] = "\x10\x02\xc1\x06"; -static u8 dat_post5[] = "\x04\x00\x10\x7b\xa1\x00\x00\x08"; -static u8 dat_post6[] = "\x10\x10\xc1\x05"; -static u8 dat_post7[] = "\x04\x00\x10\x7c\xa1\x00\x00\x08"; -static u8 dat_post8[] = "\x04\x00\x10\x7c\xa1\x00\x00\x09"; - -static struct validx tbl_init_post_alt[] = { - {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x603c, 0x00ff}, - {0x6003, 0x00ff}, {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x6001, 0x00ff}, - {0x6000, 0x801e}, - {0xffff, 0xffff}, - {0x6004, 0x001e}, {0x6000, 0x801e}, - {0xffff, 0xffff}, - {0x6004, 0x001e}, {0x6012, 0x0003}, {0x6000, 0x801e}, - {0xffff, 0xffff}, - {0x6004, 0x001e}, {0x6000, 0x801e}, - {0xffff, 0xffff}, - {0x6004, 0x001e}, {0x6012, 0x0003}, - {0xffff, 0xffff}, - {0x6000, 0x801e}, - {0xffff, 0xffff}, - {0x6004, 0x001e}, {0x6000, 0x801e}, - {0xffff, 0xffff}, - {0x6004, 0x001e}, {0x6012, 0x0003}, {0x6000, 0x801e}, - {0xffff, 0xffff}, - {0x6004, 0x001e}, {0x6000, 0x801e}, - {0xffff, 0xffff}, - {0x6004, 0x001e}, {0x6012, 0x0003}, - {0xffff, 0xffff}, - {0x6000, 0x801e}, - {0xffff, 0xffff}, - {0x6004, 0x001e}, {0x6000, 0x801e}, - {0xffff, 0xffff}, - {0x6004, 0x001e}, {0x6012, 0x0003}, -}; - -static int ov9655_init_at_startup(struct gspca_dev *gspca_dev); -static int ov9655_configure_alt(struct gspca_dev *gspca_dev); -static int ov9655_init_pre_alt(struct gspca_dev *gspca_dev); -static int ov9655_init_post_alt(struct gspca_dev *gspca_dev); -static void ov9655_post_unset_alt(struct gspca_dev *gspca_dev); -static int ov9655_camera_settings(struct gspca_dev *gspca_dev); -/*==========================================================================*/ - -void ov9655_init_settings(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->vcur.backlight = 0; - sd->vcur.brightness = 128; - sd->vcur.sharpness = 0; - sd->vcur.contrast = 0; - sd->vcur.gamma = 0; - sd->vcur.hue = 0; - sd->vcur.saturation = 0; - sd->vcur.whitebal = 0; - - sd->vmax.backlight = 0; - sd->vmax.brightness = 255; - sd->vmax.sharpness = 0; - sd->vmax.contrast = 0; - sd->vmax.gamma = 0; - sd->vmax.hue = 0 + 1; - sd->vmax.saturation = 0; - sd->vmax.whitebal = 0; - sd->vmax.mirror = 0; - sd->vmax.flip = 0; - sd->vmax.AC50Hz = 0; - - sd->dev_camera_settings = ov9655_camera_settings; - sd->dev_init_at_startup = ov9655_init_at_startup; - sd->dev_configure_alt = ov9655_configure_alt; - sd->dev_init_pre_alt = ov9655_init_pre_alt; - sd->dev_post_unset_alt = ov9655_post_unset_alt; -} - -/*==========================================================================*/ - -static int ov9655_init_at_startup(struct gspca_dev *gspca_dev) -{ - fetch_validx(gspca_dev, tbl_init_at_startup, - ARRAY_SIZE(tbl_init_at_startup)); - fetch_validx(gspca_dev, tbl_commmon, ARRAY_SIZE(tbl_commmon)); -/* ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL);*/ - - return 0; -} - -static int ov9655_init_pre_alt(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->vold.brightness = -1; - sd->vold.hue = -1; - - fetch_validx(gspca_dev, tbl_commmon, ARRAY_SIZE(tbl_commmon)); - - ov9655_init_post_alt(gspca_dev); - - return 0; -} - -static int ov9655_init_post_alt(struct gspca_dev *gspca_dev) -{ - s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; - s32 n; /* reserved for FETCH functions */ - s32 i; - u8 **tbl; - - ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL); - - tbl = (reso == IMAGE_640) ? tbl_640 : tbl_1280; - - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, - tbl_length[0], tbl[0]); - for (i = 1; i < 7; i++) - ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, - tbl_length[i], tbl[i]); - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, - tbl_length[7], tbl[7]); - - n = fetch_validx(gspca_dev, tbl_init_post_alt, - ARRAY_SIZE(tbl_init_post_alt)); - - ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04); - keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, - ARRAY_SIZE(tbl_init_post_alt), n); - ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04); - keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, - ARRAY_SIZE(tbl_init_post_alt), n); - ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04); - keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, - ARRAY_SIZE(tbl_init_post_alt), n); - ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04); - keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, - ARRAY_SIZE(tbl_init_post_alt), n); - ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1); - keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, - ARRAY_SIZE(tbl_init_post_alt), n); - - ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04); - keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, - ARRAY_SIZE(tbl_init_post_alt), n); - ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04); - keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, - ARRAY_SIZE(tbl_init_post_alt), n); - ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04); - keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, - ARRAY_SIZE(tbl_init_post_alt), n); - ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04); - keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, - ARRAY_SIZE(tbl_init_post_alt), n); - ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1); - keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, - ARRAY_SIZE(tbl_init_post_alt), n); - - ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04); - keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, - ARRAY_SIZE(tbl_init_post_alt), n); - ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04); - keep_on_fetching_validx(gspca_dev, tbl_init_post_alt, - ARRAY_SIZE(tbl_init_post_alt), n); - - ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1); - - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post2); - ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post3); - - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post4); - ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post5); - - ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post6); - ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post7); - - ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post8); - - ov9655_camera_settings(gspca_dev); - - return 0; -} - -static int ov9655_configure_alt(struct gspca_dev *gspca_dev) -{ - s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv; - - switch (reso) { - case IMAGE_640: - gspca_dev->alt = 1 + 1; - break; - - default: - gspca_dev->alt = 1 + 1; - break; - } - return 0; -} - -static int ov9655_camera_settings(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - u8 dat_bright[] = "\x04\x00\x10\x7c\xa1\x00\x00\x70"; - - s32 bright = sd->vcur.brightness; - s32 hue = sd->vcur.hue; - - if (bright != sd->vold.brightness) { - sd->vold.brightness = bright; - if (bright < 0 || bright > sd->vmax.brightness) - bright = 0; - - dat_bright[3] = bright; - ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_bright); - } - - if (hue != sd->vold.hue) { - sd->vold.hue = hue; - sd->swapRB = (hue != 0); - } - - return 0; -} - -static void ov9655_post_unset_alt(struct gspca_dev *gspca_dev) -{ - ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL); - ctrl_out(gspca_dev, 0x40, 1, 0x0061, 0x0000, 0, NULL); -} diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c deleted file mode 100644 index ced3b71f14e5..000000000000 --- a/drivers/media/video/gspca/gl860/gl860.c +++ /dev/null @@ -1,725 +0,0 @@ -/* GSPCA subdrivers for Genesys Logic webcams with the GL860 chip - * Subdriver core - * - * 2009/09/24 Olivier Lorin <o.lorin@laposte.net> - * GSPCA by Jean-Francois Moine <http://moinejf.free.fr> - * Thanks BUGabundo and Malmostoso for your amazing help! - * - * 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 - * 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, see <http://www.gnu.org/licenses/>. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "gspca.h" -#include "gl860.h" - -MODULE_AUTHOR("Olivier Lorin <o.lorin@laposte.net>"); -MODULE_DESCRIPTION("Genesys Logic USB PC Camera Driver"); -MODULE_LICENSE("GPL"); - -/*======================== static function declarations ====================*/ - -static void (*dev_init_settings)(struct gspca_dev *gspca_dev); - -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id); -static int sd_init(struct gspca_dev *gspca_dev); -static int sd_isoc_init(struct gspca_dev *gspca_dev); -static int sd_start(struct gspca_dev *gspca_dev); -static void sd_stop0(struct gspca_dev *gspca_dev); -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, int len); -static void sd_callback(struct gspca_dev *gspca_dev); - -static int gl860_guess_sensor(struct gspca_dev *gspca_dev, - u16 vendor_id, u16 product_id); - -/*============================ driver options ==============================*/ - -static s32 AC50Hz = 0xff; -module_param(AC50Hz, int, 0644); -MODULE_PARM_DESC(AC50Hz, " Does AC power frequency is 50Hz? (0/1)"); - -static char sensor[7]; -module_param_string(sensor, sensor, sizeof(sensor), 0644); -MODULE_PARM_DESC(sensor, - " Driver sensor ('MI1320'/'MI2020'/'OV9655'/'OV2640')"); - -/*============================ webcam controls =============================*/ - -/* Functions to get and set a control value */ -#define SD_SETGET(thename) \ -static int sd_set_##thename(struct gspca_dev *gspca_dev, s32 val)\ -{\ - struct sd *sd = (struct sd *) gspca_dev;\ -\ - sd->vcur.thename = val;\ - if (gspca_dev->streaming)\ - sd->waitSet = 1;\ - return 0;\ -} \ -static int sd_get_##thename(struct gspca_dev *gspca_dev, s32 *val)\ -{\ - struct sd *sd = (struct sd *) gspca_dev;\ -\ - *val = sd->vcur.thename;\ - return 0;\ -} - -SD_SETGET(mirror) -SD_SETGET(flip) -SD_SETGET(AC50Hz) -SD_SETGET(backlight) -SD_SETGET(brightness) -SD_SETGET(gamma) -SD_SETGET(hue) -SD_SETGET(saturation) -SD_SETGET(sharpness) -SD_SETGET(whitebal) -SD_SETGET(contrast) - -#define GL860_NCTRLS 11 - -/* control table */ -static struct ctrl sd_ctrls_mi1320[GL860_NCTRLS]; -static struct ctrl sd_ctrls_mi2020[GL860_NCTRLS]; -static struct ctrl sd_ctrls_ov2640[GL860_NCTRLS]; -static struct ctrl sd_ctrls_ov9655[GL860_NCTRLS]; - -#define SET_MY_CTRL(theid, \ - thetype, thelabel, thename) \ - if (sd->vmax.thename != 0) {\ - sd_ctrls[nCtrls].qctrl.id = theid;\ - sd_ctrls[nCtrls].qctrl.type = thetype;\ - strcpy(sd_ctrls[nCtrls].qctrl.name, thelabel);\ - sd_ctrls[nCtrls].qctrl.minimum = 0;\ - sd_ctrls[nCtrls].qctrl.maximum = sd->vmax.thename;\ - sd_ctrls[nCtrls].qctrl.default_value = sd->vcur.thename;\ - sd_ctrls[nCtrls].qctrl.step = \ - (sd->vmax.thename < 16) ? 1 : sd->vmax.thename/16;\ - sd_ctrls[nCtrls].set = sd_set_##thename;\ - sd_ctrls[nCtrls].get = sd_get_##thename;\ - nCtrls++;\ - } - -static int gl860_build_control_table(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct ctrl *sd_ctrls; - int nCtrls = 0; - - if (_MI1320_) - sd_ctrls = sd_ctrls_mi1320; - else if (_MI2020_) - sd_ctrls = sd_ctrls_mi2020; - else if (_OV2640_) - sd_ctrls = sd_ctrls_ov2640; - else if (_OV9655_) - sd_ctrls = sd_ctrls_ov9655; - else - return 0; - - memset(sd_ctrls, 0, GL860_NCTRLS * sizeof(struct ctrl)); - - SET_MY_CTRL(V4L2_CID_BRIGHTNESS, - V4L2_CTRL_TYPE_INTEGER, "Brightness", brightness) - SET_MY_CTRL(V4L2_CID_SHARPNESS, - V4L2_CTRL_TYPE_INTEGER, "Sharpness", sharpness) - SET_MY_CTRL(V4L2_CID_CONTRAST, - V4L2_CTRL_TYPE_INTEGER, "Contrast", contrast) - SET_MY_CTRL(V4L2_CID_GAMMA, - V4L2_CTRL_TYPE_INTEGER, "Gamma", gamma) - SET_MY_CTRL(V4L2_CID_HUE, - V4L2_CTRL_TYPE_INTEGER, "Palette", hue) - SET_MY_CTRL(V4L2_CID_SATURATION, - V4L2_CTRL_TYPE_INTEGER, "Saturation", saturation) - SET_MY_CTRL(V4L2_CID_WHITE_BALANCE_TEMPERATURE, - V4L2_CTRL_TYPE_INTEGER, "White Bal.", whitebal) - SET_MY_CTRL(V4L2_CID_BACKLIGHT_COMPENSATION, - V4L2_CTRL_TYPE_INTEGER, "Backlight" , backlight) - - SET_MY_CTRL(V4L2_CID_HFLIP, - V4L2_CTRL_TYPE_BOOLEAN, "Mirror", mirror) - SET_MY_CTRL(V4L2_CID_VFLIP, - V4L2_CTRL_TYPE_BOOLEAN, "Flip", flip) - SET_MY_CTRL(V4L2_CID_POWER_LINE_FREQUENCY, - V4L2_CTRL_TYPE_BOOLEAN, "AC power 50Hz", AC50Hz) - - return nCtrls; -} - -/*==================== sud-driver structure initialisation =================*/ - -static const struct sd_desc sd_desc_mi1320 = { - .name = MODULE_NAME, - .ctrls = sd_ctrls_mi1320, - .nctrls = GL860_NCTRLS, - .config = sd_config, - .init = sd_init, - .isoc_init = sd_isoc_init, - .start = sd_start, - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, - .dq_callback = sd_callback, -}; - -static const struct sd_desc sd_desc_mi2020 = { - .name = MODULE_NAME, - .ctrls = sd_ctrls_mi2020, - .nctrls = GL860_NCTRLS, - .config = sd_config, - .init = sd_init, - .isoc_init = sd_isoc_init, - .start = sd_start, - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, - .dq_callback = sd_callback, -}; - -static const struct sd_desc sd_desc_ov2640 = { - .name = MODULE_NAME, - .ctrls = sd_ctrls_ov2640, - .nctrls = GL860_NCTRLS, - .config = sd_config, - .init = sd_init, - .isoc_init = sd_isoc_init, - .start = sd_start, - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, - .dq_callback = sd_callback, -}; - -static const struct sd_desc sd_desc_ov9655 = { - .name = MODULE_NAME, - .ctrls = sd_ctrls_ov9655, - .nctrls = GL860_NCTRLS, - .config = sd_config, - .init = sd_init, - .isoc_init = sd_isoc_init, - .start = sd_start, - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, - .dq_callback = sd_callback, -}; - -/*=========================== sub-driver image sizes =======================*/ - -static struct v4l2_pix_format mi2020_mode[] = { - { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - }, - { 800, 598, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 800, - .sizeimage = 800 * 598, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 - }, - {1280, 1024, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 1280, - .sizeimage = 1280 * 1024, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2 - }, - {1600, 1198, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 1600, - .sizeimage = 1600 * 1198, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 3 - }, -}; - -static struct v4l2_pix_format ov2640_mode[] = { - { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - }, - { 800, 600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 800, - .sizeimage = 800 * 600, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 - }, - {1280, 960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 1280, - .sizeimage = 1280 * 960, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2 - }, - {1600, 1200, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 1600, - .sizeimage = 1600 * 1200, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 3 - }, -}; - -static struct v4l2_pix_format mi1320_mode[] = { - { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - }, - { 800, 600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 800, - .sizeimage = 800 * 600, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 - }, - {1280, 960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 1280, - .sizeimage = 1280 * 960, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2 - }, -}; - -static struct v4l2_pix_format ov9655_mode[] = { - { 640, 480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - }, - {1280, 960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 1280, - .sizeimage = 1280 * 960, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 - }, -}; - -/*========================= sud-driver functions ===========================*/ - -/* This function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - u16 vendor_id, product_id; - - /* Get USB VendorID and ProductID */ - vendor_id = id->idVendor; - product_id = id->idProduct; - - sd->nbRightUp = 1; - sd->nbIm = -1; - - sd->sensor = 0xff; - if (strcmp(sensor, "MI1320") == 0) - sd->sensor = ID_MI1320; - else if (strcmp(sensor, "OV2640") == 0) - sd->sensor = ID_OV2640; - else if (strcmp(sensor, "OV9655") == 0) - sd->sensor = ID_OV9655; - else if (strcmp(sensor, "MI2020") == 0) - sd->sensor = ID_MI2020; - - /* Get sensor and set the suitable init/start/../stop functions */ - if (gl860_guess_sensor(gspca_dev, vendor_id, product_id) == -1) - return -1; - - cam = &gspca_dev->cam; - - switch (sd->sensor) { - case ID_MI1320: - gspca_dev->sd_desc = &sd_desc_mi1320; - cam->cam_mode = mi1320_mode; - cam->nmodes = ARRAY_SIZE(mi1320_mode); - dev_init_settings = mi1320_init_settings; - break; - - case ID_MI2020: - gspca_dev->sd_desc = &sd_desc_mi2020; - cam->cam_mode = mi2020_mode; - cam->nmodes = ARRAY_SIZE(mi2020_mode); - dev_init_settings = mi2020_init_settings; - break; - - case ID_OV2640: - gspca_dev->sd_desc = &sd_desc_ov2640; - cam->cam_mode = ov2640_mode; - cam->nmodes = ARRAY_SIZE(ov2640_mode); - dev_init_settings = ov2640_init_settings; - break; - - case ID_OV9655: - gspca_dev->sd_desc = &sd_desc_ov9655; - cam->cam_mode = ov9655_mode; - cam->nmodes = ARRAY_SIZE(ov9655_mode); - dev_init_settings = ov9655_init_settings; - break; - } - - dev_init_settings(gspca_dev); - if (AC50Hz != 0xff) - ((struct sd *) gspca_dev)->vcur.AC50Hz = AC50Hz; - gl860_build_control_table(gspca_dev); - - return 0; -} - -/* This function is called at probe time after sd_config */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - return sd->dev_init_at_startup(gspca_dev); -} - -/* This function is called before to choose the alt setting */ -static int sd_isoc_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - return sd->dev_configure_alt(gspca_dev); -} - -/* This function is called to start the webcam */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - return sd->dev_init_pre_alt(gspca_dev); -} - -/* This function is called to stop the webcam */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (!sd->gspca_dev.present) - return; - - return sd->dev_post_unset_alt(gspca_dev); -} - -/* This function is called when an image is being received */ -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - static s32 nSkipped; - - s32 mode = (s32) gspca_dev->curr_mode; - s32 nToSkip = - sd->swapRB * (gspca_dev->cam.cam_mode[mode].bytesperline + 1); - - /* Test only against 0202h, so endianess does not matter */ - switch (*(s16 *) data) { - case 0x0202: /* End of frame, start a new one */ - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - nSkipped = 0; - if (sd->nbIm >= 0 && sd->nbIm < 10) - sd->nbIm++; - gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); - break; - - default: - data += 2; - len -= 2; - if (nSkipped + len <= nToSkip) - nSkipped += len; - else { - if (nSkipped < nToSkip && nSkipped + len > nToSkip) { - data += nToSkip - nSkipped; - len -= nToSkip - nSkipped; - nSkipped = nToSkip + 1; - } - gspca_frame_add(gspca_dev, - INTER_PACKET, data, len); - } - break; - } -} - -/* This function is called when an image has been read */ -/* This function is used to monitor webcam orientation */ -static void sd_callback(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (!_OV9655_) { - u8 state; - u8 upsideDown; - - /* Probe sensor orientation */ - ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, (void *)&state); - - /* C8/40 means upside-down (looking backwards) */ - /* D8/50 means right-up (looking onwards) */ - upsideDown = (state == 0xc8 || state == 0x40); - - if (upsideDown && sd->nbRightUp > -4) { - if (sd->nbRightUp > 0) - sd->nbRightUp = 0; - if (sd->nbRightUp == -3) { - sd->mirrorMask = 1; - sd->waitSet = 1; - } - sd->nbRightUp--; - } - if (!upsideDown && sd->nbRightUp < 4) { - if (sd->nbRightUp < 0) - sd->nbRightUp = 0; - if (sd->nbRightUp == 3) { - sd->mirrorMask = 0; - sd->waitSet = 1; - } - sd->nbRightUp++; - } - } - - if (sd->waitSet) - sd->dev_camera_settings(gspca_dev); -} - -/*=================== USB driver structure initialisation ==================*/ - -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x05e3, 0x0503)}, - {USB_DEVICE(0x05e3, 0xf191)}, - {} -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, - &sd_desc_mi1320, sizeof(struct sd), THIS_MODULE); -} - -static void sd_disconnect(struct usb_interface *intf) -{ - gspca_disconnect(intf); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = sd_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -/*====================== Init and Exit module functions ====================*/ - -module_usb_driver(sd_driver); - -/*==========================================================================*/ - -int gl860_RTx(struct gspca_dev *gspca_dev, - unsigned char pref, u32 req, u16 val, u16 index, - s32 len, void *pdata) -{ - struct usb_device *udev = gspca_dev->dev; - s32 r = 0; - - if (pref == 0x40) { /* Send */ - if (len > 0) { - memcpy(gspca_dev->usb_buf, pdata, len); - r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - req, pref, val, index, - gspca_dev->usb_buf, - len, 400 + 200 * (len > 1)); - } else { - r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - req, pref, val, index, NULL, len, 400); - } - } else { /* Receive */ - if (len > 0) { - r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - req, pref, val, index, - gspca_dev->usb_buf, - len, 400 + 200 * (len > 1)); - memcpy(pdata, gspca_dev->usb_buf, len); - } else { - r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - req, pref, val, index, NULL, len, 400); - } - } - - if (r < 0) - pr_err("ctrl transfer failed %4d [p%02x r%d v%04x i%04x len%d]\n", - r, pref, req, val, index, len); - else if (len > 1 && r < len) - PDEBUG(D_ERR, "short ctrl transfer %d/%d", r, len); - - msleep(1); - - return r; -} - -int fetch_validx(struct gspca_dev *gspca_dev, struct validx *tbl, int len) -{ - int n; - - for (n = 0; n < len; n++) { - if (tbl[n].idx != 0xffff) - ctrl_out(gspca_dev, 0x40, 1, tbl[n].val, - tbl[n].idx, 0, NULL); - else if (tbl[n].val == 0xffff) - break; - else - msleep(tbl[n].val); - } - return n; -} - -int keep_on_fetching_validx(struct gspca_dev *gspca_dev, struct validx *tbl, - int len, int n) -{ - while (++n < len) { - if (tbl[n].idx != 0xffff) - ctrl_out(gspca_dev, 0x40, 1, tbl[n].val, tbl[n].idx, - 0, NULL); - else if (tbl[n].val == 0xffff) - break; - else - msleep(tbl[n].val); - } - return n; -} - -void fetch_idxdata(struct gspca_dev *gspca_dev, struct idxdata *tbl, int len) -{ - int n; - - for (n = 0; n < len; n++) { - if (memcmp(tbl[n].data, "\xff\xff\xff", 3) != 0) - ctrl_out(gspca_dev, 0x40, 3, 0x7a00, tbl[n].idx, - 3, tbl[n].data); - else - msleep(tbl[n].idx); - } -} - -static int gl860_guess_sensor(struct gspca_dev *gspca_dev, - u16 vendor_id, u16 product_id) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 probe, nb26, nb96, nOV, ntry; - - if (product_id == 0xf191) - sd->sensor = ID_MI1320; - - if (sd->sensor == 0xff) { - ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe); - ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe); - - ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x0000, 0, NULL); - msleep(3); - ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL); - msleep(3); - ctrl_out(gspca_dev, 0x40, 1, 0x0008, 0x00c0, 0, NULL); - msleep(3); - ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c1, 0, NULL); - msleep(3); - ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c2, 0, NULL); - msleep(3); - ctrl_out(gspca_dev, 0x40, 1, 0x0020, 0x0006, 0, NULL); - msleep(3); - ctrl_out(gspca_dev, 0x40, 1, 0x006a, 0x000d, 0, NULL); - msleep(56); - - PDEBUG(D_PROBE, "probing for sensor MI2020 or OVXXXX"); - nOV = 0; - for (ntry = 0; ntry < 4; ntry++) { - ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL); - msleep(3); - ctrl_out(gspca_dev, 0x40, 1, 0x0063, 0x0006, 0, NULL); - msleep(3); - ctrl_out(gspca_dev, 0x40, 1, 0x7a00, 0x8030, 0, NULL); - msleep(10); - ctrl_in(gspca_dev, 0xc0, 2, 0x7a00, 0x8030, 1, &probe); - PDEBUG(D_PROBE, "probe=0x%02x", probe); - if (probe == 0xff) - nOV++; - } - - if (nOV) { - PDEBUG(D_PROBE, "0xff -> OVXXXX"); - PDEBUG(D_PROBE, "probing for sensor OV2640 or OV9655"); - - nb26 = nb96 = 0; - for (ntry = 0; ntry < 4; ntry++) { - ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, - 0, NULL); - msleep(3); - ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x800a, - 0, NULL); - msleep(10); - - /* Wait for 26(OV2640) or 96(OV9655) */ - ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x800a, - 1, &probe); - - if (probe == 0x26 || probe == 0x40) { - PDEBUG(D_PROBE, - "probe=0x%02x -> OV2640", - probe); - sd->sensor = ID_OV2640; - nb26 += 4; - break; - } - if (probe == 0x96 || probe == 0x55) { - PDEBUG(D_PROBE, - "probe=0x%02x -> OV9655", - probe); - sd->sensor = ID_OV9655; - nb96 += 4; - break; - } - PDEBUG(D_PROBE, "probe=0x%02x", probe); - if (probe == 0x00) - nb26++; - if (probe == 0xff) - nb96++; - msleep(3); - } - if (nb26 < 4 && nb96 < 4) - return -1; - } else { - PDEBUG(D_PROBE, "Not any 0xff -> MI2020"); - sd->sensor = ID_MI2020; - } - } - - if (_MI1320_) { - PDEBUG(D_PROBE, "05e3:f191 sensor MI1320 (1.3M)"); - } else if (_MI2020_) { - PDEBUG(D_PROBE, "05e3:0503 sensor MI2020 (2.0M)"); - } else if (_OV9655_) { - PDEBUG(D_PROBE, "05e3:0503 sensor OV9655 (1.3M)"); - } else if (_OV2640_) { - PDEBUG(D_PROBE, "05e3:0503 sensor OV2640 (2.0M)"); - } else { - PDEBUG(D_PROBE, "***** Unknown sensor *****"); - return -1; - } - - return 0; -} diff --git a/drivers/media/video/gspca/gl860/gl860.h b/drivers/media/video/gspca/gl860/gl860.h deleted file mode 100644 index 0330a0293b9c..000000000000 --- a/drivers/media/video/gspca/gl860/gl860.h +++ /dev/null @@ -1,105 +0,0 @@ -/* GSPCA subdrivers for Genesys Logic webcams with the GL860 chip - * Subdriver declarations - * - * 2009/10/14 Olivier LORIN <o.lorin@laposte.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * 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, see <http://www.gnu.org/licenses/>. - */ -#ifndef GL860_DEV_H -#define GL860_DEV_H - -#include "gspca.h" - -#define MODULE_NAME "gspca_gl860" -#define DRIVER_VERSION "0.9d10" - -#define ctrl_in gl860_RTx -#define ctrl_out gl860_RTx - -#define ID_MI1320 1 -#define ID_OV2640 2 -#define ID_OV9655 4 -#define ID_MI2020 8 - -#define _MI1320_ (((struct sd *) gspca_dev)->sensor == ID_MI1320) -#define _MI2020_ (((struct sd *) gspca_dev)->sensor == ID_MI2020) -#define _OV2640_ (((struct sd *) gspca_dev)->sensor == ID_OV2640) -#define _OV9655_ (((struct sd *) gspca_dev)->sensor == ID_OV9655) - -#define IMAGE_640 0 -#define IMAGE_800 1 -#define IMAGE_1280 2 -#define IMAGE_1600 3 - -struct sd_gl860 { - u16 backlight; - u16 brightness; - u16 sharpness; - u16 contrast; - u16 gamma; - u16 hue; - u16 saturation; - u16 whitebal; - u8 mirror; - u8 flip; - u8 AC50Hz; -}; - -/* Specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - struct sd_gl860 vcur; - struct sd_gl860 vold; - struct sd_gl860 vmax; - - int (*dev_configure_alt) (struct gspca_dev *); - int (*dev_init_at_startup)(struct gspca_dev *); - int (*dev_init_pre_alt) (struct gspca_dev *); - void (*dev_post_unset_alt) (struct gspca_dev *); - int (*dev_camera_settings)(struct gspca_dev *); - - u8 swapRB; - u8 mirrorMask; - u8 sensor; - s32 nbIm; - s32 nbRightUp; - u8 waitSet; -}; - -struct validx { - u16 val; - u16 idx; -}; - -struct idxdata { - u8 idx; - u8 data[3]; -}; - -int fetch_validx(struct gspca_dev *gspca_dev, struct validx *tbl, int len); -int keep_on_fetching_validx(struct gspca_dev *gspca_dev, struct validx *tbl, - int len, int n); -void fetch_idxdata(struct gspca_dev *gspca_dev, struct idxdata *tbl, int len); - -int gl860_RTx(struct gspca_dev *gspca_dev, - unsigned char pref, u32 req, u16 val, u16 index, - s32 len, void *pdata); - -void mi1320_init_settings(struct gspca_dev *); -void ov2640_init_settings(struct gspca_dev *); -void ov9655_init_settings(struct gspca_dev *); -void mi2020_init_settings(struct gspca_dev *); - -#endif diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c deleted file mode 100644 index d4e8343f5b10..000000000000 --- a/drivers/media/video/gspca/gspca.c +++ /dev/null @@ -1,2456 +0,0 @@ -/* - * Main USB camera driver - * - * Copyright (C) 2008-2011 Jean-François Moine <http://moinejf.free.fr> - * - * Camera button input handling by Márton Németh - * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu> - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define GSPCA_VERSION "2.14.0" - -#include <linux/init.h> -#include <linux/fs.h> -#include <linux/vmalloc.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/string.h> -#include <linux/pagemap.h> -#include <linux/io.h> -#include <asm/page.h> -#include <linux/uaccess.h> -#include <linux/ktime.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-fh.h> -#include <media/v4l2-event.h> - -#include "gspca.h" - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) -#include <linux/input.h> -#include <linux/usb/input.h> -#endif - -/* global values */ -#define DEF_NURBS 3 /* default number of URBs */ -#if DEF_NURBS > MAX_NURBS -#error "DEF_NURBS too big" -#endif - -MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); -MODULE_DESCRIPTION("GSPCA USB Camera Driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(GSPCA_VERSION); - -#ifdef GSPCA_DEBUG -int gspca_debug = D_ERR | D_PROBE; -EXPORT_SYMBOL(gspca_debug); - -static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h) -{ - if ((pixfmt >> 24) >= '0' && (pixfmt >> 24) <= 'z') { - PDEBUG(D_CONF|D_STREAM, "%s %c%c%c%c %dx%d", - txt, - pixfmt & 0xff, - (pixfmt >> 8) & 0xff, - (pixfmt >> 16) & 0xff, - pixfmt >> 24, - w, h); - } else { - PDEBUG(D_CONF|D_STREAM, "%s 0x%08x %dx%d", - txt, - pixfmt, - w, h); - } -} -#else -#define PDEBUG_MODE(txt, pixfmt, w, h) -#endif - -/* specific memory types - !! should be different from V4L2_MEMORY_xxx */ -#define GSPCA_MEMORY_NO 0 /* V4L2_MEMORY_xxx starts from 1 */ -#define GSPCA_MEMORY_READ 7 - -#define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE) - -/* - * VMA operations. - */ -static void gspca_vm_open(struct vm_area_struct *vma) -{ - struct gspca_frame *frame = vma->vm_private_data; - - frame->vma_use_count++; - frame->v4l2_buf.flags |= V4L2_BUF_FLAG_MAPPED; -} - -static void gspca_vm_close(struct vm_area_struct *vma) -{ - struct gspca_frame *frame = vma->vm_private_data; - - if (--frame->vma_use_count <= 0) - frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_MAPPED; -} - -static const struct vm_operations_struct gspca_vm_ops = { - .open = gspca_vm_open, - .close = gspca_vm_close, -}; - -/* - * Input and interrupt endpoint handling functions - */ -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) -static void int_irq(struct urb *urb) -{ - struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; - int ret; - - ret = urb->status; - switch (ret) { - case 0: - if (gspca_dev->sd_desc->int_pkt_scan(gspca_dev, - urb->transfer_buffer, urb->actual_length) < 0) { - PDEBUG(D_ERR, "Unknown packet received"); - } - break; - - case -ENOENT: - case -ECONNRESET: - case -ENODEV: - case -ESHUTDOWN: - /* Stop is requested either by software or hardware is gone, - * keep the ret value non-zero and don't resubmit later. - */ - break; - - default: - PDEBUG(D_ERR, "URB error %i, resubmitting", urb->status); - urb->status = 0; - ret = 0; - } - - if (ret == 0) { - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret < 0) - pr_err("Resubmit URB failed with error %i\n", ret); - } -} - -static int gspca_input_connect(struct gspca_dev *dev) -{ - struct input_dev *input_dev; - int err = 0; - - dev->input_dev = NULL; - if (dev->sd_desc->int_pkt_scan || dev->sd_desc->other_input) { - input_dev = input_allocate_device(); - if (!input_dev) - return -ENOMEM; - - usb_make_path(dev->dev, dev->phys, sizeof(dev->phys)); - strlcat(dev->phys, "/input0", sizeof(dev->phys)); - - input_dev->name = dev->sd_desc->name; - input_dev->phys = dev->phys; - - usb_to_input_id(dev->dev, &input_dev->id); - - input_dev->evbit[0] = BIT_MASK(EV_KEY); - input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA); - input_dev->dev.parent = &dev->dev->dev; - - err = input_register_device(input_dev); - if (err) { - pr_err("Input device registration failed with error %i\n", - err); - input_dev->dev.parent = NULL; - input_free_device(input_dev); - } else { - dev->input_dev = input_dev; - } - } - - return err; -} - -static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, - struct usb_endpoint_descriptor *ep) -{ - unsigned int buffer_len; - int interval; - struct urb *urb; - struct usb_device *dev; - void *buffer = NULL; - int ret = -EINVAL; - - buffer_len = le16_to_cpu(ep->wMaxPacketSize); - interval = ep->bInterval; - PDEBUG(D_CONF, "found int in endpoint: 0x%x, " - "buffer_len=%u, interval=%u", - ep->bEndpointAddress, buffer_len, interval); - - dev = gspca_dev->dev; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - ret = -ENOMEM; - goto error; - } - - buffer = usb_alloc_coherent(dev, buffer_len, - GFP_KERNEL, &urb->transfer_dma); - if (!buffer) { - ret = -ENOMEM; - goto error_buffer; - } - usb_fill_int_urb(urb, dev, - usb_rcvintpipe(dev, ep->bEndpointAddress), - buffer, buffer_len, - int_irq, (void *)gspca_dev, interval); - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - ret = usb_submit_urb(urb, GFP_KERNEL); - if (ret < 0) { - PDEBUG(D_ERR, "submit int URB failed with error %i", ret); - goto error_submit; - } - gspca_dev->int_urb = urb; - return ret; - -error_submit: - usb_free_coherent(dev, - urb->transfer_buffer_length, - urb->transfer_buffer, - urb->transfer_dma); -error_buffer: - usb_free_urb(urb); -error: - return ret; -} - -static void gspca_input_create_urb(struct gspca_dev *gspca_dev) -{ - struct usb_interface *intf; - struct usb_host_interface *intf_desc; - struct usb_endpoint_descriptor *ep; - int i; - - if (gspca_dev->sd_desc->int_pkt_scan) { - intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); - intf_desc = intf->cur_altsetting; - for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) { - ep = &intf_desc->endpoint[i].desc; - if (usb_endpoint_dir_in(ep) && - usb_endpoint_xfer_int(ep)) { - - alloc_and_submit_int_urb(gspca_dev, ep); - break; - } - } - } -} - -static void gspca_input_destroy_urb(struct gspca_dev *gspca_dev) -{ - struct urb *urb; - - urb = gspca_dev->int_urb; - if (urb) { - gspca_dev->int_urb = NULL; - usb_kill_urb(urb); - usb_free_coherent(gspca_dev->dev, - urb->transfer_buffer_length, - urb->transfer_buffer, - urb->transfer_dma); - usb_free_urb(urb); - } -} -#else -static inline void gspca_input_destroy_urb(struct gspca_dev *gspca_dev) -{ -} - -static inline void gspca_input_create_urb(struct gspca_dev *gspca_dev) -{ -} - -static inline int gspca_input_connect(struct gspca_dev *dev) -{ - return 0; -} -#endif - -/* - * fill a video frame from an URB and resubmit - */ -static void fill_frame(struct gspca_dev *gspca_dev, - struct urb *urb) -{ - u8 *data; /* address of data in the iso message */ - int i, len, st; - cam_pkt_op pkt_scan; - - if (urb->status != 0) { - if (urb->status == -ESHUTDOWN) - return; /* disconnection */ -#ifdef CONFIG_PM - if (gspca_dev->frozen) - return; -#endif - PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); - urb->status = 0; - goto resubmit; - } - pkt_scan = gspca_dev->sd_desc->pkt_scan; - for (i = 0; i < urb->number_of_packets; i++) { - len = urb->iso_frame_desc[i].actual_length; - - /* check the packet status and length */ - st = urb->iso_frame_desc[i].status; - if (st) { - pr_err("ISOC data error: [%d] len=%d, status=%d\n", - i, len, st); - gspca_dev->last_packet_type = DISCARD_PACKET; - continue; - } - if (len == 0) { - if (gspca_dev->empty_packet == 0) - gspca_dev->empty_packet = 1; - continue; - } - - /* let the packet be analyzed by the subdriver */ - PDEBUG(D_PACK, "packet [%d] o:%d l:%d", - i, urb->iso_frame_desc[i].offset, len); - data = (u8 *) urb->transfer_buffer - + urb->iso_frame_desc[i].offset; - pkt_scan(gspca_dev, data, len); - } - -resubmit: - /* resubmit the URB */ - st = usb_submit_urb(urb, GFP_ATOMIC); - if (st < 0) - pr_err("usb_submit_urb() ret %d\n", st); -} - -/* - * ISOC message interrupt from the USB device - * - * Analyse each packet and call the subdriver for copy to the frame buffer. - */ -static void isoc_irq(struct urb *urb) -{ - struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; - - PDEBUG(D_PACK, "isoc irq"); - if (!gspca_dev->streaming) - return; - fill_frame(gspca_dev, urb); -} - -/* - * bulk message interrupt from the USB device - */ -static void bulk_irq(struct urb *urb) -{ - struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; - int st; - - PDEBUG(D_PACK, "bulk irq"); - if (!gspca_dev->streaming) - return; - switch (urb->status) { - case 0: - break; - case -ESHUTDOWN: - return; /* disconnection */ - default: -#ifdef CONFIG_PM - if (gspca_dev->frozen) - return; -#endif - PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); - urb->status = 0; - goto resubmit; - } - - PDEBUG(D_PACK, "packet l:%d", urb->actual_length); - gspca_dev->sd_desc->pkt_scan(gspca_dev, - urb->transfer_buffer, - urb->actual_length); - -resubmit: - /* resubmit the URB */ - if (gspca_dev->cam.bulk_nurbs != 0) { - st = usb_submit_urb(urb, GFP_ATOMIC); - if (st < 0) - pr_err("usb_submit_urb() ret %d\n", st); - } -} - -/* - * add data to the current frame - * - * This function is called by the subdrivers at interrupt level. - * - * To build a frame, these ones must add - * - one FIRST_PACKET - * - 0 or many INTER_PACKETs - * - one LAST_PACKET - * DISCARD_PACKET invalidates the whole frame. - */ -void gspca_frame_add(struct gspca_dev *gspca_dev, - enum gspca_packet_type packet_type, - const u8 *data, - int len) -{ - struct gspca_frame *frame; - int i, j; - - PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len); - - if (packet_type == FIRST_PACKET) { - i = atomic_read(&gspca_dev->fr_i); - - /* if there are no queued buffer, discard the whole frame */ - if (i == atomic_read(&gspca_dev->fr_q)) { - gspca_dev->last_packet_type = DISCARD_PACKET; - gspca_dev->sequence++; - return; - } - j = gspca_dev->fr_queue[i]; - frame = &gspca_dev->frame[j]; - frame->v4l2_buf.timestamp = ktime_to_timeval(ktime_get()); - frame->v4l2_buf.sequence = gspca_dev->sequence++; - gspca_dev->image = frame->data; - gspca_dev->image_len = 0; - } else { - switch (gspca_dev->last_packet_type) { - case DISCARD_PACKET: - if (packet_type == LAST_PACKET) { - gspca_dev->last_packet_type = packet_type; - gspca_dev->image = NULL; - gspca_dev->image_len = 0; - } - return; - case LAST_PACKET: - return; - } - } - - /* append the packet to the frame buffer */ - if (len > 0) { - if (gspca_dev->image_len + len > gspca_dev->frsz) { - PDEBUG(D_ERR|D_PACK, "frame overflow %d > %d", - gspca_dev->image_len + len, - gspca_dev->frsz); - packet_type = DISCARD_PACKET; - } else { -/* !! image is NULL only when last pkt is LAST or DISCARD - if (gspca_dev->image == NULL) { - pr_err("gspca_frame_add() image == NULL\n"); - return; - } - */ - memcpy(gspca_dev->image + gspca_dev->image_len, - data, len); - gspca_dev->image_len += len; - } - } - gspca_dev->last_packet_type = packet_type; - - /* if last packet, invalidate packet concatenation until - * next first packet, wake up the application and advance - * in the queue */ - if (packet_type == LAST_PACKET) { - i = atomic_read(&gspca_dev->fr_i); - j = gspca_dev->fr_queue[i]; - frame = &gspca_dev->frame[j]; - frame->v4l2_buf.bytesused = gspca_dev->image_len; - frame->v4l2_buf.flags = (frame->v4l2_buf.flags - | V4L2_BUF_FLAG_DONE) - & ~V4L2_BUF_FLAG_QUEUED; - i = (i + 1) % GSPCA_MAX_FRAMES; - atomic_set(&gspca_dev->fr_i, i); - wake_up_interruptible(&gspca_dev->wq); /* event = new frame */ - PDEBUG(D_FRAM, "frame complete len:%d", - frame->v4l2_buf.bytesused); - gspca_dev->image = NULL; - gspca_dev->image_len = 0; - } -} -EXPORT_SYMBOL(gspca_frame_add); - -static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file, - enum v4l2_memory memory, unsigned int count) -{ - struct gspca_frame *frame; - unsigned int frsz; - int i; - - i = gspca_dev->curr_mode; - frsz = gspca_dev->cam.cam_mode[i].sizeimage; - PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz); - frsz = PAGE_ALIGN(frsz); - if (count >= GSPCA_MAX_FRAMES) - count = GSPCA_MAX_FRAMES - 1; - gspca_dev->frbuf = vmalloc_32(frsz * count); - if (!gspca_dev->frbuf) { - pr_err("frame alloc failed\n"); - return -ENOMEM; - } - gspca_dev->capt_file = file; - gspca_dev->memory = memory; - gspca_dev->frsz = frsz; - gspca_dev->nframes = count; - for (i = 0; i < count; i++) { - frame = &gspca_dev->frame[i]; - frame->v4l2_buf.index = i; - frame->v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - frame->v4l2_buf.flags = 0; - frame->v4l2_buf.field = V4L2_FIELD_NONE; - frame->v4l2_buf.length = frsz; - frame->v4l2_buf.memory = memory; - frame->v4l2_buf.sequence = 0; - frame->data = gspca_dev->frbuf + i * frsz; - frame->v4l2_buf.m.offset = i * frsz; - } - atomic_set(&gspca_dev->fr_q, 0); - atomic_set(&gspca_dev->fr_i, 0); - gspca_dev->fr_o = 0; - return 0; -} - -static void frame_free(struct gspca_dev *gspca_dev) -{ - int i; - - PDEBUG(D_STREAM, "frame free"); - if (gspca_dev->frbuf != NULL) { - vfree(gspca_dev->frbuf); - gspca_dev->frbuf = NULL; - for (i = 0; i < gspca_dev->nframes; i++) - gspca_dev->frame[i].data = NULL; - } - gspca_dev->nframes = 0; - gspca_dev->frsz = 0; - gspca_dev->capt_file = NULL; - gspca_dev->memory = GSPCA_MEMORY_NO; -} - -static void destroy_urbs(struct gspca_dev *gspca_dev) -{ - struct urb *urb; - unsigned int i; - - PDEBUG(D_STREAM, "kill transfer"); - for (i = 0; i < MAX_NURBS; i++) { - urb = gspca_dev->urb[i]; - if (urb == NULL) - break; - - gspca_dev->urb[i] = NULL; - usb_kill_urb(urb); - if (urb->transfer_buffer != NULL) - usb_free_coherent(gspca_dev->dev, - urb->transfer_buffer_length, - urb->transfer_buffer, - urb->transfer_dma); - usb_free_urb(urb); - } -} - -static int gspca_set_alt0(struct gspca_dev *gspca_dev) -{ - int ret; - - if (gspca_dev->alt == 0) - return 0; - ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0); - if (ret < 0) - pr_err("set alt 0 err %d\n", ret); - return ret; -} - -/* Note: both the queue and the usb locks should be held when calling this */ -static void gspca_stream_off(struct gspca_dev *gspca_dev) -{ - gspca_dev->streaming = 0; - gspca_dev->usb_err = 0; - if (gspca_dev->sd_desc->stopN) - gspca_dev->sd_desc->stopN(gspca_dev); - destroy_urbs(gspca_dev); - gspca_input_destroy_urb(gspca_dev); - gspca_set_alt0(gspca_dev); - gspca_input_create_urb(gspca_dev); - if (gspca_dev->sd_desc->stop0) - gspca_dev->sd_desc->stop0(gspca_dev); - PDEBUG(D_STREAM, "stream off OK"); -} - -/* - * look for an input transfer endpoint in an alternate setting - */ -static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt, - int xfer) -{ - struct usb_host_endpoint *ep; - int i, attr; - - for (i = 0; i < alt->desc.bNumEndpoints; i++) { - ep = &alt->endpoint[i]; - attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - if (attr == xfer - && ep->desc.wMaxPacketSize != 0 - && usb_endpoint_dir_in(&ep->desc)) - return ep; - } - return NULL; -} - -/* compute the minimum bandwidth for the current transfer */ -static u32 which_bandwidth(struct gspca_dev *gspca_dev) -{ - u32 bandwidth; - int i; - - /* get the (max) image size */ - i = gspca_dev->curr_mode; - bandwidth = gspca_dev->cam.cam_mode[i].sizeimage; - - /* if the image is compressed, estimate its mean size */ - if (!gspca_dev->cam.needs_full_bandwidth && - bandwidth < gspca_dev->cam.cam_mode[i].width * - gspca_dev->cam.cam_mode[i].height) - bandwidth = bandwidth * 3 / 8; /* 0.375 */ - - /* estimate the frame rate */ - if (gspca_dev->sd_desc->get_streamparm) { - struct v4l2_streamparm parm; - - gspca_dev->sd_desc->get_streamparm(gspca_dev, &parm); - bandwidth *= parm.parm.capture.timeperframe.denominator; - bandwidth /= parm.parm.capture.timeperframe.numerator; - } else { - - /* don't hope more than 15 fps with USB 1.1 and - * image resolution >= 640x480 */ - if (gspca_dev->width >= 640 - && gspca_dev->dev->speed == USB_SPEED_FULL) - bandwidth *= 15; /* 15 fps */ - else - bandwidth *= 30; /* 30 fps */ - } - - PDEBUG(D_STREAM, "min bandwidth: %d", bandwidth); - return bandwidth; -} - -/* endpoint table */ -#define MAX_ALT 16 -struct ep_tb_s { - u32 alt; - u32 bandwidth; -}; - -/* - * build the table of the endpoints - * and compute the minimum bandwidth for the image transfer - */ -static int build_isoc_ep_tb(struct gspca_dev *gspca_dev, - struct usb_interface *intf, - struct ep_tb_s *ep_tb) -{ - struct usb_host_endpoint *ep; - int i, j, nbalt, psize, found; - u32 bandwidth, last_bw; - - nbalt = intf->num_altsetting; - if (nbalt > MAX_ALT) - nbalt = MAX_ALT; /* fixme: should warn */ - - /* build the endpoint table */ - i = 0; - last_bw = 0; - for (;;) { - ep_tb->bandwidth = 2000 * 2000 * 120; - found = 0; - for (j = 0; j < nbalt; j++) { - ep = alt_xfer(&intf->altsetting[j], - USB_ENDPOINT_XFER_ISOC); - if (ep == NULL) - continue; - if (ep->desc.bInterval == 0) { - pr_err("alt %d iso endp with 0 interval\n", j); - continue; - } - psize = le16_to_cpu(ep->desc.wMaxPacketSize); - psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); - bandwidth = psize * 1000; - if (gspca_dev->dev->speed == USB_SPEED_HIGH - || gspca_dev->dev->speed == USB_SPEED_SUPER) - bandwidth *= 8; - bandwidth /= 1 << (ep->desc.bInterval - 1); - if (bandwidth <= last_bw) - continue; - if (bandwidth < ep_tb->bandwidth) { - ep_tb->bandwidth = bandwidth; - ep_tb->alt = j; - found = 1; - } - } - if (!found) - break; - PDEBUG(D_STREAM, "alt %d bandwidth %d", - ep_tb->alt, ep_tb->bandwidth); - last_bw = ep_tb->bandwidth; - i++; - ep_tb++; - } - - /* - * If the camera: - * has a usb audio class interface (a built in usb mic); and - * is a usb 1 full speed device; and - * uses the max full speed iso bandwidth; and - * and has more than 1 alt setting - * then skip the highest alt setting to spare bandwidth for the mic - */ - if (gspca_dev->audio && - gspca_dev->dev->speed == USB_SPEED_FULL && - last_bw >= 1000000 && - i > 1) { - PDEBUG(D_STREAM, "dev has usb audio, skipping highest alt"); - i--; - ep_tb--; - } - - /* get the requested bandwidth and start at the highest atlsetting */ - bandwidth = which_bandwidth(gspca_dev); - ep_tb--; - while (i > 1) { - ep_tb--; - if (ep_tb->bandwidth < bandwidth) - break; - i--; - } - return i; -} - -/* - * create the URBs for image transfer - */ -static int create_urbs(struct gspca_dev *gspca_dev, - struct usb_host_endpoint *ep) -{ - struct urb *urb; - int n, nurbs, i, psize, npkt, bsize; - - /* calculate the packet size and the number of packets */ - psize = le16_to_cpu(ep->desc.wMaxPacketSize); - - if (!gspca_dev->cam.bulk) { /* isoc */ - - /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ - if (gspca_dev->pkt_size == 0) - psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); - else - psize = gspca_dev->pkt_size; - npkt = gspca_dev->cam.npkt; - if (npkt == 0) - npkt = 32; /* default value */ - bsize = psize * npkt; - PDEBUG(D_STREAM, - "isoc %d pkts size %d = bsize:%d", - npkt, psize, bsize); - nurbs = DEF_NURBS; - } else { /* bulk */ - npkt = 0; - bsize = gspca_dev->cam.bulk_size; - if (bsize == 0) - bsize = psize; - PDEBUG(D_STREAM, "bulk bsize:%d", bsize); - if (gspca_dev->cam.bulk_nurbs != 0) - nurbs = gspca_dev->cam.bulk_nurbs; - else - nurbs = 1; - } - - for (n = 0; n < nurbs; n++) { - urb = usb_alloc_urb(npkt, GFP_KERNEL); - if (!urb) { - pr_err("usb_alloc_urb failed\n"); - return -ENOMEM; - } - gspca_dev->urb[n] = urb; - urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev, - bsize, - GFP_KERNEL, - &urb->transfer_dma); - - if (urb->transfer_buffer == NULL) { - pr_err("usb_alloc_coherent failed\n"); - return -ENOMEM; - } - urb->dev = gspca_dev->dev; - urb->context = gspca_dev; - urb->transfer_buffer_length = bsize; - if (npkt != 0) { /* ISOC */ - urb->pipe = usb_rcvisocpipe(gspca_dev->dev, - ep->desc.bEndpointAddress); - urb->transfer_flags = URB_ISO_ASAP - | URB_NO_TRANSFER_DMA_MAP; - urb->interval = 1 << (ep->desc.bInterval - 1); - urb->complete = isoc_irq; - urb->number_of_packets = npkt; - for (i = 0; i < npkt; i++) { - urb->iso_frame_desc[i].length = psize; - urb->iso_frame_desc[i].offset = psize * i; - } - } else { /* bulk */ - urb->pipe = usb_rcvbulkpipe(gspca_dev->dev, - ep->desc.bEndpointAddress); - urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; - urb->complete = bulk_irq; - } - } - return 0; -} - -/* - * start the USB transfer - */ -static int gspca_init_transfer(struct gspca_dev *gspca_dev) -{ - struct usb_interface *intf; - struct usb_host_endpoint *ep; - struct urb *urb; - struct ep_tb_s ep_tb[MAX_ALT]; - int n, ret, xfer, alt, alt_idx; - - /* reset the streaming variables */ - gspca_dev->image = NULL; - gspca_dev->image_len = 0; - gspca_dev->last_packet_type = DISCARD_PACKET; - gspca_dev->sequence = 0; - - gspca_dev->usb_err = 0; - - /* do the specific subdriver stuff before endpoint selection */ - intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); - gspca_dev->alt = gspca_dev->cam.bulk ? intf->num_altsetting : 0; - if (gspca_dev->sd_desc->isoc_init) { - ret = gspca_dev->sd_desc->isoc_init(gspca_dev); - if (ret < 0) - return ret; - } - xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK - : USB_ENDPOINT_XFER_ISOC; - - /* if bulk or the subdriver forced an altsetting, get the endpoint */ - if (gspca_dev->alt != 0) { - gspca_dev->alt--; /* (previous version compatibility) */ - ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer); - if (ep == NULL) { - pr_err("bad altsetting %d\n", gspca_dev->alt); - return -EIO; - } - ep_tb[0].alt = gspca_dev->alt; - alt_idx = 1; - } else { - - /* else, compute the minimum bandwidth - * and build the endpoint table */ - alt_idx = build_isoc_ep_tb(gspca_dev, intf, ep_tb); - if (alt_idx <= 0) { - pr_err("no transfer endpoint found\n"); - return -EIO; - } - } - - /* set the highest alternate setting and - * loop until urb submit succeeds */ - gspca_input_destroy_urb(gspca_dev); - - gspca_dev->alt = ep_tb[--alt_idx].alt; - alt = -1; - for (;;) { - if (alt != gspca_dev->alt) { - alt = gspca_dev->alt; - if (intf->num_altsetting > 1) { - ret = usb_set_interface(gspca_dev->dev, - gspca_dev->iface, - alt); - if (ret < 0) { - if (ret == -ENOSPC) - goto retry; /*fixme: ugly*/ - pr_err("set alt %d err %d\n", alt, ret); - goto out; - } - } - } - if (!gspca_dev->cam.no_urb_create) { - PDEBUG(D_STREAM, "init transfer alt %d", alt); - ret = create_urbs(gspca_dev, - alt_xfer(&intf->altsetting[alt], xfer)); - if (ret < 0) { - destroy_urbs(gspca_dev); - goto out; - } - } - - /* clear the bulk endpoint */ - if (gspca_dev->cam.bulk) - usb_clear_halt(gspca_dev->dev, - gspca_dev->urb[0]->pipe); - - /* start the cam */ - ret = gspca_dev->sd_desc->start(gspca_dev); - if (ret < 0) { - destroy_urbs(gspca_dev); - goto out; - } - gspca_dev->streaming = 1; - v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler); - - /* some bulk transfers are started by the subdriver */ - if (gspca_dev->cam.bulk && gspca_dev->cam.bulk_nurbs == 0) - break; - - /* submit the URBs */ - for (n = 0; n < MAX_NURBS; n++) { - urb = gspca_dev->urb[n]; - if (urb == NULL) - break; - ret = usb_submit_urb(urb, GFP_KERNEL); - if (ret < 0) - break; - } - if (ret >= 0) - break; /* transfer is started */ - - /* something when wrong - * stop the webcam and free the transfer resources */ - gspca_stream_off(gspca_dev); - if (ret != -ENOSPC) { - pr_err("usb_submit_urb alt %d err %d\n", - gspca_dev->alt, ret); - goto out; - } - - /* the bandwidth is not wide enough - * negotiate or try a lower alternate setting */ -retry: - PDEBUG(D_ERR|D_STREAM, - "alt %d - bandwidth not wide enough - trying again", - alt); - msleep(20); /* wait for kill complete */ - if (gspca_dev->sd_desc->isoc_nego) { - ret = gspca_dev->sd_desc->isoc_nego(gspca_dev); - if (ret < 0) - goto out; - } else { - if (alt_idx <= 0) { - pr_err("no transfer endpoint found\n"); - ret = -EIO; - goto out; - } - gspca_dev->alt = ep_tb[--alt_idx].alt; - } - } -out: - gspca_input_create_urb(gspca_dev); - return ret; -} - -static void gspca_set_default_mode(struct gspca_dev *gspca_dev) -{ - struct gspca_ctrl *ctrl; - int i; - - i = gspca_dev->cam.nmodes - 1; /* take the highest mode */ - gspca_dev->curr_mode = i; - gspca_dev->width = gspca_dev->cam.cam_mode[i].width; - gspca_dev->height = gspca_dev->cam.cam_mode[i].height; - gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixelformat; - - /* set the current control values to their default values - * which may have changed in sd_init() */ - /* does nothing if ctrl_handler == NULL */ - v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler); - ctrl = gspca_dev->cam.ctrls; - if (ctrl != NULL) { - for (i = 0; - i < gspca_dev->sd_desc->nctrls; - i++, ctrl++) - ctrl->val = ctrl->def; - } -} - -static int wxh_to_mode(struct gspca_dev *gspca_dev, - int width, int height) -{ - int i; - - for (i = gspca_dev->cam.nmodes; --i > 0; ) { - if (width >= gspca_dev->cam.cam_mode[i].width - && height >= gspca_dev->cam.cam_mode[i].height) - break; - } - return i; -} - -/* - * search a mode with the right pixel format - */ -static int gspca_get_mode(struct gspca_dev *gspca_dev, - int mode, - int pixfmt) -{ - int modeU, modeD; - - modeU = modeD = mode; - while ((modeU < gspca_dev->cam.nmodes) || modeD >= 0) { - if (--modeD >= 0) { - if (gspca_dev->cam.cam_mode[modeD].pixelformat - == pixfmt) - return modeD; - } - if (++modeU < gspca_dev->cam.nmodes) { - if (gspca_dev->cam.cam_mode[modeU].pixelformat - == pixfmt) - return modeU; - } - } - return -EINVAL; -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int vidioc_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - - gspca_dev->usb_err = 0; - return gspca_dev->sd_desc->get_register(gspca_dev, reg); -} - -static int vidioc_s_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - - gspca_dev->usb_err = 0; - return gspca_dev->sd_desc->set_register(gspca_dev, reg); -} -#endif - -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - - gspca_dev->usb_err = 0; - return gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip); -} - -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *fmtdesc) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - int i, j, index; - __u32 fmt_tb[8]; - - /* give an index to each format */ - index = 0; - j = 0; - for (i = gspca_dev->cam.nmodes; --i >= 0; ) { - fmt_tb[index] = gspca_dev->cam.cam_mode[i].pixelformat; - j = 0; - for (;;) { - if (fmt_tb[j] == fmt_tb[index]) - break; - j++; - } - if (j == index) { - if (fmtdesc->index == index) - break; /* new format */ - index++; - if (index >= ARRAY_SIZE(fmt_tb)) - return -EINVAL; - } - } - if (i < 0) - return -EINVAL; /* no more format */ - - fmtdesc->pixelformat = fmt_tb[index]; - if (gspca_dev->cam.cam_mode[i].sizeimage < - gspca_dev->cam.cam_mode[i].width * - gspca_dev->cam.cam_mode[i].height) - fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED; - fmtdesc->description[0] = fmtdesc->pixelformat & 0xff; - fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff; - fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff; - fmtdesc->description[3] = fmtdesc->pixelformat >> 24; - fmtdesc->description[4] = '\0'; - return 0; -} - -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - int mode; - - mode = gspca_dev->curr_mode; - fmt->fmt.pix = gspca_dev->cam.cam_mode[mode]; - /* some drivers use priv internally, zero it before giving it to - userspace */ - fmt->fmt.pix.priv = 0; - return 0; -} - -static int try_fmt_vid_cap(struct gspca_dev *gspca_dev, - struct v4l2_format *fmt) -{ - int w, h, mode, mode2; - - w = fmt->fmt.pix.width; - h = fmt->fmt.pix.height; - -#ifdef GSPCA_DEBUG - if (gspca_debug & D_CONF) - PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h); -#endif - /* search the closest mode for width and height */ - mode = wxh_to_mode(gspca_dev, w, h); - - /* OK if right palette */ - if (gspca_dev->cam.cam_mode[mode].pixelformat - != fmt->fmt.pix.pixelformat) { - - /* else, search the closest mode with the same pixel format */ - mode2 = gspca_get_mode(gspca_dev, mode, - fmt->fmt.pix.pixelformat); - if (mode2 >= 0) - mode = mode2; -/* else - ; * no chance, return this mode */ - } - fmt->fmt.pix = gspca_dev->cam.cam_mode[mode]; - /* some drivers use priv internally, zero it before giving it to - userspace */ - fmt->fmt.pix.priv = 0; - return mode; /* used when s_fmt */ -} - -static int vidioc_try_fmt_vid_cap(struct file *file, - void *priv, - struct v4l2_format *fmt) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - int ret; - - ret = try_fmt_vid_cap(gspca_dev, fmt); - if (ret < 0) - return ret; - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - int ret; - - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - - ret = try_fmt_vid_cap(gspca_dev, fmt); - if (ret < 0) - goto out; - - if (gspca_dev->nframes != 0 - && fmt->fmt.pix.sizeimage > gspca_dev->frsz) { - ret = -EINVAL; - goto out; - } - - if (ret == gspca_dev->curr_mode) { - ret = 0; - goto out; /* same mode */ - } - - if (gspca_dev->streaming) { - ret = -EBUSY; - goto out; - } - gspca_dev->width = fmt->fmt.pix.width; - gspca_dev->height = fmt->fmt.pix.height; - gspca_dev->pixfmt = fmt->fmt.pix.pixelformat; - gspca_dev->curr_mode = ret; - - ret = 0; -out: - mutex_unlock(&gspca_dev->queue_lock); - return ret; -} - -static int vidioc_enum_framesizes(struct file *file, void *priv, - struct v4l2_frmsizeenum *fsize) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - int i; - __u32 index = 0; - - for (i = 0; i < gspca_dev->cam.nmodes; i++) { - if (fsize->pixel_format != - gspca_dev->cam.cam_mode[i].pixelformat) - continue; - - if (fsize->index == index) { - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - fsize->discrete.width = - gspca_dev->cam.cam_mode[i].width; - fsize->discrete.height = - gspca_dev->cam.cam_mode[i].height; - return 0; - } - index++; - } - - return -EINVAL; -} - -static int vidioc_enum_frameintervals(struct file *filp, void *priv, - struct v4l2_frmivalenum *fival) -{ - struct gspca_dev *gspca_dev = video_drvdata(filp); - int mode = wxh_to_mode(gspca_dev, fival->width, fival->height); - __u32 i; - - if (gspca_dev->cam.mode_framerates == NULL || - gspca_dev->cam.mode_framerates[mode].nrates == 0) - return -EINVAL; - - if (fival->pixel_format != - gspca_dev->cam.cam_mode[mode].pixelformat) - return -EINVAL; - - for (i = 0; i < gspca_dev->cam.mode_framerates[mode].nrates; i++) { - if (fival->index == i) { - fival->type = V4L2_FRMSIZE_TYPE_DISCRETE; - fival->discrete.numerator = 1; - fival->discrete.denominator = - gspca_dev->cam.mode_framerates[mode].rates[i]; - return 0; - } - } - - return -EINVAL; -} - -static void gspca_release(struct v4l2_device *v4l2_device) -{ - struct gspca_dev *gspca_dev = - container_of(v4l2_device, struct gspca_dev, v4l2_dev); - - v4l2_ctrl_handler_free(gspca_dev->vdev.ctrl_handler); - v4l2_device_unregister(&gspca_dev->v4l2_dev); - kfree(gspca_dev->usb_buf); - kfree(gspca_dev); -} - -static int dev_open(struct file *file) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - - PDEBUG(D_STREAM, "[%s] open", current->comm); - - /* protect the subdriver against rmmod */ - if (!try_module_get(gspca_dev->module)) - return -ENODEV; - -#ifdef GSPCA_DEBUG - /* activate the v4l2 debug */ - if (gspca_debug & D_V4L2) - gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL - | V4L2_DEBUG_IOCTL_ARG; - else - gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL - | V4L2_DEBUG_IOCTL_ARG); -#endif - return v4l2_fh_open(file); -} - -static int dev_close(struct file *file) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - - PDEBUG(D_STREAM, "[%s] close", current->comm); - - /* Needed for gspca_stream_off, always lock before queue_lock! */ - if (mutex_lock_interruptible(&gspca_dev->usb_lock)) - return -ERESTARTSYS; - - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) { - mutex_unlock(&gspca_dev->usb_lock); - return -ERESTARTSYS; - } - - /* if the file did the capture, free the streaming resources */ - if (gspca_dev->capt_file == file) { - if (gspca_dev->streaming) - gspca_stream_off(gspca_dev); - frame_free(gspca_dev); - } - module_put(gspca_dev->module); - mutex_unlock(&gspca_dev->queue_lock); - mutex_unlock(&gspca_dev->usb_lock); - - PDEBUG(D_STREAM, "close done"); - - return v4l2_fh_release(file); -} - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - - strlcpy((char *) cap->driver, gspca_dev->sd_desc->name, - sizeof cap->driver); - if (gspca_dev->dev->product != NULL) { - strlcpy((char *) cap->card, gspca_dev->dev->product, - sizeof cap->card); - } else { - snprintf((char *) cap->card, sizeof cap->card, - "USB Camera (%04x:%04x)", - le16_to_cpu(gspca_dev->dev->descriptor.idVendor), - le16_to_cpu(gspca_dev->dev->descriptor.idProduct)); - } - usb_make_path(gspca_dev->dev, (char *) cap->bus_info, - sizeof(cap->bus_info)); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE - | V4L2_CAP_STREAMING - | V4L2_CAP_READWRITE; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -static int get_ctrl(struct gspca_dev *gspca_dev, - int id) -{ - const struct ctrl *ctrls; - int i; - - for (i = 0, ctrls = gspca_dev->sd_desc->ctrls; - i < gspca_dev->sd_desc->nctrls; - i++, ctrls++) { - if (gspca_dev->ctrl_dis & (1 << i)) - continue; - if (id == ctrls->qctrl.id) - return i; - } - return -1; -} - -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *q_ctrl) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - const struct ctrl *ctrls; - struct gspca_ctrl *gspca_ctrl; - int i, idx; - u32 id; - - id = q_ctrl->id; - if (id & V4L2_CTRL_FLAG_NEXT_CTRL) { - id &= V4L2_CTRL_ID_MASK; - id++; - idx = -1; - for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { - if (gspca_dev->ctrl_dis & (1 << i)) - continue; - if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id) - continue; - if (idx >= 0 - && gspca_dev->sd_desc->ctrls[i].qctrl.id - > gspca_dev->sd_desc->ctrls[idx].qctrl.id) - continue; - idx = i; - } - } else { - idx = get_ctrl(gspca_dev, id); - } - if (idx < 0) - return -EINVAL; - ctrls = &gspca_dev->sd_desc->ctrls[idx]; - memcpy(q_ctrl, &ctrls->qctrl, sizeof *q_ctrl); - if (gspca_dev->cam.ctrls != NULL) { - gspca_ctrl = &gspca_dev->cam.ctrls[idx]; - q_ctrl->default_value = gspca_ctrl->def; - q_ctrl->minimum = gspca_ctrl->min; - q_ctrl->maximum = gspca_ctrl->max; - } - if (gspca_dev->ctrl_inac & (1 << idx)) - q_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - const struct ctrl *ctrls; - struct gspca_ctrl *gspca_ctrl; - int idx; - - idx = get_ctrl(gspca_dev, ctrl->id); - if (idx < 0) - return -EINVAL; - if (gspca_dev->ctrl_inac & (1 << idx)) - return -EINVAL; - ctrls = &gspca_dev->sd_desc->ctrls[idx]; - if (gspca_dev->cam.ctrls != NULL) { - gspca_ctrl = &gspca_dev->cam.ctrls[idx]; - if (ctrl->value < gspca_ctrl->min - || ctrl->value > gspca_ctrl->max) - return -ERANGE; - } else { - gspca_ctrl = NULL; - if (ctrl->value < ctrls->qctrl.minimum - || ctrl->value > ctrls->qctrl.maximum) - return -ERANGE; - } - PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value); - gspca_dev->usb_err = 0; - if (ctrls->set != NULL) - return ctrls->set(gspca_dev, ctrl->value); - if (gspca_ctrl != NULL) { - gspca_ctrl->val = ctrl->value; - if (ctrls->set_control != NULL - && gspca_dev->streaming) - ctrls->set_control(gspca_dev); - } - return gspca_dev->usb_err; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - const struct ctrl *ctrls; - int idx; - - idx = get_ctrl(gspca_dev, ctrl->id); - if (idx < 0) - return -EINVAL; - ctrls = &gspca_dev->sd_desc->ctrls[idx]; - - gspca_dev->usb_err = 0; - if (ctrls->get != NULL) - return ctrls->get(gspca_dev, &ctrl->value); - if (gspca_dev->cam.ctrls != NULL) - ctrl->value = gspca_dev->cam.ctrls[idx].val; - return 0; -} - -static int vidioc_querymenu(struct file *file, void *priv, - struct v4l2_querymenu *qmenu) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - - if (!gspca_dev->sd_desc->querymenu) - return -ENOTTY; - return gspca_dev->sd_desc->querymenu(gspca_dev, qmenu); -} - -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *input) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - - if (input->index != 0) - return -EINVAL; - input->type = V4L2_INPUT_TYPE_CAMERA; - input->status = gspca_dev->cam.input_flags; - strlcpy(input->name, gspca_dev->sd_desc->name, - sizeof input->name); - return 0; -} - -static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) -{ - *i = 0; - return 0; -} - -static int vidioc_s_input(struct file *file, void *priv, unsigned int i) -{ - if (i > 0) - return -EINVAL; - return (0); -} - -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - int i, ret = 0, streaming; - - i = rb->memory; /* (avoid compilation warning) */ - switch (i) { - case GSPCA_MEMORY_READ: /* (internal call) */ - case V4L2_MEMORY_MMAP: - case V4L2_MEMORY_USERPTR: - break; - default: - return -EINVAL; - } - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - - if (gspca_dev->memory != GSPCA_MEMORY_NO - && gspca_dev->memory != GSPCA_MEMORY_READ - && gspca_dev->memory != rb->memory) { - ret = -EBUSY; - goto out; - } - - /* only one file may do the capture */ - if (gspca_dev->capt_file != NULL - && gspca_dev->capt_file != file) { - ret = -EBUSY; - goto out; - } - - /* if allocated, the buffers must not be mapped */ - for (i = 0; i < gspca_dev->nframes; i++) { - if (gspca_dev->frame[i].vma_use_count) { - ret = -EBUSY; - goto out; - } - } - - /* stop streaming */ - streaming = gspca_dev->streaming; - if (streaming) { - gspca_stream_off(gspca_dev); - - /* Don't restart the stream when switching from read - * to mmap mode */ - if (gspca_dev->memory == GSPCA_MEMORY_READ) - streaming = 0; - } - - /* free the previous allocated buffers, if any */ - if (gspca_dev->nframes != 0) - frame_free(gspca_dev); - if (rb->count == 0) /* unrequest */ - goto out; - ret = frame_alloc(gspca_dev, file, rb->memory, rb->count); - if (ret == 0) { - rb->count = gspca_dev->nframes; - if (streaming) - ret = gspca_init_transfer(gspca_dev); - } -out: - mutex_unlock(&gspca_dev->queue_lock); - PDEBUG(D_STREAM, "reqbufs st:%d c:%d", ret, rb->count); - return ret; -} - -static int vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *v4l2_buf) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - struct gspca_frame *frame; - - if (v4l2_buf->index < 0 - || v4l2_buf->index >= gspca_dev->nframes) - return -EINVAL; - - frame = &gspca_dev->frame[v4l2_buf->index]; - memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf); - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type buf_type) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - int ret; - - if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - - /* check the capture file */ - if (gspca_dev->capt_file != file) { - ret = -EBUSY; - goto out; - } - - if (gspca_dev->nframes == 0 - || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) { - ret = -EINVAL; - goto out; - } - if (!gspca_dev->streaming) { - ret = gspca_init_transfer(gspca_dev); - if (ret < 0) - goto out; - } -#ifdef GSPCA_DEBUG - if (gspca_debug & D_STREAM) { - PDEBUG_MODE("stream on OK", - gspca_dev->pixfmt, - gspca_dev->width, - gspca_dev->height); - } -#endif - ret = 0; -out: - mutex_unlock(&gspca_dev->queue_lock); - return ret; -} - -static int vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type buf_type) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - int i, ret; - - if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - - if (!gspca_dev->streaming) { - ret = 0; - goto out; - } - - /* check the capture file */ - if (gspca_dev->capt_file != file) { - ret = -EBUSY; - goto out; - } - - /* stop streaming */ - gspca_stream_off(gspca_dev); - /* In case another thread is waiting in dqbuf */ - wake_up_interruptible(&gspca_dev->wq); - - /* empty the transfer queues */ - for (i = 0; i < gspca_dev->nframes; i++) - gspca_dev->frame[i].v4l2_buf.flags &= ~BUF_ALL_FLAGS; - atomic_set(&gspca_dev->fr_q, 0); - atomic_set(&gspca_dev->fr_i, 0); - gspca_dev->fr_o = 0; - ret = 0; -out: - mutex_unlock(&gspca_dev->queue_lock); - return ret; -} - -static int vidioc_g_jpegcomp(struct file *file, void *priv, - struct v4l2_jpegcompression *jpegcomp) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - - gspca_dev->usb_err = 0; - return gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp); -} - -static int vidioc_s_jpegcomp(struct file *file, void *priv, - struct v4l2_jpegcompression *jpegcomp) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - - gspca_dev->usb_err = 0; - return gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp); -} - -static int vidioc_g_parm(struct file *filp, void *priv, - struct v4l2_streamparm *parm) -{ - struct gspca_dev *gspca_dev = video_drvdata(filp); - - parm->parm.capture.readbuffers = gspca_dev->nbufread; - - if (gspca_dev->sd_desc->get_streamparm) { - gspca_dev->usb_err = 0; - gspca_dev->sd_desc->get_streamparm(gspca_dev, parm); - return gspca_dev->usb_err; - } - return 0; -} - -static int vidioc_s_parm(struct file *filp, void *priv, - struct v4l2_streamparm *parm) -{ - struct gspca_dev *gspca_dev = video_drvdata(filp); - int n; - - n = parm->parm.capture.readbuffers; - if (n == 0 || n >= GSPCA_MAX_FRAMES) - parm->parm.capture.readbuffers = gspca_dev->nbufread; - else - gspca_dev->nbufread = n; - - if (gspca_dev->sd_desc->set_streamparm) { - gspca_dev->usb_err = 0; - gspca_dev->sd_desc->set_streamparm(gspca_dev, parm); - return gspca_dev->usb_err; - } - - return 0; -} - -static int dev_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - struct gspca_frame *frame; - struct page *page; - unsigned long addr, start, size; - int i, ret; - - start = vma->vm_start; - size = vma->vm_end - vma->vm_start; - PDEBUG(D_STREAM, "mmap start:%08x size:%d", (int) start, (int) size); - - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - if (gspca_dev->capt_file != file) { - ret = -EINVAL; - goto out; - } - - frame = NULL; - for (i = 0; i < gspca_dev->nframes; ++i) { - if (gspca_dev->frame[i].v4l2_buf.memory != V4L2_MEMORY_MMAP) { - PDEBUG(D_STREAM, "mmap bad memory type"); - break; - } - if ((gspca_dev->frame[i].v4l2_buf.m.offset >> PAGE_SHIFT) - == vma->vm_pgoff) { - frame = &gspca_dev->frame[i]; - break; - } - } - if (frame == NULL) { - PDEBUG(D_STREAM, "mmap no frame buffer found"); - ret = -EINVAL; - goto out; - } - if (size != frame->v4l2_buf.length) { - PDEBUG(D_STREAM, "mmap bad size"); - ret = -EINVAL; - goto out; - } - - /* - * - VM_IO marks the area as being a mmaped region for I/O to a - * device. It also prevents the region from being core dumped. - */ - vma->vm_flags |= VM_IO; - - addr = (unsigned long) frame->data; - while (size > 0) { - page = vmalloc_to_page((void *) addr); - ret = vm_insert_page(vma, start, page); - if (ret < 0) - goto out; - start += PAGE_SIZE; - addr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - vma->vm_ops = &gspca_vm_ops; - vma->vm_private_data = frame; - gspca_vm_open(vma); - ret = 0; -out: - mutex_unlock(&gspca_dev->queue_lock); - return ret; -} - -static int frame_ready_nolock(struct gspca_dev *gspca_dev, struct file *file, - enum v4l2_memory memory) -{ - if (!gspca_dev->present) - return -ENODEV; - if (gspca_dev->capt_file != file || gspca_dev->memory != memory || - !gspca_dev->streaming) - return -EINVAL; - - /* check if a frame is ready */ - return gspca_dev->fr_o != atomic_read(&gspca_dev->fr_i); -} - -static int frame_ready(struct gspca_dev *gspca_dev, struct file *file, - enum v4l2_memory memory) -{ - int ret; - - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - ret = frame_ready_nolock(gspca_dev, file, memory); - mutex_unlock(&gspca_dev->queue_lock); - return ret; -} - -/* - * dequeue a video buffer - * - * If nonblock_ing is false, block until a buffer is available. - */ -static int vidioc_dqbuf(struct file *file, void *priv, - struct v4l2_buffer *v4l2_buf) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - struct gspca_frame *frame; - int i, j, ret; - - PDEBUG(D_FRAM, "dqbuf"); - - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - - for (;;) { - ret = frame_ready_nolock(gspca_dev, file, v4l2_buf->memory); - if (ret < 0) - goto out; - if (ret > 0) - break; - - mutex_unlock(&gspca_dev->queue_lock); - - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - - /* wait till a frame is ready */ - ret = wait_event_interruptible_timeout(gspca_dev->wq, - frame_ready(gspca_dev, file, v4l2_buf->memory), - msecs_to_jiffies(3000)); - if (ret < 0) - return ret; - if (ret == 0) - return -EIO; - - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - } - - i = gspca_dev->fr_o; - j = gspca_dev->fr_queue[i]; - frame = &gspca_dev->frame[j]; - - gspca_dev->fr_o = (i + 1) % GSPCA_MAX_FRAMES; - - frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; - memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf); - PDEBUG(D_FRAM, "dqbuf %d", j); - ret = 0; - - if (gspca_dev->memory == V4L2_MEMORY_USERPTR) { - if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr, - frame->data, - frame->v4l2_buf.bytesused)) { - PDEBUG(D_ERR|D_STREAM, - "dqbuf cp to user failed"); - ret = -EFAULT; - } - } -out: - mutex_unlock(&gspca_dev->queue_lock); - - if (ret == 0 && gspca_dev->sd_desc->dq_callback) { - mutex_lock(&gspca_dev->usb_lock); - gspca_dev->usb_err = 0; - if (gspca_dev->present) - gspca_dev->sd_desc->dq_callback(gspca_dev); - mutex_unlock(&gspca_dev->usb_lock); - } - - return ret; -} - -/* - * queue a video buffer - * - * Attempting to queue a buffer that has already been - * queued will return -EINVAL. - */ -static int vidioc_qbuf(struct file *file, void *priv, - struct v4l2_buffer *v4l2_buf) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - struct gspca_frame *frame; - int i, index, ret; - - PDEBUG(D_FRAM, "qbuf %d", v4l2_buf->index); - - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - - index = v4l2_buf->index; - if ((unsigned) index >= gspca_dev->nframes) { - PDEBUG(D_FRAM, - "qbuf idx %d >= %d", index, gspca_dev->nframes); - ret = -EINVAL; - goto out; - } - if (v4l2_buf->memory != gspca_dev->memory) { - PDEBUG(D_FRAM, "qbuf bad memory type"); - ret = -EINVAL; - goto out; - } - - frame = &gspca_dev->frame[index]; - if (frame->v4l2_buf.flags & BUF_ALL_FLAGS) { - PDEBUG(D_FRAM, "qbuf bad state"); - ret = -EINVAL; - goto out; - } - - frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED; - - if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) { - frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr; - frame->v4l2_buf.length = v4l2_buf->length; - } - - /* put the buffer in the 'queued' queue */ - i = atomic_read(&gspca_dev->fr_q); - gspca_dev->fr_queue[i] = index; - atomic_set(&gspca_dev->fr_q, (i + 1) % GSPCA_MAX_FRAMES); - - v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED; - v4l2_buf->flags &= ~V4L2_BUF_FLAG_DONE; - ret = 0; -out: - mutex_unlock(&gspca_dev->queue_lock); - return ret; -} - -/* - * allocate the resources for read() - */ -static int read_alloc(struct gspca_dev *gspca_dev, - struct file *file) -{ - struct v4l2_buffer v4l2_buf; - int i, ret; - - PDEBUG(D_STREAM, "read alloc"); - - if (mutex_lock_interruptible(&gspca_dev->usb_lock)) - return -ERESTARTSYS; - - if (gspca_dev->nframes == 0) { - struct v4l2_requestbuffers rb; - - memset(&rb, 0, sizeof rb); - rb.count = gspca_dev->nbufread; - rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - rb.memory = GSPCA_MEMORY_READ; - ret = vidioc_reqbufs(file, gspca_dev, &rb); - if (ret != 0) { - PDEBUG(D_STREAM, "read reqbuf err %d", ret); - goto out; - } - memset(&v4l2_buf, 0, sizeof v4l2_buf); - v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - v4l2_buf.memory = GSPCA_MEMORY_READ; - for (i = 0; i < gspca_dev->nbufread; i++) { - v4l2_buf.index = i; - ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf); - if (ret != 0) { - PDEBUG(D_STREAM, "read qbuf err: %d", ret); - goto out; - } - } - } - - /* start streaming */ - ret = vidioc_streamon(file, gspca_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE); - if (ret != 0) - PDEBUG(D_STREAM, "read streamon err %d", ret); -out: - mutex_unlock(&gspca_dev->usb_lock); - return ret; -} - -static unsigned int dev_poll(struct file *file, poll_table *wait) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - unsigned long req_events = poll_requested_events(wait); - int ret = 0; - - PDEBUG(D_FRAM, "poll"); - - if (req_events & POLLPRI) - ret |= v4l2_ctrl_poll(file, wait); - - if (req_events & (POLLIN | POLLRDNORM)) { - /* if reqbufs is not done, the user would use read() */ - if (gspca_dev->memory == GSPCA_MEMORY_NO) { - if (read_alloc(gspca_dev, file) != 0) { - ret |= POLLERR; - goto out; - } - } - - poll_wait(file, &gspca_dev->wq, wait); - - /* check if an image has been received */ - if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0) { - ret |= POLLERR; - goto out; - } - if (gspca_dev->fr_o != atomic_read(&gspca_dev->fr_i)) - ret |= POLLIN | POLLRDNORM; - mutex_unlock(&gspca_dev->queue_lock); - } - -out: - if (!gspca_dev->present) - ret |= POLLHUP; - - return ret; -} - -static ssize_t dev_read(struct file *file, char __user *data, - size_t count, loff_t *ppos) -{ - struct gspca_dev *gspca_dev = video_drvdata(file); - struct gspca_frame *frame; - struct v4l2_buffer v4l2_buf; - struct timeval timestamp; - int n, ret, ret2; - - PDEBUG(D_FRAM, "read (%zd)", count); - if (gspca_dev->memory == GSPCA_MEMORY_NO) { /* first time ? */ - ret = read_alloc(gspca_dev, file); - if (ret != 0) - return ret; - } - - /* get a frame */ - timestamp = ktime_to_timeval(ktime_get()); - timestamp.tv_sec--; - n = 2; - for (;;) { - memset(&v4l2_buf, 0, sizeof v4l2_buf); - v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - v4l2_buf.memory = GSPCA_MEMORY_READ; - ret = vidioc_dqbuf(file, gspca_dev, &v4l2_buf); - if (ret != 0) { - PDEBUG(D_STREAM, "read dqbuf err %d", ret); - return ret; - } - - /* if the process slept for more than 1 second, - * get a newer frame */ - frame = &gspca_dev->frame[v4l2_buf.index]; - if (--n < 0) - break; /* avoid infinite loop */ - if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec) - break; - ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf); - if (ret != 0) { - PDEBUG(D_STREAM, "read qbuf err %d", ret); - return ret; - } - } - - /* copy the frame */ - if (count > frame->v4l2_buf.bytesused) - count = frame->v4l2_buf.bytesused; - ret = copy_to_user(data, frame->data, count); - if (ret != 0) { - PDEBUG(D_ERR|D_STREAM, - "read cp to user lack %d / %zd", ret, count); - ret = -EFAULT; - goto out; - } - ret = count; -out: - /* in each case, requeue the buffer */ - ret2 = vidioc_qbuf(file, gspca_dev, &v4l2_buf); - if (ret2 != 0) - return ret2; - return ret; -} - -static struct v4l2_file_operations dev_fops = { - .owner = THIS_MODULE, - .open = dev_open, - .release = dev_close, - .read = dev_read, - .mmap = dev_mmap, - .unlocked_ioctl = video_ioctl2, - .poll = dev_poll, -}; - -static const struct v4l2_ioctl_ops dev_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_dqbuf = vidioc_dqbuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_streamon = vidioc_streamon, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_querymenu = vidioc_querymenu, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_g_jpegcomp = vidioc_g_jpegcomp, - .vidioc_s_jpegcomp = vidioc_s_jpegcomp, - .vidioc_g_parm = vidioc_g_parm, - .vidioc_s_parm = vidioc_s_parm, - .vidioc_enum_framesizes = vidioc_enum_framesizes, - .vidioc_enum_frameintervals = vidioc_enum_frameintervals, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, -#endif - .vidioc_g_chip_ident = vidioc_g_chip_ident, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -static const struct video_device gspca_template = { - .name = "gspca main driver", - .fops = &dev_fops, - .ioctl_ops = &dev_ioctl_ops, - .release = video_device_release_empty, /* We use v4l2_dev.release */ -}; - -/* initialize the controls */ -static void ctrls_init(struct gspca_dev *gspca_dev) -{ - struct gspca_ctrl *ctrl; - int i; - - for (i = 0, ctrl = gspca_dev->cam.ctrls; - i < gspca_dev->sd_desc->nctrls; - i++, ctrl++) { - ctrl->def = gspca_dev->sd_desc->ctrls[i].qctrl.default_value; - ctrl->val = ctrl->def; - ctrl->min = gspca_dev->sd_desc->ctrls[i].qctrl.minimum; - ctrl->max = gspca_dev->sd_desc->ctrls[i].qctrl.maximum; - } -} - -/* - * probe and create a new gspca device - * - * This function must be called by the sub-driver when it is - * called for probing a new device. - */ -int gspca_dev_probe2(struct usb_interface *intf, - const struct usb_device_id *id, - const struct sd_desc *sd_desc, - int dev_size, - struct module *module) -{ - struct gspca_dev *gspca_dev; - struct usb_device *dev = interface_to_usbdev(intf); - int ret; - - pr_info("%s-" GSPCA_VERSION " probing %04x:%04x\n", - sd_desc->name, id->idVendor, id->idProduct); - - /* create the device */ - if (dev_size < sizeof *gspca_dev) - dev_size = sizeof *gspca_dev; - gspca_dev = kzalloc(dev_size, GFP_KERNEL); - if (!gspca_dev) { - pr_err("couldn't kzalloc gspca struct\n"); - return -ENOMEM; - } - gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL); - if (!gspca_dev->usb_buf) { - pr_err("out of memory\n"); - ret = -ENOMEM; - goto out; - } - gspca_dev->dev = dev; - gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber; - - /* check if any audio device */ - if (dev->actconfig->desc.bNumInterfaces != 1) { - int i; - struct usb_interface *intf2; - - for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { - intf2 = dev->actconfig->interface[i]; - if (intf2 != NULL - && intf2->altsetting != NULL - && intf2->altsetting->desc.bInterfaceClass == - USB_CLASS_AUDIO) { - gspca_dev->audio = 1; - break; - } - } - } - - gspca_dev->v4l2_dev.release = gspca_release; - ret = v4l2_device_register(&intf->dev, &gspca_dev->v4l2_dev); - if (ret) - goto out; - gspca_dev->sd_desc = sd_desc; - gspca_dev->nbufread = 2; - gspca_dev->empty_packet = -1; /* don't check the empty packets */ - gspca_dev->vdev = gspca_template; - gspca_dev->vdev.v4l2_dev = &gspca_dev->v4l2_dev; - video_set_drvdata(&gspca_dev->vdev, gspca_dev); - set_bit(V4L2_FL_USE_FH_PRIO, &gspca_dev->vdev.flags); - gspca_dev->module = module; - gspca_dev->present = 1; - - mutex_init(&gspca_dev->usb_lock); - gspca_dev->vdev.lock = &gspca_dev->usb_lock; - mutex_init(&gspca_dev->queue_lock); - init_waitqueue_head(&gspca_dev->wq); - - /* configure the subdriver and initialize the USB device */ - ret = sd_desc->config(gspca_dev, id); - if (ret < 0) - goto out; - if (gspca_dev->cam.ctrls != NULL) - ctrls_init(gspca_dev); - ret = sd_desc->init(gspca_dev); - if (ret < 0) - goto out; - if (sd_desc->init_controls) - ret = sd_desc->init_controls(gspca_dev); - if (ret < 0) - goto out; - gspca_set_default_mode(gspca_dev); - - ret = gspca_input_connect(gspca_dev); - if (ret) - goto out; - - /* - * Don't take usb_lock for these ioctls. This improves latency if - * usb_lock is taken for a long time, e.g. when changing a control - * value, and a new frame is ready to be dequeued. - */ - v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_DQBUF); - v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_QBUF); - v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_QUERYBUF); - if (!gspca_dev->sd_desc->get_chip_ident) - v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_G_CHIP_IDENT); -#ifdef CONFIG_VIDEO_ADV_DEBUG - if (!gspca_dev->sd_desc->get_chip_ident || - !gspca_dev->sd_desc->get_register) - v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_G_REGISTER); - if (!gspca_dev->sd_desc->get_chip_ident || - !gspca_dev->sd_desc->set_register) - v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_S_REGISTER); -#endif - if (!gspca_dev->sd_desc->get_jcomp) - v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_G_JPEGCOMP); - if (!gspca_dev->sd_desc->set_jcomp) - v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_S_JPEGCOMP); - - /* init video stuff */ - ret = video_register_device(&gspca_dev->vdev, - VFL_TYPE_GRABBER, - -1); - if (ret < 0) { - pr_err("video_register_device err %d\n", ret); - goto out; - } - - usb_set_intfdata(intf, gspca_dev); - PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev)); - - gspca_input_create_urb(gspca_dev); - - return 0; -out: -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - if (gspca_dev->input_dev) - input_unregister_device(gspca_dev->input_dev); -#endif - v4l2_ctrl_handler_free(gspca_dev->vdev.ctrl_handler); - kfree(gspca_dev->usb_buf); - kfree(gspca_dev); - return ret; -} -EXPORT_SYMBOL(gspca_dev_probe2); - -/* same function as the previous one, but check the interface */ -int gspca_dev_probe(struct usb_interface *intf, - const struct usb_device_id *id, - const struct sd_desc *sd_desc, - int dev_size, - struct module *module) -{ - struct usb_device *dev = interface_to_usbdev(intf); - - /* we don't handle multi-config cameras */ - if (dev->descriptor.bNumConfigurations != 1) { - pr_err("%04x:%04x too many config\n", - id->idVendor, id->idProduct); - return -ENODEV; - } - - /* the USB video interface must be the first one */ - if (dev->actconfig->desc.bNumInterfaces != 1 - && intf->cur_altsetting->desc.bInterfaceNumber != 0) - return -ENODEV; - - return gspca_dev_probe2(intf, id, sd_desc, dev_size, module); -} -EXPORT_SYMBOL(gspca_dev_probe); - -/* - * USB disconnection - * - * This function must be called by the sub-driver - * when the device disconnects, after the specific resources are freed. - */ -void gspca_disconnect(struct usb_interface *intf) -{ - struct gspca_dev *gspca_dev = usb_get_intfdata(intf); -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - struct input_dev *input_dev; -#endif - - PDEBUG(D_PROBE, "%s disconnect", - video_device_node_name(&gspca_dev->vdev)); - - mutex_lock(&gspca_dev->usb_lock); - - usb_set_intfdata(intf, NULL); - gspca_dev->dev = NULL; - gspca_dev->present = 0; - destroy_urbs(gspca_dev); - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - gspca_input_destroy_urb(gspca_dev); - input_dev = gspca_dev->input_dev; - if (input_dev) { - gspca_dev->input_dev = NULL; - input_unregister_device(input_dev); - } -#endif - /* Free subdriver's streaming resources / stop sd workqueue(s) */ - if (gspca_dev->sd_desc->stop0 && gspca_dev->streaming) - gspca_dev->sd_desc->stop0(gspca_dev); - gspca_dev->streaming = 0; - wake_up_interruptible(&gspca_dev->wq); - - v4l2_device_disconnect(&gspca_dev->v4l2_dev); - video_unregister_device(&gspca_dev->vdev); - - mutex_unlock(&gspca_dev->usb_lock); - - /* (this will call gspca_release() immediately or on last close) */ - v4l2_device_put(&gspca_dev->v4l2_dev); -} -EXPORT_SYMBOL(gspca_disconnect); - -#ifdef CONFIG_PM -int gspca_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct gspca_dev *gspca_dev = usb_get_intfdata(intf); - - if (!gspca_dev->streaming) - return 0; - mutex_lock(&gspca_dev->usb_lock); - gspca_dev->frozen = 1; /* avoid urb error messages */ - gspca_dev->usb_err = 0; - if (gspca_dev->sd_desc->stopN) - gspca_dev->sd_desc->stopN(gspca_dev); - destroy_urbs(gspca_dev); - gspca_input_destroy_urb(gspca_dev); - gspca_set_alt0(gspca_dev); - if (gspca_dev->sd_desc->stop0) - gspca_dev->sd_desc->stop0(gspca_dev); - mutex_unlock(&gspca_dev->usb_lock); - return 0; -} -EXPORT_SYMBOL(gspca_suspend); - -int gspca_resume(struct usb_interface *intf) -{ - struct gspca_dev *gspca_dev = usb_get_intfdata(intf); - int streaming, ret = 0; - - mutex_lock(&gspca_dev->usb_lock); - gspca_dev->frozen = 0; - gspca_dev->usb_err = 0; - gspca_dev->sd_desc->init(gspca_dev); - gspca_input_create_urb(gspca_dev); - /* - * Most subdrivers send all ctrl values on sd_start and thus - * only write to the device registers on s_ctrl when streaming -> - * Clear streaming to avoid setting all ctrls twice. - */ - streaming = gspca_dev->streaming; - gspca_dev->streaming = 0; - if (streaming) - ret = gspca_init_transfer(gspca_dev); - mutex_unlock(&gspca_dev->usb_lock); - return ret; -} -EXPORT_SYMBOL(gspca_resume); -#endif - -/* -- module insert / remove -- */ -static int __init gspca_init(void) -{ - pr_info("v" GSPCA_VERSION " registered\n"); - return 0; -} -static void __exit gspca_exit(void) -{ -} - -module_init(gspca_init); -module_exit(gspca_exit); - -#ifdef GSPCA_DEBUG -module_param_named(debug, gspca_debug, int, 0644); -MODULE_PARM_DESC(debug, - "Debug (bit) 0x01:error 0x02:probe 0x04:config" - " 0x08:stream 0x10:frame 0x20:packet" - " 0x0100: v4l2"); -#endif diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h deleted file mode 100644 index dc688c7f5e48..000000000000 --- a/drivers/media/video/gspca/gspca.h +++ /dev/null @@ -1,259 +0,0 @@ -#ifndef GSPCAV2_H -#define GSPCAV2_H - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/usb.h> -#include <linux/videodev2.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-device.h> -#include <linux/mutex.h> - -/* compilation option */ -/*#define GSPCA_DEBUG 1*/ - -#ifdef GSPCA_DEBUG -/* GSPCA our debug messages */ -extern int gspca_debug; -#define PDEBUG(level, fmt, ...) \ -do { \ - if (gspca_debug & (level)) \ - pr_info(fmt, ##__VA_ARGS__); \ -} while (0) - -#define D_ERR 0x01 -#define D_PROBE 0x02 -#define D_CONF 0x04 -#define D_STREAM 0x08 -#define D_FRAM 0x10 -#define D_PACK 0x20 -#define D_USBI 0x00 -#define D_USBO 0x00 -#define D_V4L2 0x0100 -#else -#define PDEBUG(level, fmt, ...) -#endif - -#define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */ -/* image transfers */ -#define MAX_NURBS 4 /* max number of URBs */ - - -/* used to list framerates supported by a camera mode (resolution) */ -struct framerates { - const u8 *rates; - int nrates; -}; - -/* control definition */ -struct gspca_ctrl { - s16 val; /* current value */ - s16 def; /* default value */ - s16 min, max; /* minimum and maximum values */ -}; - -/* device information - set at probe time */ -struct cam { - const struct v4l2_pix_format *cam_mode; /* size nmodes */ - const struct framerates *mode_framerates; /* must have size nmodes, - * just like cam_mode */ - struct gspca_ctrl *ctrls; /* control table - size nctrls */ - /* may be NULL */ - u32 bulk_size; /* buffer size when image transfer by bulk */ - u32 input_flags; /* value for ENUM_INPUT status flags */ - u8 nmodes; /* size of cam_mode */ - u8 no_urb_create; /* don't create transfer URBs */ - u8 bulk_nurbs; /* number of URBs in bulk mode - * - cannot be > MAX_NURBS - * - when 0 and bulk_size != 0 means - * 1 URB and submit done by subdriver */ - u8 bulk; /* image transfer by 0:isoc / 1:bulk */ - u8 npkt; /* number of packets in an ISOC message - * 0 is the default value: 32 packets */ - u8 needs_full_bandwidth;/* Set this flag to notify the bandwidth calc. - * code that the cam fills all image buffers to - * the max, even when using compression. */ -}; - -struct gspca_dev; -struct gspca_frame; - -/* subdriver operations */ -typedef int (*cam_op) (struct gspca_dev *); -typedef void (*cam_v_op) (struct gspca_dev *); -typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *); -typedef int (*cam_jpg_op) (struct gspca_dev *, - struct v4l2_jpegcompression *); -typedef int (*cam_reg_op) (struct gspca_dev *, - struct v4l2_dbg_register *); -typedef int (*cam_ident_op) (struct gspca_dev *, - struct v4l2_dbg_chip_ident *); -typedef void (*cam_streamparm_op) (struct gspca_dev *, - struct v4l2_streamparm *); -typedef int (*cam_qmnu_op) (struct gspca_dev *, - struct v4l2_querymenu *); -typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev, - u8 *data, - int len); -typedef int (*cam_int_pkt_op) (struct gspca_dev *gspca_dev, - u8 *data, - int len); - -struct ctrl { - struct v4l2_queryctrl qctrl; - int (*set)(struct gspca_dev *, __s32); - int (*get)(struct gspca_dev *, __s32 *); - cam_v_op set_control; -}; - -/* subdriver description */ -struct sd_desc { -/* information */ - const char *name; /* sub-driver name */ -/* controls */ - const struct ctrl *ctrls; /* static control definition */ - int nctrls; -/* mandatory operations */ - cam_cf_op config; /* called on probe */ - cam_op init; /* called on probe and resume */ - cam_op init_controls; /* called on probe */ - cam_op start; /* called on stream on after URBs creation */ - cam_pkt_op pkt_scan; -/* optional operations */ - cam_op isoc_init; /* called on stream on before getting the EP */ - cam_op isoc_nego; /* called when URB submit failed with NOSPC */ - cam_v_op stopN; /* called on stream off - main alt */ - cam_v_op stop0; /* called on stream off & disconnect - alt 0 */ - cam_v_op dq_callback; /* called when a frame has been dequeued */ - cam_jpg_op get_jcomp; - cam_jpg_op set_jcomp; - cam_qmnu_op querymenu; - cam_streamparm_op get_streamparm; - cam_streamparm_op set_streamparm; -#ifdef CONFIG_VIDEO_ADV_DEBUG - cam_reg_op set_register; - cam_reg_op get_register; -#endif - cam_ident_op get_chip_ident; -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - cam_int_pkt_op int_pkt_scan; - /* other_input makes the gspca core create gspca_dev->input even when - int_pkt_scan is NULL, for cams with non interrupt driven buttons */ - u8 other_input; -#endif -}; - -/* packet types when moving from iso buf to frame buf */ -enum gspca_packet_type { - DISCARD_PACKET, - FIRST_PACKET, - INTER_PACKET, - LAST_PACKET -}; - -struct gspca_frame { - __u8 *data; /* frame buffer */ - int vma_use_count; - struct v4l2_buffer v4l2_buf; -}; - -struct gspca_dev { - struct video_device vdev; /* !! must be the first item */ - struct module *module; /* subdriver handling the device */ - struct v4l2_device v4l2_dev; - struct usb_device *dev; - struct file *capt_file; /* file doing video capture */ - /* protected by queue_lock */ -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - struct input_dev *input_dev; - char phys[64]; /* physical device path */ -#endif - - struct cam cam; /* device information */ - const struct sd_desc *sd_desc; /* subdriver description */ - unsigned ctrl_dis; /* disabled controls (bit map) */ - unsigned ctrl_inac; /* inactive controls (bit map) */ - struct v4l2_ctrl_handler ctrl_handler; - - /* autogain and exposure or gain control cluster, these are global as - the autogain/exposure functions in autogain_functions.c use them */ - struct { - struct v4l2_ctrl *autogain; - struct v4l2_ctrl *exposure; - struct v4l2_ctrl *gain; - int exp_too_low_cnt, exp_too_high_cnt; - }; - -#define USB_BUF_SZ 64 - __u8 *usb_buf; /* buffer for USB exchanges */ - struct urb *urb[MAX_NURBS]; -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - struct urb *int_urb; -#endif - - __u8 *frbuf; /* buffer for nframes */ - struct gspca_frame frame[GSPCA_MAX_FRAMES]; - u8 *image; /* image beeing filled */ - __u32 frsz; /* frame size */ - u32 image_len; /* current length of image */ - atomic_t fr_q; /* next frame to queue */ - atomic_t fr_i; /* frame being filled */ - signed char fr_queue[GSPCA_MAX_FRAMES]; /* frame queue */ - char nframes; /* number of frames */ - u8 fr_o; /* next frame to dequeue */ - __u8 last_packet_type; - __s8 empty_packet; /* if (-1) don't check empty packets */ - __u8 streaming; /* protected by both mutexes (*) */ - - __u8 curr_mode; /* current camera mode */ - __u32 pixfmt; /* current mode parameters */ - __u16 width; - __u16 height; - __u32 sequence; /* frame sequence number */ - - wait_queue_head_t wq; /* wait queue */ - struct mutex usb_lock; /* usb exchange protection */ - struct mutex queue_lock; /* ISOC queue protection */ - int usb_err; /* USB error - protected by usb_lock */ - u16 pkt_size; /* ISOC packet size */ -#ifdef CONFIG_PM - char frozen; /* suspend - resume */ -#endif - char present; /* device connected */ - char nbufread; /* number of buffers for read() */ - char memory; /* memory type (V4L2_MEMORY_xxx) */ - __u8 iface; /* USB interface number */ - __u8 alt; /* USB alternate setting */ - u8 audio; /* presence of audio device */ - - /* (*) These variables are proteced by both usb_lock and queue_lock, - that is any code setting them is holding *both*, which means that - any code getting them needs to hold at least one of them */ -}; - -int gspca_dev_probe(struct usb_interface *intf, - const struct usb_device_id *id, - const struct sd_desc *sd_desc, - int dev_size, - struct module *module); -int gspca_dev_probe2(struct usb_interface *intf, - const struct usb_device_id *id, - const struct sd_desc *sd_desc, - int dev_size, - struct module *module); -void gspca_disconnect(struct usb_interface *intf); -void gspca_frame_add(struct gspca_dev *gspca_dev, - enum gspca_packet_type packet_type, - const u8 *data, - int len); -#ifdef CONFIG_PM -int gspca_suspend(struct usb_interface *intf, pm_message_t message); -int gspca_resume(struct usb_interface *intf); -#endif -int gspca_expo_autogain(struct gspca_dev *gspca_dev, int avg_lum, - int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee); -int gspca_coarse_grained_expo_autogain(struct gspca_dev *gspca_dev, - int avg_lum, int desired_avg_lum, int deadzone); - -#endif /* GSPCAV2_H */ diff --git a/drivers/media/video/gspca/jeilinj.c b/drivers/media/video/gspca/jeilinj.c deleted file mode 100644 index 26b99310d628..000000000000 --- a/drivers/media/video/gspca/jeilinj.c +++ /dev/null @@ -1,548 +0,0 @@ -/* - * Jeilinj subdriver - * - * Supports some Jeilin dual-mode cameras which use bulk transport and - * download raw JPEG data. - * - * Copyright (C) 2009 Theodore Kilgore - * - * Sportscam DV15 support and control settings are - * Copyright (C) 2011 Patrice Chotard - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "jeilinj" - -#include <linux/slab.h> -#include "gspca.h" -#include "jpeg.h" - -MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>"); -MODULE_DESCRIPTION("GSPCA/JEILINJ USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* Default timeouts, in ms */ -#define JEILINJ_CMD_TIMEOUT 500 -#define JEILINJ_CMD_DELAY 160 -#define JEILINJ_DATA_TIMEOUT 1000 - -/* Maximum transfer size to use. */ -#define JEILINJ_MAX_TRANSFER 0x200 -#define FRAME_HEADER_LEN 0x10 -#define FRAME_START 0xFFFFFFFF - -enum { - SAKAR_57379, - SPORTSCAM_DV15, -}; - -#define CAMQUALITY_MIN 0 /* highest cam quality */ -#define CAMQUALITY_MAX 97 /* lowest cam quality */ - -/* Structure to hold all of our device specific stuff */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - int blocks_left; - const struct v4l2_pix_format *cap_mode; - struct v4l2_ctrl *freq; - struct v4l2_ctrl *jpegqual; - /* Driver stuff */ - u8 type; - u8 quality; /* image quality */ -#define QUALITY_MIN 35 -#define QUALITY_MAX 85 -#define QUALITY_DEF 85 - u8 jpeg_hdr[JPEG_HDR_SZ]; -}; - -struct jlj_command { - unsigned char instruction[2]; - unsigned char ack_wanted; - unsigned char delay; -}; - -/* AFAICT these cameras will only do 320x240. */ -static struct v4l2_pix_format jlj_mode[] = { - { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, - { 640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0} -}; - -/* - * cam uses endpoint 0x03 to send commands, 0x84 for read commands, - * and 0x82 for bulk transfer. - */ - -/* All commands are two bytes only */ -static void jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command) -{ - int retval; - - if (gspca_dev->usb_err < 0) - return; - memcpy(gspca_dev->usb_buf, command, 2); - retval = usb_bulk_msg(gspca_dev->dev, - usb_sndbulkpipe(gspca_dev->dev, 3), - gspca_dev->usb_buf, 2, NULL, 500); - if (retval < 0) { - pr_err("command write [%02x] error %d\n", - gspca_dev->usb_buf[0], retval); - gspca_dev->usb_err = retval; - } -} - -/* Responses are one byte only */ -static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char response) -{ - int retval; - - if (gspca_dev->usb_err < 0) - return; - retval = usb_bulk_msg(gspca_dev->dev, - usb_rcvbulkpipe(gspca_dev->dev, 0x84), - gspca_dev->usb_buf, 1, NULL, 500); - response = gspca_dev->usb_buf[0]; - if (retval < 0) { - pr_err("read command [%02x] error %d\n", - gspca_dev->usb_buf[0], retval); - gspca_dev->usb_err = retval; - } -} - -static void setfreq(struct gspca_dev *gspca_dev, s32 val) -{ - u8 freq_commands[][2] = { - {0x71, 0x80}, - {0x70, 0x07} - }; - - freq_commands[0][1] |= val >> 1; - - jlj_write2(gspca_dev, freq_commands[0]); - jlj_write2(gspca_dev, freq_commands[1]); -} - -static void setcamquality(struct gspca_dev *gspca_dev, s32 val) -{ - u8 quality_commands[][2] = { - {0x71, 0x1E}, - {0x70, 0x06} - }; - u8 camquality; - - /* adapt camera quality from jpeg quality */ - camquality = ((QUALITY_MAX - val) * CAMQUALITY_MAX) - / (QUALITY_MAX - QUALITY_MIN); - quality_commands[0][1] += camquality; - - jlj_write2(gspca_dev, quality_commands[0]); - jlj_write2(gspca_dev, quality_commands[1]); -} - -static void setautogain(struct gspca_dev *gspca_dev, s32 val) -{ - u8 autogain_commands[][2] = { - {0x94, 0x02}, - {0xcf, 0x00} - }; - - autogain_commands[1][1] = val << 4; - - jlj_write2(gspca_dev, autogain_commands[0]); - jlj_write2(gspca_dev, autogain_commands[1]); -} - -static void setred(struct gspca_dev *gspca_dev, s32 val) -{ - u8 setred_commands[][2] = { - {0x94, 0x02}, - {0xe6, 0x00} - }; - - setred_commands[1][1] = val; - - jlj_write2(gspca_dev, setred_commands[0]); - jlj_write2(gspca_dev, setred_commands[1]); -} - -static void setgreen(struct gspca_dev *gspca_dev, s32 val) -{ - u8 setgreen_commands[][2] = { - {0x94, 0x02}, - {0xe7, 0x00} - }; - - setgreen_commands[1][1] = val; - - jlj_write2(gspca_dev, setgreen_commands[0]); - jlj_write2(gspca_dev, setgreen_commands[1]); -} - -static void setblue(struct gspca_dev *gspca_dev, s32 val) -{ - u8 setblue_commands[][2] = { - {0x94, 0x02}, - {0xe9, 0x00} - }; - - setblue_commands[1][1] = val; - - jlj_write2(gspca_dev, setblue_commands[0]); - jlj_write2(gspca_dev, setblue_commands[1]); -} - -static int jlj_start(struct gspca_dev *gspca_dev) -{ - int i; - int start_commands_size; - u8 response = 0xff; - struct sd *sd = (struct sd *) gspca_dev; - struct jlj_command start_commands[] = { - {{0x71, 0x81}, 0, 0}, - {{0x70, 0x05}, 0, JEILINJ_CMD_DELAY}, - {{0x95, 0x70}, 1, 0}, - {{0x71, 0x81 - gspca_dev->curr_mode}, 0, 0}, - {{0x70, 0x04}, 0, JEILINJ_CMD_DELAY}, - {{0x95, 0x70}, 1, 0}, - {{0x71, 0x00}, 0, 0}, /* start streaming ??*/ - {{0x70, 0x08}, 0, JEILINJ_CMD_DELAY}, - {{0x95, 0x70}, 1, 0}, -#define SPORTSCAM_DV15_CMD_SIZE 9 - {{0x94, 0x02}, 0, 0}, - {{0xde, 0x24}, 0, 0}, - {{0x94, 0x02}, 0, 0}, - {{0xdd, 0xf0}, 0, 0}, - {{0x94, 0x02}, 0, 0}, - {{0xe3, 0x2c}, 0, 0}, - {{0x94, 0x02}, 0, 0}, - {{0xe4, 0x00}, 0, 0}, - {{0x94, 0x02}, 0, 0}, - {{0xe5, 0x00}, 0, 0}, - {{0x94, 0x02}, 0, 0}, - {{0xe6, 0x2c}, 0, 0}, - {{0x94, 0x03}, 0, 0}, - {{0xaa, 0x00}, 0, 0} - }; - - sd->blocks_left = 0; - /* Under Windows, USB spy shows that only the 9 first start - * commands are used for SPORTSCAM_DV15 webcam - */ - if (sd->type == SPORTSCAM_DV15) - start_commands_size = SPORTSCAM_DV15_CMD_SIZE; - else - start_commands_size = ARRAY_SIZE(start_commands); - - for (i = 0; i < start_commands_size; i++) { - jlj_write2(gspca_dev, start_commands[i].instruction); - if (start_commands[i].delay) - msleep(start_commands[i].delay); - if (start_commands[i].ack_wanted) - jlj_read1(gspca_dev, response); - } - setcamquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual)); - msleep(2); - setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq)); - if (gspca_dev->usb_err < 0) - PDEBUG(D_ERR, "Start streaming command failed"); - return gspca_dev->usb_err; -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - int packet_type; - u32 header_marker; - - PDEBUG(D_STREAM, "Got %d bytes out of %d for Block 0", - len, JEILINJ_MAX_TRANSFER); - if (len != JEILINJ_MAX_TRANSFER) { - PDEBUG(D_PACK, "bad length"); - goto discard; - } - /* check if it's start of frame */ - header_marker = ((u32 *)data)[0]; - if (header_marker == FRAME_START) { - sd->blocks_left = data[0x0a] - 1; - PDEBUG(D_STREAM, "blocks_left = 0x%x", sd->blocks_left); - /* Start a new frame, and add the JPEG header, first thing */ - gspca_frame_add(gspca_dev, FIRST_PACKET, - sd->jpeg_hdr, JPEG_HDR_SZ); - /* Toss line 0 of data block 0, keep the rest. */ - gspca_frame_add(gspca_dev, INTER_PACKET, - data + FRAME_HEADER_LEN, - JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN); - } else if (sd->blocks_left > 0) { - PDEBUG(D_STREAM, "%d blocks remaining for frame", - sd->blocks_left); - sd->blocks_left -= 1; - if (sd->blocks_left == 0) - packet_type = LAST_PACKET; - else - packet_type = INTER_PACKET; - gspca_frame_add(gspca_dev, packet_type, - data, JEILINJ_MAX_TRANSFER); - } else - goto discard; - return; -discard: - /* Discard data until a new frame starts. */ - gspca_dev->last_packet_type = DISCARD_PACKET; -} - -/* This function is called at probe time just before sd_init */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct cam *cam = &gspca_dev->cam; - struct sd *dev = (struct sd *) gspca_dev; - - dev->type = id->driver_info; - dev->quality = QUALITY_DEF; - - cam->cam_mode = jlj_mode; - cam->nmodes = ARRAY_SIZE(jlj_mode); - cam->bulk = 1; - cam->bulk_nurbs = 1; - cam->bulk_size = JEILINJ_MAX_TRANSFER; - return 0; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - int i; - u8 *buf; - static u8 stop_commands[][2] = { - {0x71, 0x00}, - {0x70, 0x09}, - {0x71, 0x80}, - {0x70, 0x05} - }; - - for (;;) { - /* get the image remaining blocks */ - usb_bulk_msg(gspca_dev->dev, - gspca_dev->urb[0]->pipe, - gspca_dev->urb[0]->transfer_buffer, - JEILINJ_MAX_TRANSFER, NULL, - JEILINJ_DATA_TIMEOUT); - - /* search for 0xff 0xd9 (EOF for JPEG) */ - i = 0; - buf = gspca_dev->urb[0]->transfer_buffer; - while ((i < (JEILINJ_MAX_TRANSFER - 1)) && - ((buf[i] != 0xff) || (buf[i+1] != 0xd9))) - i++; - - if (i != (JEILINJ_MAX_TRANSFER - 1)) - /* last remaining block found */ - break; - } - - for (i = 0; i < ARRAY_SIZE(stop_commands); i++) - jlj_write2(gspca_dev, stop_commands[i]); -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - return gspca_dev->usb_err; -} - -/* Set up for getting frames. */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *dev = (struct sd *) gspca_dev; - - /* create the JPEG header */ - jpeg_define(dev->jpeg_hdr, gspca_dev->height, gspca_dev->width, - 0x21); /* JPEG 422 */ - jpeg_set_qual(dev->jpeg_hdr, dev->quality); - PDEBUG(D_STREAM, "Start streaming at %dx%d", - gspca_dev->height, gspca_dev->width); - jlj_start(gspca_dev); - return gspca_dev->usb_err; -} - -/* Table of supported USB devices */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x0979, 0x0280), .driver_info = SAKAR_57379}, - {USB_DEVICE(0x0979, 0x0270), .driver_info = SPORTSCAM_DV15}, - {} -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_POWER_LINE_FREQUENCY: - setfreq(gspca_dev, ctrl->val); - break; - case V4L2_CID_RED_BALANCE: - setred(gspca_dev, ctrl->val); - break; - case V4L2_CID_GAIN: - setgreen(gspca_dev, ctrl->val); - break; - case V4L2_CID_BLUE_BALANCE: - setblue(gspca_dev, ctrl->val); - break; - case V4L2_CID_AUTOGAIN: - setautogain(gspca_dev, ctrl->val); - break; - case V4L2_CID_JPEG_COMPRESSION_QUALITY: - jpeg_set_qual(sd->jpeg_hdr, ctrl->val); - setcamquality(gspca_dev, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - static const struct v4l2_ctrl_config custom_autogain = { - .ops = &sd_ctrl_ops, - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Automatic Gain (and Exposure)", - .max = 3, - .step = 1, - .def = 0, - }; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 6); - sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, - V4L2_CID_POWER_LINE_FREQUENCY, - V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1, - V4L2_CID_POWER_LINE_FREQUENCY_60HZ); - v4l2_ctrl_new_custom(hdl, &custom_autogain, NULL); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_RED_BALANCE, 0, 3, 1, 2); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 3, 1, 2); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BLUE_BALANCE, 0, 3, 1, 2); - sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_JPEG_COMPRESSION_QUALITY, - QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -static int sd_set_jcomp(struct gspca_dev *gspca_dev, - struct v4l2_jpegcompression *jcomp) -{ - struct sd *sd = (struct sd *) gspca_dev; - - v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality); - return 0; -} - -static int sd_get_jcomp(struct gspca_dev *gspca_dev, - struct v4l2_jpegcompression *jcomp) -{ - struct sd *sd = (struct sd *) gspca_dev; - - memset(jcomp, 0, sizeof *jcomp); - jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual); - jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT - | V4L2_JPEG_MARKER_DQT; - return 0; -} - - -/* sub-driver description */ -static const struct sd_desc sd_desc_sakar_57379 = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, -}; - -/* sub-driver description */ -static const struct sd_desc sd_desc_sportscam_dv15 = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, - .get_jcomp = sd_get_jcomp, - .set_jcomp = sd_set_jcomp, -}; - -static const struct sd_desc *sd_desc[2] = { - &sd_desc_sakar_57379, - &sd_desc_sportscam_dv15 -}; - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, - sd_desc[id->driver_info], - sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/jl2005bcd.c b/drivers/media/video/gspca/jl2005bcd.c deleted file mode 100644 index cf9d9fca5b84..000000000000 --- a/drivers/media/video/gspca/jl2005bcd.c +++ /dev/null @@ -1,557 +0,0 @@ -/* - * Jeilin JL2005B/C/D library - * - * Copyright (C) 2011 Theodore Kilgore <kilgota@auburn.edu> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define MODULE_NAME "jl2005bcd" - -#include <linux/workqueue.h> -#include <linux/slab.h> -#include "gspca.h" - - -MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>"); -MODULE_DESCRIPTION("JL2005B/C/D USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* Default timeouts, in ms */ -#define JL2005C_CMD_TIMEOUT 500 -#define JL2005C_DATA_TIMEOUT 1000 - -/* Maximum transfer size to use. */ -#define JL2005C_MAX_TRANSFER 0x200 -#define FRAME_HEADER_LEN 16 - - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - unsigned char firmware_id[6]; - const struct v4l2_pix_format *cap_mode; - /* Driver stuff */ - struct work_struct work_struct; - struct workqueue_struct *work_thread; - u8 frame_brightness; - int block_size; /* block size of camera */ - int vga; /* 1 if vga cam, 0 if cif cam */ -}; - - -/* Camera has two resolution settings. What they are depends on model. */ -static const struct v4l2_pix_format cif_mode[] = { - {176, 144, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, - {352, 288, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; - -static const struct v4l2_pix_format vga_mode[] = { - {320, 240, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, - {640, 480, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; - -/* - * cam uses endpoint 0x03 to send commands, 0x84 for read commands, - * and 0x82 for bulk data transfer. - */ - -/* All commands are two bytes only */ -static int jl2005c_write2(struct gspca_dev *gspca_dev, unsigned char *command) -{ - int retval; - - memcpy(gspca_dev->usb_buf, command, 2); - retval = usb_bulk_msg(gspca_dev->dev, - usb_sndbulkpipe(gspca_dev->dev, 3), - gspca_dev->usb_buf, 2, NULL, 500); - if (retval < 0) - pr_err("command write [%02x] error %d\n", - gspca_dev->usb_buf[0], retval); - return retval; -} - -/* Response to a command is one byte in usb_buf[0], only if requested. */ -static int jl2005c_read1(struct gspca_dev *gspca_dev) -{ - int retval; - - retval = usb_bulk_msg(gspca_dev->dev, - usb_rcvbulkpipe(gspca_dev->dev, 0x84), - gspca_dev->usb_buf, 1, NULL, 500); - if (retval < 0) - pr_err("read command [0x%02x] error %d\n", - gspca_dev->usb_buf[0], retval); - return retval; -} - -/* Response appears in gspca_dev->usb_buf[0] */ -static int jl2005c_read_reg(struct gspca_dev *gspca_dev, unsigned char reg) -{ - int retval; - - static u8 instruction[2] = {0x95, 0x00}; - /* put register to read in byte 1 */ - instruction[1] = reg; - /* Send the read request */ - retval = jl2005c_write2(gspca_dev, instruction); - if (retval < 0) - return retval; - retval = jl2005c_read1(gspca_dev); - - return retval; -} - -static int jl2005c_start_new_frame(struct gspca_dev *gspca_dev) -{ - int i; - int retval; - int frame_brightness = 0; - - static u8 instruction[2] = {0x7f, 0x01}; - - retval = jl2005c_write2(gspca_dev, instruction); - if (retval < 0) - return retval; - - i = 0; - while (i < 20 && !frame_brightness) { - /* If we tried 20 times, give up. */ - retval = jl2005c_read_reg(gspca_dev, 0x7e); - if (retval < 0) - return retval; - frame_brightness = gspca_dev->usb_buf[0]; - retval = jl2005c_read_reg(gspca_dev, 0x7d); - if (retval < 0) - return retval; - i++; - } - PDEBUG(D_FRAM, "frame_brightness is 0x%02x", gspca_dev->usb_buf[0]); - return retval; -} - -static int jl2005c_write_reg(struct gspca_dev *gspca_dev, unsigned char reg, - unsigned char value) -{ - int retval; - u8 instruction[2]; - - instruction[0] = reg; - instruction[1] = value; - - retval = jl2005c_write2(gspca_dev, instruction); - if (retval < 0) - return retval; - - return retval; -} - -static int jl2005c_get_firmware_id(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - int i = 0; - int retval = -1; - unsigned char regs_to_read[] = {0x57, 0x02, 0x03, 0x5d, 0x5e, 0x5f}; - - PDEBUG(D_PROBE, "Running jl2005c_get_firmware_id"); - /* Read the first ID byte once for warmup */ - retval = jl2005c_read_reg(gspca_dev, regs_to_read[0]); - PDEBUG(D_PROBE, "response is %02x", gspca_dev->usb_buf[0]); - if (retval < 0) - return retval; - /* Now actually get the ID string */ - for (i = 0; i < 6; i++) { - retval = jl2005c_read_reg(gspca_dev, regs_to_read[i]); - if (retval < 0) - return retval; - sd->firmware_id[i] = gspca_dev->usb_buf[0]; - } - PDEBUG(D_PROBE, "firmware ID is %02x%02x%02x%02x%02x%02x", - sd->firmware_id[0], - sd->firmware_id[1], - sd->firmware_id[2], - sd->firmware_id[3], - sd->firmware_id[4], - sd->firmware_id[5]); - return 0; -} - -static int jl2005c_stream_start_vga_lg - (struct gspca_dev *gspca_dev) -{ - int i; - int retval = -1; - static u8 instruction[][2] = { - {0x05, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x18}, - {0x02, 0x00}, - {0x01, 0x00}, - {0x04, 0x52}, - }; - - for (i = 0; i < ARRAY_SIZE(instruction); i++) { - msleep(60); - retval = jl2005c_write2(gspca_dev, instruction[i]); - if (retval < 0) - return retval; - } - msleep(60); - return retval; -} - -static int jl2005c_stream_start_vga_small(struct gspca_dev *gspca_dev) -{ - int i; - int retval = -1; - static u8 instruction[][2] = { - {0x06, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x1a}, - {0x02, 0x00}, - {0x01, 0x00}, - {0x04, 0x52}, - }; - - for (i = 0; i < ARRAY_SIZE(instruction); i++) { - msleep(60); - retval = jl2005c_write2(gspca_dev, instruction[i]); - if (retval < 0) - return retval; - } - msleep(60); - return retval; -} - -static int jl2005c_stream_start_cif_lg(struct gspca_dev *gspca_dev) -{ - int i; - int retval = -1; - static u8 instruction[][2] = { - {0x05, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x30}, - {0x02, 0x00}, - {0x01, 0x00}, - {0x04, 0x42}, - }; - - for (i = 0; i < ARRAY_SIZE(instruction); i++) { - msleep(60); - retval = jl2005c_write2(gspca_dev, instruction[i]); - if (retval < 0) - return retval; - } - msleep(60); - return retval; -} - -static int jl2005c_stream_start_cif_small(struct gspca_dev *gspca_dev) -{ - int i; - int retval = -1; - static u8 instruction[][2] = { - {0x06, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x32}, - {0x02, 0x00}, - {0x01, 0x00}, - {0x04, 0x42}, - }; - - for (i = 0; i < ARRAY_SIZE(instruction); i++) { - msleep(60); - retval = jl2005c_write2(gspca_dev, instruction[i]); - if (retval < 0) - return retval; - } - msleep(60); - return retval; -} - - -static int jl2005c_stop(struct gspca_dev *gspca_dev) -{ - int retval; - - retval = jl2005c_write_reg(gspca_dev, 0x07, 0x00); - return retval; -} - -/* This function is called as a workqueue function and runs whenever the camera - * is streaming data. Because it is a workqueue function it is allowed to sleep - * so we can use synchronous USB calls. To avoid possible collisions with other - * threads attempting to use the camera's USB interface the gspca usb_lock is - * used when performing the one USB control operation inside the workqueue, - * which tells the camera to close the stream. In practice the only thing - * which needs to be protected against is the usb_set_interface call that - * gspca makes during stream_off. Otherwise the camera doesn't provide any - * controls that the user could try to change. - */ -static void jl2005c_dostream(struct work_struct *work) -{ - struct sd *dev = container_of(work, struct sd, work_struct); - struct gspca_dev *gspca_dev = &dev->gspca_dev; - int bytes_left = 0; /* bytes remaining in current frame. */ - int data_len; /* size to use for the next read. */ - int header_read = 0; - unsigned char header_sig[2] = {0x4a, 0x4c}; - int act_len; - int packet_type; - int ret; - u8 *buffer; - - buffer = kmalloc(JL2005C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); - if (!buffer) { - pr_err("Couldn't allocate USB buffer\n"); - goto quit_stream; - } - - while (gspca_dev->dev && gspca_dev->streaming) { -#ifdef CONFIG_PM - if (gspca_dev->frozen) - break; -#endif - /* Check if this is a new frame. If so, start the frame first */ - if (!header_read) { - mutex_lock(&gspca_dev->usb_lock); - ret = jl2005c_start_new_frame(gspca_dev); - mutex_unlock(&gspca_dev->usb_lock); - if (ret < 0) - goto quit_stream; - ret = usb_bulk_msg(gspca_dev->dev, - usb_rcvbulkpipe(gspca_dev->dev, 0x82), - buffer, JL2005C_MAX_TRANSFER, &act_len, - JL2005C_DATA_TIMEOUT); - PDEBUG(D_PACK, - "Got %d bytes out of %d for header", - act_len, JL2005C_MAX_TRANSFER); - if (ret < 0 || act_len < JL2005C_MAX_TRANSFER) - goto quit_stream; - /* Check whether we actually got the first blodk */ - if (memcmp(header_sig, buffer, 2) != 0) { - pr_err("First block is not the first block\n"); - goto quit_stream; - } - /* total size to fetch is byte 7, times blocksize - * of which we already got act_len */ - bytes_left = buffer[0x07] * dev->block_size - act_len; - PDEBUG(D_PACK, "bytes_left = 0x%x", bytes_left); - /* We keep the header. It has other information, too.*/ - packet_type = FIRST_PACKET; - gspca_frame_add(gspca_dev, packet_type, - buffer, act_len); - header_read = 1; - } - while (bytes_left > 0 && gspca_dev->dev) { - data_len = bytes_left > JL2005C_MAX_TRANSFER ? - JL2005C_MAX_TRANSFER : bytes_left; - ret = usb_bulk_msg(gspca_dev->dev, - usb_rcvbulkpipe(gspca_dev->dev, 0x82), - buffer, data_len, &act_len, - JL2005C_DATA_TIMEOUT); - if (ret < 0 || act_len < data_len) - goto quit_stream; - PDEBUG(D_PACK, - "Got %d bytes out of %d for frame", - data_len, bytes_left); - bytes_left -= data_len; - if (bytes_left == 0) { - packet_type = LAST_PACKET; - header_read = 0; - } else - packet_type = INTER_PACKET; - gspca_frame_add(gspca_dev, packet_type, - buffer, data_len); - } - } -quit_stream: - if (gspca_dev->dev) { - mutex_lock(&gspca_dev->usb_lock); - jl2005c_stop(gspca_dev); - mutex_unlock(&gspca_dev->usb_lock); - } - kfree(buffer); -} - - - - -/* This function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct cam *cam; - struct sd *sd = (struct sd *) gspca_dev; - - cam = &gspca_dev->cam; - /* We don't use the buffer gspca allocates so make it small. */ - cam->bulk_size = 64; - cam->bulk = 1; - /* For the rest, the camera needs to be detected */ - jl2005c_get_firmware_id(gspca_dev); - /* Here are some known firmware IDs - * First some JL2005B cameras - * {0x41, 0x07, 0x04, 0x2c, 0xe8, 0xf2} Sakar KidzCam - * {0x45, 0x02, 0x08, 0xb9, 0x00, 0xd2} No-name JL2005B - * JL2005C cameras - * {0x01, 0x0c, 0x16, 0x10, 0xf8, 0xc8} Argus DC-1512 - * {0x12, 0x04, 0x03, 0xc0, 0x00, 0xd8} ICarly - * {0x86, 0x08, 0x05, 0x02, 0x00, 0xd4} Jazz - * - * Based upon this scanty evidence, we can detect a CIF camera by - * testing byte 0 for 0x4x. - */ - if ((sd->firmware_id[0] & 0xf0) == 0x40) { - cam->cam_mode = cif_mode; - cam->nmodes = ARRAY_SIZE(cif_mode); - sd->block_size = 0x80; - } else { - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - sd->block_size = 0x200; - } - - INIT_WORK(&sd->work_struct, jl2005c_dostream); - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - return 0; -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - - struct sd *sd = (struct sd *) gspca_dev; - sd->cap_mode = gspca_dev->cam.cam_mode; - - switch (gspca_dev->width) { - case 640: - PDEBUG(D_STREAM, "Start streaming at vga resolution"); - jl2005c_stream_start_vga_lg(gspca_dev); - break; - case 320: - PDEBUG(D_STREAM, "Start streaming at qvga resolution"); - jl2005c_stream_start_vga_small(gspca_dev); - break; - case 352: - PDEBUG(D_STREAM, "Start streaming at cif resolution"); - jl2005c_stream_start_cif_lg(gspca_dev); - break; - case 176: - PDEBUG(D_STREAM, "Start streaming at qcif resolution"); - jl2005c_stream_start_cif_small(gspca_dev); - break; - default: - pr_err("Unknown resolution specified\n"); - return -1; - } - - /* Start the workqueue function to do the streaming */ - sd->work_thread = create_singlethread_workqueue(MODULE_NAME); - queue_work(sd->work_thread, &sd->work_struct); - - return 0; -} - -/* called on streamoff with alt==0 and on disconnect */ -/* the usb_lock is held at entry - restore on exit */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct sd *dev = (struct sd *) gspca_dev; - - /* wait for the work queue to terminate */ - mutex_unlock(&gspca_dev->usb_lock); - /* This waits for sq905c_dostream to finish */ - destroy_workqueue(dev->work_thread); - dev->work_thread = NULL; - mutex_lock(&gspca_dev->usb_lock); -} - - - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .start = sd_start, - .stop0 = sd_stop0, -}; - -/* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { - {USB_DEVICE(0x0979, 0x0227)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -/* -- module insert / remove -- */ -static int __init sd_mod_init(void) -{ - int ret; - - ret = usb_register(&sd_driver); - if (ret < 0) - return ret; - return 0; -} -static void __exit sd_mod_exit(void) -{ - usb_deregister(&sd_driver); -} - -module_init(sd_mod_init); -module_exit(sd_mod_exit); diff --git a/drivers/media/video/gspca/jpeg.h b/drivers/media/video/gspca/jpeg.h deleted file mode 100644 index ab54910418b4..000000000000 --- a/drivers/media/video/gspca/jpeg.h +++ /dev/null @@ -1,168 +0,0 @@ -#ifndef JPEG_H -#define JPEG_H 1 -/* - * Insert a JPEG header at start of frame - * - * This module is used by the gspca subdrivers. - * A special case is done for Conexant webcams. - * - * Copyright (C) Jean-Francois Moine (http://moinejf.free.fr) - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* - * generation options - * CONEX_CAM Conexant if present - */ - -/* JPEG header */ -static const u8 jpeg_head[] = { - 0xff, 0xd8, /* jpeg */ - -/* quantization table quality 50% */ - 0xff, 0xdb, 0x00, 0x84, /* DQT */ -0, -#define JPEG_QT0_OFFSET 7 - 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, - 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, - 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, - 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, - 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44, - 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, - 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, - 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63, -1, -#define JPEG_QT1_OFFSET 72 - 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, - 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - -/* huffman table */ - 0xff, 0xc4, 0x01, 0xa2, - 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01, 0x00, 0x03, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, - 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, - 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04, - 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, - 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, - 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, - 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, - 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, - 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, - 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, - 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, - 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, - 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, - 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, - 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, - 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, - 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, - 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, - 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, - 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, - 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02, - 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, - 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, - 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, - 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, - 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, - 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, - 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, - 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, - 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, - 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, - 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, - 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, - 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, - 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, - 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, - 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, - 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, -#ifdef CONEX_CAM -/* the Conexant frames start with SOF0 */ -#define JPEG_HDR_SZ 556 -#else - 0xff, 0xc0, 0x00, 0x11, /* SOF0 (start of frame 0 */ - 0x08, /* data precision */ -#define JPEG_HEIGHT_OFFSET 561 - 0x01, 0xe0, /* height */ - 0x02, 0x80, /* width */ - 0x03, /* component number */ - 0x01, - 0x21, /* samples Y */ - 0x00, /* quant Y */ - 0x02, 0x11, 0x01, /* samples CbCr - quant CbCr */ - 0x03, 0x11, 0x01, - - 0xff, 0xda, 0x00, 0x0c, /* SOS (start of scan) */ - 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 -#define JPEG_HDR_SZ 589 -#endif -}; - -/* define the JPEG header */ -static void jpeg_define(u8 *jpeg_hdr, - int height, - int width, - int samplesY) -{ - memcpy(jpeg_hdr, jpeg_head, sizeof jpeg_head); -#ifndef CONEX_CAM - jpeg_hdr[JPEG_HEIGHT_OFFSET + 0] = height >> 8; - jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height; - jpeg_hdr[JPEG_HEIGHT_OFFSET + 2] = width >> 8; - jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width; - jpeg_hdr[JPEG_HEIGHT_OFFSET + 6] = samplesY; -#endif -} - -/* set the JPEG quality */ -static void jpeg_set_qual(u8 *jpeg_hdr, - int quality) -{ - int i, sc; - - if (quality < 50) - sc = 5000 / quality; - else - sc = 200 - quality * 2; - for (i = 0; i < 64; i++) { - jpeg_hdr[JPEG_QT0_OFFSET + i] = - (jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100; - jpeg_hdr[JPEG_QT1_OFFSET + i] = - (jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100; - } -} -#endif diff --git a/drivers/media/video/gspca/kinect.c b/drivers/media/video/gspca/kinect.c deleted file mode 100644 index 40ad6687ee5d..000000000000 --- a/drivers/media/video/gspca/kinect.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * kinect sensor device camera, gspca driver - * - * Copyright (C) 2011 Antonio Ospite <ospite@studenti.unina.it> - * - * Based on the OpenKinect project and libfreenect - * http://openkinect.org/wiki/Init_Analysis - * - * Special thanks to Steven Toth and kernellabs.com for sponsoring a Kinect - * sensor device which I tested the driver on. - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "kinect" - -#include "gspca.h" - -#define CTRL_TIMEOUT 500 - -MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); -MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver"); -MODULE_LICENSE("GPL"); - -struct pkt_hdr { - uint8_t magic[2]; - uint8_t pad; - uint8_t flag; - uint8_t unk1; - uint8_t seq; - uint8_t unk2; - uint8_t unk3; - uint32_t timestamp; -}; - -struct cam_hdr { - uint8_t magic[2]; - uint16_t len; - uint16_t cmd; - uint16_t tag; -}; - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - uint16_t cam_tag; /* a sequence number for packets */ - uint8_t stream_flag; /* to identify different stream types */ - uint8_t obuf[0x400]; /* output buffer for control commands */ - uint8_t ibuf[0x200]; /* input buffer for control commands */ -}; - -#define MODE_640x480 0x0001 -#define MODE_640x488 0x0002 -#define MODE_1280x1024 0x0004 - -#define FORMAT_BAYER 0x0010 -#define FORMAT_UYVY 0x0020 -#define FORMAT_Y10B 0x0040 - -#define FPS_HIGH 0x0100 - -static const struct v4l2_pix_format video_camera_mode[] = { - {640, 480, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = MODE_640x480 | FORMAT_BAYER | FPS_HIGH}, - {640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, - .bytesperline = 640 * 2, - .sizeimage = 640 * 480 * 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = MODE_640x480 | FORMAT_UYVY}, - {1280, 1024, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, - .bytesperline = 1280, - .sizeimage = 1280 * 1024, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = MODE_1280x1024 | FORMAT_BAYER}, - {640, 488, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE, - .bytesperline = 640 * 10 / 8, - .sizeimage = 640 * 488 * 10 / 8, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = MODE_640x488 | FORMAT_Y10B | FPS_HIGH}, - {1280, 1024, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE, - .bytesperline = 1280 * 10 / 8, - .sizeimage = 1280 * 1024 * 10 / 8, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = MODE_1280x1024 | FORMAT_Y10B}, -}; - -static int kinect_write(struct usb_device *udev, uint8_t *data, - uint16_t wLength) -{ - return usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), - 0x00, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, 0, data, wLength, CTRL_TIMEOUT); -} - -static int kinect_read(struct usb_device *udev, uint8_t *data, uint16_t wLength) -{ - return usb_control_msg(udev, - usb_rcvctrlpipe(udev, 0), - 0x00, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, 0, data, wLength, CTRL_TIMEOUT); -} - -static int send_cmd(struct gspca_dev *gspca_dev, uint16_t cmd, void *cmdbuf, - unsigned int cmd_len, void *replybuf, unsigned int reply_len) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *udev = gspca_dev->dev; - int res, actual_len; - uint8_t *obuf = sd->obuf; - uint8_t *ibuf = sd->ibuf; - struct cam_hdr *chdr = (void *)obuf; - struct cam_hdr *rhdr = (void *)ibuf; - - if (cmd_len & 1 || cmd_len > (0x400 - sizeof(*chdr))) { - pr_err("send_cmd: Invalid command length (0x%x)\n", cmd_len); - return -1; - } - - chdr->magic[0] = 0x47; - chdr->magic[1] = 0x4d; - chdr->cmd = cpu_to_le16(cmd); - chdr->tag = cpu_to_le16(sd->cam_tag); - chdr->len = cpu_to_le16(cmd_len / 2); - - memcpy(obuf+sizeof(*chdr), cmdbuf, cmd_len); - - res = kinect_write(udev, obuf, cmd_len + sizeof(*chdr)); - PDEBUG(D_USBO, "Control cmd=%04x tag=%04x len=%04x: %d", cmd, - sd->cam_tag, cmd_len, res); - if (res < 0) { - pr_err("send_cmd: Output control transfer failed (%d)\n", res); - return res; - } - - do { - actual_len = kinect_read(udev, ibuf, 0x200); - } while (actual_len == 0); - PDEBUG(D_USBO, "Control reply: %d", res); - if (actual_len < sizeof(*rhdr)) { - pr_err("send_cmd: Input control transfer failed (%d)\n", res); - return res; - } - actual_len -= sizeof(*rhdr); - - if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) { - pr_err("send_cmd: Bad magic %02x %02x\n", - rhdr->magic[0], rhdr->magic[1]); - return -1; - } - if (rhdr->cmd != chdr->cmd) { - pr_err("send_cmd: Bad cmd %02x != %02x\n", - rhdr->cmd, chdr->cmd); - return -1; - } - if (rhdr->tag != chdr->tag) { - pr_err("send_cmd: Bad tag %04x != %04x\n", - rhdr->tag, chdr->tag); - return -1; - } - if (cpu_to_le16(rhdr->len) != (actual_len/2)) { - pr_err("send_cmd: Bad len %04x != %04x\n", - cpu_to_le16(rhdr->len), (int)(actual_len/2)); - return -1; - } - - if (actual_len > reply_len) { - pr_warn("send_cmd: Data buffer is %d bytes long, but got %d bytes\n", - reply_len, actual_len); - memcpy(replybuf, ibuf+sizeof(*rhdr), reply_len); - } else { - memcpy(replybuf, ibuf+sizeof(*rhdr), actual_len); - } - - sd->cam_tag++; - - return actual_len; -} - -static int write_register(struct gspca_dev *gspca_dev, uint16_t reg, - uint16_t data) -{ - uint16_t reply[2]; - uint16_t cmd[2]; - int res; - - cmd[0] = cpu_to_le16(reg); - cmd[1] = cpu_to_le16(data); - - PDEBUG(D_USBO, "Write Reg 0x%04x <= 0x%02x", reg, data); - res = send_cmd(gspca_dev, 0x03, cmd, 4, reply, 4); - if (res < 0) - return res; - if (res != 2) { - pr_warn("send_cmd returned %d [%04x %04x], 0000 expected\n", - res, reply[0], reply[1]); - } - return 0; -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - - sd->cam_tag = 0; - - /* Only video stream is supported for now, - * which has stream flag = 0x80 */ - sd->stream_flag = 0x80; - - cam = &gspca_dev->cam; - - cam->cam_mode = video_camera_mode; - cam->nmodes = ARRAY_SIZE(video_camera_mode); - -#if 0 - /* Setting those values is not needed for video stream */ - cam->npkt = 15; - gspca_dev->pkt_size = 960 * 2; -#endif - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - PDEBUG(D_PROBE, "Kinect Camera device."); - - return 0; -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - int mode; - uint8_t fmt_reg, fmt_val; - uint8_t res_reg, res_val; - uint8_t fps_reg, fps_val; - uint8_t mode_val; - - mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - - if (mode & FORMAT_Y10B) { - fmt_reg = 0x19; - res_reg = 0x1a; - fps_reg = 0x1b; - mode_val = 0x03; - } else { - fmt_reg = 0x0c; - res_reg = 0x0d; - fps_reg = 0x0e; - mode_val = 0x01; - } - - /* format */ - if (mode & FORMAT_UYVY) - fmt_val = 0x05; - else - fmt_val = 0x00; - - if (mode & MODE_1280x1024) - res_val = 0x02; - else - res_val = 0x01; - - if (mode & FPS_HIGH) - fps_val = 0x1e; - else - fps_val = 0x0f; - - - /* turn off IR-reset function */ - write_register(gspca_dev, 0x105, 0x00); - - /* Reset video stream */ - write_register(gspca_dev, 0x05, 0x00); - - /* Due to some ridiculous condition in the firmware, we have to start - * and stop the depth stream before the camera will hand us 1280x1024 - * IR. This is a stupid workaround, but we've yet to find a better - * solution. - * - * Thanks to Drew Fisher for figuring this out. - */ - if (mode & (FORMAT_Y10B | MODE_1280x1024)) { - write_register(gspca_dev, 0x13, 0x01); - write_register(gspca_dev, 0x14, 0x1e); - write_register(gspca_dev, 0x06, 0x02); - write_register(gspca_dev, 0x06, 0x00); - } - - write_register(gspca_dev, fmt_reg, fmt_val); - write_register(gspca_dev, res_reg, res_val); - write_register(gspca_dev, fps_reg, fps_val); - - /* Start video stream */ - write_register(gspca_dev, 0x05, mode_val); - - /* disable Hflip */ - write_register(gspca_dev, 0x47, 0x00); - - return 0; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - /* reset video stream */ - write_register(gspca_dev, 0x05, 0x00); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - - struct pkt_hdr *hdr = (void *)__data; - uint8_t *data = __data + sizeof(*hdr); - int datalen = len - sizeof(*hdr); - - uint8_t sof = sd->stream_flag | 1; - uint8_t mof = sd->stream_flag | 2; - uint8_t eof = sd->stream_flag | 5; - - if (len < 12) - return; - - if (hdr->magic[0] != 'R' || hdr->magic[1] != 'B') { - pr_warn("[Stream %02x] Invalid magic %02x%02x\n", - sd->stream_flag, hdr->magic[0], hdr->magic[1]); - return; - } - - if (hdr->flag == sof) - gspca_frame_add(gspca_dev, FIRST_PACKET, data, datalen); - - else if (hdr->flag == mof) - gspca_frame_add(gspca_dev, INTER_PACKET, data, datalen); - - else if (hdr->flag == eof) - gspca_frame_add(gspca_dev, LAST_PACKET, data, datalen); - - else - pr_warn("Packet type not recognized...\n"); -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, - /* - .get_streamparm = sd_get_streamparm, - .set_streamparm = sd_set_streamparm, - */ -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x045e, 0x02ae)}, - {} -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/konica.c b/drivers/media/video/gspca/konica.c deleted file mode 100644 index bbf91e07e38b..000000000000 --- a/drivers/media/video/gspca/konica.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Driver for USB webcams based on Konica chipset. This - * chipset is used in Intel YC76 camera. - * - * Copyright (C) 2010 Hans de Goede <hdegoede@redhat.com> - * - * Based on the usbvideo v4l1 konicawc driver which is: - * - * Copyright (C) 2002 Simon Evans <spse@secret.org.uk> - * - * The code for making gspca work with a webcam with 2 isoc endpoints was - * taken from the benq gspca subdriver which is: - * - * Copyright (C) 2009 Jean-Francois Moine (http://moinejf.free.fr) - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "konica" - -#include <linux/input.h> -#include "gspca.h" - -MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); -MODULE_DESCRIPTION("Konica chipset USB Camera Driver"); -MODULE_LICENSE("GPL"); - -#define WHITEBAL_REG 0x01 -#define BRIGHTNESS_REG 0x02 -#define SHARPNESS_REG 0x03 -#define CONTRAST_REG 0x04 -#define SATURATION_REG 0x05 - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - struct urb *last_data_urb; - u8 snapshot_pressed; -}; - - -/* .priv is what goes to register 8 for this mode, known working values: - 0x00 -> 176x144, cropped - 0x01 -> 176x144, cropped - 0x02 -> 176x144, cropped - 0x03 -> 176x144, cropped - 0x04 -> 176x144, binned - 0x05 -> 320x240 - 0x06 -> 320x240 - 0x07 -> 160x120, cropped - 0x08 -> 160x120, cropped - 0x09 -> 160x120, binned (note has 136 lines) - 0x0a -> 160x120, binned (note has 136 lines) - 0x0b -> 160x120, cropped -*/ -static const struct v4l2_pix_format vga_mode[] = { - {160, 120, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 136 * 3 / 2 + 960, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0x0a}, - {176, 144, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 2 + 960, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0x04}, - {320, 240, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 2 + 960, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0x05}, -}; - -static void sd_isoc_irq(struct urb *urb); - -static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index) -{ - struct usb_device *dev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return; - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x02, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - NULL, - 0, - 1000); - if (ret < 0) { - pr_err("reg_w err writing %02x to %02x: %d\n", - value, index, ret); - gspca_dev->usb_err = ret; - } -} - -static void reg_r(struct gspca_dev *gspca_dev, u16 value, u16 index) -{ - struct usb_device *dev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return; - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - 0x03, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - gspca_dev->usb_buf, - 2, - 1000); - if (ret < 0) { - pr_err("reg_r err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -static void konica_stream_on(struct gspca_dev *gspca_dev) -{ - reg_w(gspca_dev, 1, 0x0b); -} - -static void konica_stream_off(struct gspca_dev *gspca_dev) -{ - reg_w(gspca_dev, 0, 0x0b); -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - gspca_dev->cam.cam_mode = vga_mode; - gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); - gspca_dev->cam.no_urb_create = 1; - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - int i; - - /* - * The konica needs a freaking large time to "boot" (approx 6.5 sec.), - * and does not want to be bothered while doing so :| - * Register 0x10 counts from 1 - 3, with 3 being "ready" - */ - msleep(6000); - for (i = 0; i < 20; i++) { - reg_r(gspca_dev, 0, 0x10); - if (gspca_dev->usb_buf[0] == 3) - break; - msleep(100); - } - reg_w(gspca_dev, 0, 0x0d); - - return gspca_dev->usb_err; -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct urb *urb; - int i, n, packet_size; - struct usb_host_interface *alt; - struct usb_interface *intf; - - intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); - alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); - if (!alt) { - pr_err("Couldn't get altsetting\n"); - return -EIO; - } - - packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); - - n = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - reg_w(gspca_dev, n, 0x08); - - konica_stream_on(gspca_dev); - - if (gspca_dev->usb_err) - return gspca_dev->usb_err; - - /* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */ -#if MAX_NURBS < 4 -#error "Not enough URBs in the gspca table" -#endif -#define SD_NPKT 32 - for (n = 0; n < 4; n++) { - i = n & 1 ? 0 : 1; - packet_size = - le16_to_cpu(alt->endpoint[i].desc.wMaxPacketSize); - urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL); - if (!urb) { - pr_err("usb_alloc_urb failed\n"); - return -ENOMEM; - } - gspca_dev->urb[n] = urb; - urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev, - packet_size * SD_NPKT, - GFP_KERNEL, - &urb->transfer_dma); - if (urb->transfer_buffer == NULL) { - pr_err("usb_buffer_alloc failed\n"); - return -ENOMEM; - } - - urb->dev = gspca_dev->dev; - urb->context = gspca_dev; - urb->transfer_buffer_length = packet_size * SD_NPKT; - urb->pipe = usb_rcvisocpipe(gspca_dev->dev, - n & 1 ? 0x81 : 0x82); - urb->transfer_flags = URB_ISO_ASAP - | URB_NO_TRANSFER_DMA_MAP; - urb->interval = 1; - urb->complete = sd_isoc_irq; - urb->number_of_packets = SD_NPKT; - for (i = 0; i < SD_NPKT; i++) { - urb->iso_frame_desc[i].length = packet_size; - urb->iso_frame_desc[i].offset = packet_size * i; - } - } - - return 0; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - konica_stream_off(gspca_dev); -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - /* Don't keep the button in the pressed state "forever" if it was - pressed when streaming is stopped */ - if (sd->snapshot_pressed) { - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); - input_sync(gspca_dev->input_dev); - sd->snapshot_pressed = 0; - } -#endif -} - -/* reception of an URB */ -static void sd_isoc_irq(struct urb *urb) -{ - struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; - struct sd *sd = (struct sd *) gspca_dev; - struct urb *data_urb, *status_urb; - u8 *data; - int i, st; - - PDEBUG(D_PACK, "sd isoc irq"); - if (!gspca_dev->streaming) - return; - - if (urb->status != 0) { - if (urb->status == -ESHUTDOWN) - return; /* disconnection */ -#ifdef CONFIG_PM - if (gspca_dev->frozen) - return; -#endif - PDEBUG(D_ERR, "urb status: %d", urb->status); - st = usb_submit_urb(urb, GFP_ATOMIC); - if (st < 0) - pr_err("resubmit urb error %d\n", st); - return; - } - - /* if this is a data URB (ep 0x82), wait */ - if (urb->transfer_buffer_length > 32) { - sd->last_data_urb = urb; - return; - } - - status_urb = urb; - data_urb = sd->last_data_urb; - sd->last_data_urb = NULL; - - if (!data_urb || data_urb->start_frame != status_urb->start_frame) { - PDEBUG(D_ERR|D_PACK, "lost sync on frames"); - goto resubmit; - } - - if (data_urb->number_of_packets != status_urb->number_of_packets) { - PDEBUG(D_ERR|D_PACK, - "no packets does not match, data: %d, status: %d", - data_urb->number_of_packets, - status_urb->number_of_packets); - goto resubmit; - } - - for (i = 0; i < status_urb->number_of_packets; i++) { - if (data_urb->iso_frame_desc[i].status || - status_urb->iso_frame_desc[i].status) { - PDEBUG(D_ERR|D_PACK, - "pkt %d data-status %d, status-status %d", i, - data_urb->iso_frame_desc[i].status, - status_urb->iso_frame_desc[i].status); - gspca_dev->last_packet_type = DISCARD_PACKET; - continue; - } - - if (status_urb->iso_frame_desc[i].actual_length != 1) { - PDEBUG(D_ERR|D_PACK, - "bad status packet length %d", - status_urb->iso_frame_desc[i].actual_length); - gspca_dev->last_packet_type = DISCARD_PACKET; - continue; - } - - st = *((u8 *)status_urb->transfer_buffer - + status_urb->iso_frame_desc[i].offset); - - data = (u8 *)data_urb->transfer_buffer - + data_urb->iso_frame_desc[i].offset; - - /* st: 0x80-0xff: frame start with frame number (ie 0-7f) - * otherwise: - * bit 0 0: keep packet - * 1: drop packet (padding data) - * - * bit 4 0 button not clicked - * 1 button clicked - * button is used to `take a picture' (in software) - */ - if (st & 0x80) { - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); - } else { -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - u8 button_state = st & 0x40 ? 1 : 0; - if (sd->snapshot_pressed != button_state) { - input_report_key(gspca_dev->input_dev, - KEY_CAMERA, - button_state); - input_sync(gspca_dev->input_dev); - sd->snapshot_pressed = button_state; - } -#endif - if (st & 0x01) - continue; - } - gspca_frame_add(gspca_dev, INTER_PACKET, data, - data_urb->iso_frame_desc[i].actual_length); - } - -resubmit: - if (data_urb) { - st = usb_submit_urb(data_urb, GFP_ATOMIC); - if (st < 0) - PDEBUG(D_ERR|D_PACK, - "usb_submit_urb(data_urb) ret %d", st); - } - st = usb_submit_urb(status_urb, GFP_ATOMIC); - if (st < 0) - pr_err("usb_submit_urb(status_urb) ret %d\n", st); -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - konica_stream_off(gspca_dev); - reg_w(gspca_dev, ctrl->val, BRIGHTNESS_REG); - konica_stream_on(gspca_dev); - break; - case V4L2_CID_CONTRAST: - konica_stream_off(gspca_dev); - reg_w(gspca_dev, ctrl->val, CONTRAST_REG); - konica_stream_on(gspca_dev); - break; - case V4L2_CID_SATURATION: - konica_stream_off(gspca_dev); - reg_w(gspca_dev, ctrl->val, SATURATION_REG); - konica_stream_on(gspca_dev); - break; - case V4L2_CID_WHITE_BALANCE_TEMPERATURE: - konica_stream_off(gspca_dev); - reg_w(gspca_dev, ctrl->val, WHITEBAL_REG); - konica_stream_on(gspca_dev); - break; - case V4L2_CID_SHARPNESS: - konica_stream_off(gspca_dev); - reg_w(gspca_dev, ctrl->val, SHARPNESS_REG); - konica_stream_on(gspca_dev); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 5); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 9, 1, 4); - /* Needs to be verified */ - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 9, 1, 4); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SATURATION, 0, 9, 1, 4); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_WHITE_BALANCE_TEMPERATURE, - 0, 33, 1, 25); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SHARPNESS, 0, 9, 1, 4); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .other_input = 1, -#endif -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x04c8, 0x0720)}, /* Intel YC 76 */ - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/m5602/Kconfig b/drivers/media/video/gspca/m5602/Kconfig deleted file mode 100644 index 5a69016ed75f..000000000000 --- a/drivers/media/video/gspca/m5602/Kconfig +++ /dev/null @@ -1,11 +0,0 @@ -config USB_M5602 - tristate "ALi USB m5602 Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help - Say Y here if you want support for cameras based on the - ALi m5602 connected to various image sensors. - - See <file:Documentation/video4linux/m5602.txt> for more info. - - To compile this driver as a module, choose M here: the - module will be called gspca_m5602. diff --git a/drivers/media/video/gspca/m5602/Makefile b/drivers/media/video/gspca/m5602/Makefile deleted file mode 100644 index 575b75bacb62..000000000000 --- a/drivers/media/video/gspca/m5602/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -obj-$(CONFIG_USB_M5602) += gspca_m5602.o - -gspca_m5602-objs := m5602_core.o \ - m5602_ov9650.o \ - m5602_ov7660.o \ - m5602_mt9m111.o \ - m5602_po1030.o \ - m5602_s5k83a.o \ - m5602_s5k4aa.o - -ccflags-y += -I$(srctree)/drivers/media/video/gspca diff --git a/drivers/media/video/gspca/m5602/m5602_bridge.h b/drivers/media/video/gspca/m5602/m5602_bridge.h deleted file mode 100644 index 51af3ee3ab85..000000000000 --- a/drivers/media/video/gspca/m5602/m5602_bridge.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * USB Driver for ALi m5602 based webcams - * - * Copyright (C) 2008 Erik Andrén - * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. - * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> - * - * Portions of code to USB interface and ALi driver software, - * Copyright (c) 2006 Willem Duinker - * v4l2 interface modeled after the V4L2 driver - * for SN9C10x PC Camera Controllers - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#ifndef M5602_BRIDGE_H_ -#define M5602_BRIDGE_H_ - -#include <linux/slab.h> -#include "gspca.h" - -#define MODULE_NAME "ALi m5602" - -/*****************************************************************************/ - -#define M5602_XB_SENSOR_TYPE 0x00 -#define M5602_XB_SENSOR_CTRL 0x01 -#define M5602_XB_LINE_OF_FRAME_H 0x02 -#define M5602_XB_LINE_OF_FRAME_L 0x03 -#define M5602_XB_PIX_OF_LINE_H 0x04 -#define M5602_XB_PIX_OF_LINE_L 0x05 -#define M5602_XB_VSYNC_PARA 0x06 -#define M5602_XB_HSYNC_PARA 0x07 -#define M5602_XB_TEST_MODE_1 0x08 -#define M5602_XB_TEST_MODE_2 0x09 -#define M5602_XB_SIG_INI 0x0a -#define M5602_XB_DS_PARA 0x0e -#define M5602_XB_TRIG_PARA 0x0f -#define M5602_XB_CLK_PD 0x10 -#define M5602_XB_MCU_CLK_CTRL 0x12 -#define M5602_XB_MCU_CLK_DIV 0x13 -#define M5602_XB_SEN_CLK_CTRL 0x14 -#define M5602_XB_SEN_CLK_DIV 0x15 -#define M5602_XB_AUD_CLK_CTRL 0x16 -#define M5602_XB_AUD_CLK_DIV 0x17 -#define M5602_OB_AC_LINK_STATE 0x22 -#define M5602_OB_PCM_SLOT_INDEX 0x24 -#define M5602_OB_GPIO_SLOT_INDEX 0x25 -#define M5602_OB_ACRX_STATUS_ADDRESS_H 0x28 -#define M5602_OB_ACRX_STATUS_DATA_L 0x29 -#define M5602_OB_ACRX_STATUS_DATA_H 0x2a -#define M5602_OB_ACTX_COMMAND_ADDRESS 0x31 -#define M5602_OB_ACRX_COMMAND_DATA_L 0x32 -#define M5602_OB_ACTX_COMMAND_DATA_H 0X33 -#define M5602_XB_DEVCTR1 0x41 -#define M5602_XB_EPSETR0 0x42 -#define M5602_XB_EPAFCTR 0x47 -#define M5602_XB_EPBFCTR 0x49 -#define M5602_XB_EPEFCTR 0x4f -#define M5602_XB_TEST_REG 0x53 -#define M5602_XB_ALT2SIZE 0x54 -#define M5602_XB_ALT3SIZE 0x55 -#define M5602_XB_OBSFRAME 0x56 -#define M5602_XB_PWR_CTL 0x59 -#define M5602_XB_ADC_CTRL 0x60 -#define M5602_XB_ADC_DATA 0x61 -#define M5602_XB_MISC_CTRL 0x62 -#define M5602_XB_SNAPSHOT 0x63 -#define M5602_XB_SCRATCH_1 0x64 -#define M5602_XB_SCRATCH_2 0x65 -#define M5602_XB_SCRATCH_3 0x66 -#define M5602_XB_SCRATCH_4 0x67 -#define M5602_XB_I2C_CTRL 0x68 -#define M5602_XB_I2C_CLK_DIV 0x69 -#define M5602_XB_I2C_DEV_ADDR 0x6a -#define M5602_XB_I2C_REG_ADDR 0x6b -#define M5602_XB_I2C_DATA 0x6c -#define M5602_XB_I2C_STATUS 0x6d -#define M5602_XB_GPIO_DAT_H 0x70 -#define M5602_XB_GPIO_DAT_L 0x71 -#define M5602_XB_GPIO_DIR_H 0x72 -#define M5602_XB_GPIO_DIR_L 0x73 -#define M5602_XB_GPIO_EN_H 0x74 -#define M5602_XB_GPIO_EN_L 0x75 -#define M5602_XB_GPIO_DAT 0x76 -#define M5602_XB_GPIO_DIR 0x77 -#define M5602_XB_SEN_CLK_CONTROL 0x80 -#define M5602_XB_SEN_CLK_DIVISION 0x81 -#define M5602_XB_CPR_CLK_CONTROL 0x82 -#define M5602_XB_CPR_CLK_DIVISION 0x83 -#define M5602_XB_MCU_CLK_CONTROL 0x84 -#define M5602_XB_MCU_CLK_DIVISION 0x85 -#define M5602_XB_DCT_CLK_CONTROL 0x86 -#define M5602_XB_DCT_CLK_DIVISION 0x87 -#define M5602_XB_EC_CLK_CONTROL 0x88 -#define M5602_XB_EC_CLK_DIVISION 0x89 -#define M5602_XB_LBUF_CLK_CONTROL 0x8a -#define M5602_XB_LBUF_CLK_DIVISION 0x8b - -#define I2C_BUSY 0x80 - -/*****************************************************************************/ - -/* Driver info */ -#define DRIVER_AUTHOR "ALi m5602 Linux Driver Project" -#define DRIVER_DESC "ALi m5602 webcam driver" - -#define M5602_ISOC_ENDPOINT_ADDR 0x81 -#define M5602_INTR_ENDPOINT_ADDR 0x82 - -#define M5602_URB_MSG_TIMEOUT 5000 - -/*****************************************************************************/ - -/* A skeleton used for sending messages to the m5602 bridge */ -static const unsigned char bridge_urb_skeleton[] = { - 0x13, 0x00, 0x81, 0x00 -}; - -/* A skeleton used for sending messages to the sensor */ -static const unsigned char sensor_urb_skeleton[] = { - 0x23, M5602_XB_GPIO_EN_H, 0x81, 0x06, - 0x23, M5602_XB_MISC_CTRL, 0x81, 0x80, - 0x13, M5602_XB_I2C_DEV_ADDR, 0x81, 0x00, - 0x13, M5602_XB_I2C_REG_ADDR, 0x81, 0x00, - 0x13, M5602_XB_I2C_DATA, 0x81, 0x00, - 0x13, M5602_XB_I2C_CTRL, 0x81, 0x11 -}; - -struct sd { - struct gspca_dev gspca_dev; - - /* A pointer to the currently connected sensor */ - const struct m5602_sensor *sensor; - - struct sd_desc *desc; - - /* Sensor private data */ - void *sensor_priv; - - /* The current frame's id, used to detect frame boundaries */ - u8 frame_id; - - /* The current frame count */ - u32 frame_count; -}; - -int m5602_read_bridge( - struct sd *sd, const u8 address, u8 *i2c_data); - -int m5602_write_bridge( - struct sd *sd, const u8 address, const u8 i2c_data); - -int m5602_write_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); - -int m5602_read_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); - -#endif diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c deleted file mode 100644 index ed22638978ce..000000000000 --- a/drivers/media/video/gspca/m5602/m5602_core.c +++ /dev/null @@ -1,424 +0,0 @@ - /* - * USB Driver for ALi m5602 based webcams - * - * Copyright (C) 2008 Erik Andrén - * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. - * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> - * - * Portions of code to USB interface and ALi driver software, - * Copyright (c) 2006 Willem Duinker - * v4l2 interface modeled after the V4L2 driver - * for SN9C10x PC Camera Controllers - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "m5602_ov9650.h" -#include "m5602_ov7660.h" -#include "m5602_mt9m111.h" -#include "m5602_po1030.h" -#include "m5602_s5k83a.h" -#include "m5602_s5k4aa.h" - -/* Kernel module parameters */ -int force_sensor; -static bool dump_bridge; -bool dump_sensor; - -static const struct usb_device_id m5602_table[] = { - {USB_DEVICE(0x0402, 0x5602)}, - {} -}; - -MODULE_DEVICE_TABLE(usb, m5602_table); - -/* Reads a byte from the m5602 */ -int m5602_read_bridge(struct sd *sd, const u8 address, u8 *i2c_data) -{ - int err; - struct usb_device *udev = sd->gspca_dev.dev; - __u8 *buf = sd->gspca_dev.usb_buf; - - err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - 0x04, 0xc0, 0x14, - 0x8100 + address, buf, - 1, M5602_URB_MSG_TIMEOUT); - *i2c_data = buf[0]; - - PDEBUG(D_CONF, "Reading bridge register 0x%x containing 0x%x", - address, *i2c_data); - - /* usb_control_msg(...) returns the number of bytes sent upon success, - mask that and return zero instead*/ - return (err < 0) ? err : 0; -} - -/* Writes a byte to the m5602 */ -int m5602_write_bridge(struct sd *sd, const u8 address, const u8 i2c_data) -{ - int err; - struct usb_device *udev = sd->gspca_dev.dev; - __u8 *buf = sd->gspca_dev.usb_buf; - - PDEBUG(D_CONF, "Writing bridge register 0x%x with 0x%x", - address, i2c_data); - - memcpy(buf, bridge_urb_skeleton, - sizeof(bridge_urb_skeleton)); - buf[1] = address; - buf[3] = i2c_data; - - err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x04, 0x40, 0x19, - 0x0000, buf, - 4, M5602_URB_MSG_TIMEOUT); - - /* usb_control_msg(...) returns the number of bytes sent upon success, - mask that and return zero instead */ - return (err < 0) ? err : 0; -} - -static int m5602_wait_for_i2c(struct sd *sd) -{ - int err; - u8 data; - - do { - err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, &data); - } while ((data & I2C_BUSY) && !err); - return err; -} - -int m5602_read_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len) -{ - int err, i; - - if (!len || len > sd->sensor->i2c_regW) - return -EINVAL; - - err = m5602_wait_for_i2c(sd); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, - sd->sensor->i2c_slave_id); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); - if (err < 0) - return err; - - /* Sensors with registers that are of only - one byte width are differently read */ - - /* FIXME: This works with the ov9650, but has issues with the po1030 */ - if (sd->sensor->i2c_regW == 1) { - err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 1); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); - } else { - err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len); - } - - for (i = 0; (i < len) && !err; i++) { - err = m5602_wait_for_i2c(sd); - if (err < 0) - return err; - - err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); - - PDEBUG(D_CONF, "Reading sensor register " - "0x%x containing 0x%x ", address, *i2c_data); - } - return err; -} - -int m5602_write_sensor(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len) -{ - int err, i; - u8 *p; - struct usb_device *udev = sd->gspca_dev.dev; - __u8 *buf = sd->gspca_dev.usb_buf; - - /* No sensor with a data width larger than 16 bits has yet been seen */ - if (len > sd->sensor->i2c_regW || !len) - return -EINVAL; - - memcpy(buf, sensor_urb_skeleton, - sizeof(sensor_urb_skeleton)); - - buf[11] = sd->sensor->i2c_slave_id; - buf[15] = address; - - /* Special case larger sensor writes */ - p = buf + 16; - - /* Copy a four byte write sequence for each byte to be written to */ - for (i = 0; i < len; i++) { - memcpy(p, sensor_urb_skeleton + 16, 4); - p[3] = i2c_data[i]; - p += 4; - PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x", - address, i2c_data[i]); - } - - /* Copy the tailer */ - memcpy(p, sensor_urb_skeleton + 20, 4); - - /* Set the total length */ - p[3] = 0x10 + len; - - err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x04, 0x40, 0x19, - 0x0000, buf, - 20 + len * 4, M5602_URB_MSG_TIMEOUT); - - return (err < 0) ? err : 0; -} - -/* Dump all the registers of the m5602 bridge, - unfortunately this breaks the camera until it's power cycled */ -static void m5602_dump_bridge(struct sd *sd) -{ - int i; - for (i = 0; i < 0x80; i++) { - unsigned char val = 0; - m5602_read_bridge(sd, i, &val); - pr_info("ALi m5602 address 0x%x contains 0x%x\n", i, val); - } - pr_info("Warning: The ALi m5602 webcam probably won't work until it's power cycled\n"); -} - -static int m5602_probe_sensor(struct sd *sd) -{ - /* Try the po1030 */ - sd->sensor = &po1030; - if (!sd->sensor->probe(sd)) - return 0; - - /* Try the mt9m111 sensor */ - sd->sensor = &mt9m111; - if (!sd->sensor->probe(sd)) - return 0; - - /* Try the s5k4aa */ - sd->sensor = &s5k4aa; - if (!sd->sensor->probe(sd)) - return 0; - - /* Try the ov9650 */ - sd->sensor = &ov9650; - if (!sd->sensor->probe(sd)) - return 0; - - /* Try the ov7660 */ - sd->sensor = &ov7660; - if (!sd->sensor->probe(sd)) - return 0; - - /* Try the s5k83a */ - sd->sensor = &s5k83a; - if (!sd->sensor->probe(sd)) - return 0; - - /* More sensor probe function goes here */ - pr_info("Failed to find a sensor\n"); - sd->sensor = NULL; - return -ENODEV; -} - -static int m5602_configure(struct gspca_dev *gspca_dev, - const struct usb_device_id *id); - -static int m5602_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int err; - - PDEBUG(D_CONF, "Initializing ALi m5602 webcam"); - /* Run the init sequence */ - err = sd->sensor->init(sd); - - return err; -} - -static int m5602_start_transfer(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - __u8 *buf = sd->gspca_dev.usb_buf; - int err; - - /* Send start command to the camera */ - const u8 buffer[4] = {0x13, 0xf9, 0x0f, 0x01}; - - if (sd->sensor->start) - sd->sensor->start(sd); - - memcpy(buf, buffer, sizeof(buffer)); - err = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x04, 0x40, 0x19, 0x0000, buf, - sizeof(buffer), M5602_URB_MSG_TIMEOUT); - - PDEBUG(D_STREAM, "Transfer started"); - return (err < 0) ? err : 0; -} - -static void m5602_urb_complete(struct gspca_dev *gspca_dev, - u8 *data, int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (len < 6) { - PDEBUG(D_PACK, "Packet is less than 6 bytes"); - return; - } - - /* Frame delimiter: ff xx xx xx ff ff */ - if (data[0] == 0xff && data[4] == 0xff && data[5] == 0xff && - data[2] != sd->frame_id) { - PDEBUG(D_FRAM, "Frame delimiter detected"); - sd->frame_id = data[2]; - - /* Remove the extra fluff appended on each header */ - data += 6; - len -= 6; - - /* Complete the last frame (if any) */ - gspca_frame_add(gspca_dev, LAST_PACKET, - NULL, 0); - sd->frame_count++; - - /* Create a new frame */ - gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); - - PDEBUG(D_FRAM, "Starting new frame %d", - sd->frame_count); - - } else { - int cur_frame_len; - - cur_frame_len = gspca_dev->image_len; - /* Remove urb header */ - data += 4; - len -= 4; - - if (cur_frame_len + len <= gspca_dev->frsz) { - PDEBUG(D_FRAM, "Continuing frame %d copying %d bytes", - sd->frame_count, len); - - gspca_frame_add(gspca_dev, INTER_PACKET, - data, len); - } else { - /* Add the remaining data up to frame size */ - gspca_frame_add(gspca_dev, INTER_PACKET, data, - gspca_dev->frsz - cur_frame_len); - } - } -} - -static void m5602_stop_transfer(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* Run the sensor specific end transfer sequence */ - if (sd->sensor->stop) - sd->sensor->stop(sd); -} - -/* sub-driver description, the ctrl and nctrl is filled at probe time */ -static struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = m5602_configure, - .init = m5602_init, - .start = m5602_start_transfer, - .stopN = m5602_stop_transfer, - .pkt_scan = m5602_urb_complete -}; - -/* this function is called at probe time */ -static int m5602_configure(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - int err; - - cam = &gspca_dev->cam; - sd->desc = &sd_desc; - - if (dump_bridge) - m5602_dump_bridge(sd); - - /* Probe sensor */ - err = m5602_probe_sensor(sd); - if (err) - goto fail; - - return 0; - -fail: - PDEBUG(D_ERR, "ALi m5602 webcam failed"); - cam->cam_mode = NULL; - cam->nmodes = 0; - - return err; -} - -static int m5602_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static void m5602_disconnect(struct usb_interface *intf) -{ - struct gspca_dev *gspca_dev = usb_get_intfdata(intf); - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor->disconnect) - sd->sensor->disconnect(sd); - - gspca_disconnect(intf); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = m5602_table, - .probe = m5602_probe, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif - .disconnect = m5602_disconnect -}; - -module_usb_driver(sd_driver); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -module_param(force_sensor, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(force_sensor, - "forces detection of a sensor, " - "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, " - "4 = MT9M111, 5 = PO1030, 6 = OV7660"); - -module_param(dump_bridge, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup"); - -module_param(dump_sensor, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(dump_sensor, "Dumps all usb sensor registers " - "at startup providing a sensor is found"); diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c deleted file mode 100644 index 6268aa24ec5d..000000000000 --- a/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ /dev/null @@ -1,647 +0,0 @@ -/* - * Driver for the mt9m111 sensor - * - * Copyright (C) 2008 Erik Andrén - * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. - * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> - * - * Portions of code to USB interface and ALi driver software, - * Copyright (c) 2006 Willem Duinker - * v4l2 interface modeled after the V4L2 driver - * for SN9C10x PC Camera Controllers - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "m5602_mt9m111.h" - -static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val); -static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); -static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); -static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val); -static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val); -static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val); -static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev, - __s32 val); -static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev, - __s32 *val); -static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val); -static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val); -static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); -static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); -static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); -static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); - -static struct v4l2_pix_format mt9m111_modes[] = { - { - 640, - 480, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = 640 * 480, - .bytesperline = 640, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - } -}; - -static const struct ctrl mt9m111_ctrls[] = { -#define VFLIP_IDX 0 - { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = mt9m111_set_vflip, - .get = mt9m111_get_vflip - }, -#define HFLIP_IDX 1 - { - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "horizontal flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = mt9m111_set_hflip, - .get = mt9m111_get_hflip - }, -#define GAIN_IDX 2 - { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "gain", - .minimum = 0, - .maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2, - .step = 1, - .default_value = MT9M111_DEFAULT_GAIN, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = mt9m111_set_gain, - .get = mt9m111_get_gain - }, -#define AUTO_WHITE_BALANCE_IDX 3 - { - { - .id = V4L2_CID_AUTO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto white balance", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - .set = mt9m111_set_auto_white_balance, - .get = mt9m111_get_auto_white_balance - }, -#define GREEN_BALANCE_IDX 4 - { - { - .id = M5602_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x7ff, - .step = 0x1, - .default_value = MT9M111_GREEN_GAIN_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = mt9m111_set_green_balance, - .get = mt9m111_get_green_balance - }, -#define BLUE_BALANCE_IDX 5 - { - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x7ff, - .step = 0x1, - .default_value = MT9M111_BLUE_GAIN_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = mt9m111_set_blue_balance, - .get = mt9m111_get_blue_balance - }, -#define RED_BALANCE_IDX 5 - { - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x7ff, - .step = 0x1, - .default_value = MT9M111_RED_GAIN_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = mt9m111_set_red_balance, - .get = mt9m111_get_red_balance - }, -}; - -static void mt9m111_dump_registers(struct sd *sd); - -int mt9m111_probe(struct sd *sd) -{ - u8 data[2] = {0x00, 0x00}; - int i; - s32 *sensor_settings; - - if (force_sensor) { - if (force_sensor == MT9M111_SENSOR) { - pr_info("Forcing a %s sensor\n", mt9m111.name); - goto sensor_found; - } - /* If we want to force another sensor, don't try to probe this - * one */ - return -ENODEV; - } - - PDEBUG(D_PROBE, "Probing for a mt9m111 sensor"); - - /* Do the preinit */ - for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) { - if (preinit_mt9m111[i][0] == BRIDGE) { - m5602_write_bridge(sd, - preinit_mt9m111[i][1], - preinit_mt9m111[i][2]); - } else { - data[0] = preinit_mt9m111[i][2]; - data[1] = preinit_mt9m111[i][3]; - m5602_write_sensor(sd, - preinit_mt9m111[i][1], data, 2); - } - } - - if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2)) - return -ENODEV; - - if ((data[0] == 0x14) && (data[1] == 0x3a)) { - pr_info("Detected a mt9m111 sensor\n"); - goto sensor_found; - } - - return -ENODEV; - -sensor_found: - sensor_settings = kmalloc(ARRAY_SIZE(mt9m111_ctrls) * sizeof(s32), - GFP_KERNEL); - if (!sensor_settings) - return -ENOMEM; - - sd->gspca_dev.cam.cam_mode = mt9m111_modes; - sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes); - sd->desc->ctrls = mt9m111_ctrls; - sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls); - - for (i = 0; i < ARRAY_SIZE(mt9m111_ctrls); i++) - sensor_settings[i] = mt9m111_ctrls[i].qctrl.default_value; - sd->sensor_priv = sensor_settings; - - return 0; -} - -int mt9m111_init(struct sd *sd) -{ - int i, err = 0; - s32 *sensor_settings = sd->sensor_priv; - - /* Init the sensor */ - for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) { - u8 data[2]; - - if (init_mt9m111[i][0] == BRIDGE) { - err = m5602_write_bridge(sd, - init_mt9m111[i][1], - init_mt9m111[i][2]); - } else { - data[0] = init_mt9m111[i][2]; - data[1] = init_mt9m111[i][3]; - err = m5602_write_sensor(sd, - init_mt9m111[i][1], data, 2); - } - } - - if (dump_sensor) - mt9m111_dump_registers(sd); - - err = mt9m111_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); - if (err < 0) - return err; - - err = mt9m111_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); - if (err < 0) - return err; - - err = mt9m111_set_green_balance(&sd->gspca_dev, - sensor_settings[GREEN_BALANCE_IDX]); - if (err < 0) - return err; - - err = mt9m111_set_blue_balance(&sd->gspca_dev, - sensor_settings[BLUE_BALANCE_IDX]); - if (err < 0) - return err; - - err = mt9m111_set_red_balance(&sd->gspca_dev, - sensor_settings[RED_BALANCE_IDX]); - if (err < 0) - return err; - - return mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); -} - -int mt9m111_start(struct sd *sd) -{ - int i, err = 0; - u8 data[2]; - struct cam *cam = &sd->gspca_dev.cam; - s32 *sensor_settings = sd->sensor_priv; - - int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1; - int height = cam->cam_mode[sd->gspca_dev.curr_mode].height; - - for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) { - if (start_mt9m111[i][0] == BRIDGE) { - err = m5602_write_bridge(sd, - start_mt9m111[i][1], - start_mt9m111[i][2]); - } else { - data[0] = start_mt9m111[i][2]; - data[1] = start_mt9m111[i][3]; - err = m5602_write_sensor(sd, - start_mt9m111[i][1], data, 2); - } - } - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff)); - if (err < 0) - return err; - - for (i = 0; i < 2 && !err; i++) - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2); - if (err < 0) - return err; - - for (i = 0; i < 2 && !err; i++) - err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, - (width >> 8) & 0xff); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, width & 0xff); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); - if (err < 0) - return err; - - switch (width) { - case 640: - PDEBUG(D_V4L2, "Configuring camera for VGA mode"); - data[0] = MT9M111_RMB_OVER_SIZED; - data[1] = MT9M111_RMB_ROW_SKIP_2X | - MT9M111_RMB_COLUMN_SKIP_2X | - (sensor_settings[VFLIP_IDX] << 0) | - (sensor_settings[HFLIP_IDX] << 1); - - err = m5602_write_sensor(sd, - MT9M111_SC_R_MODE_CONTEXT_B, data, 2); - break; - - case 320: - PDEBUG(D_V4L2, "Configuring camera for QVGA mode"); - data[0] = MT9M111_RMB_OVER_SIZED; - data[1] = MT9M111_RMB_ROW_SKIP_4X | - MT9M111_RMB_COLUMN_SKIP_4X | - (sensor_settings[VFLIP_IDX] << 0) | - (sensor_settings[HFLIP_IDX] << 1); - err = m5602_write_sensor(sd, - MT9M111_SC_R_MODE_CONTEXT_B, data, 2); - break; - } - return err; -} - -void mt9m111_disconnect(struct sd *sd) -{ - sd->sensor = NULL; - kfree(sd->sensor_priv); -} - -static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[VFLIP_IDX]; - PDEBUG(D_V4L2, "Read vertical flip %d", *val); - - return 0; -} - -static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 data[2] = {0x00, 0x00}; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Set vertical flip to %d", val); - - sensor_settings[VFLIP_IDX] = val; - - /* The mt9m111 is flipped by default */ - val = !val; - - /* Set the correct page map */ - err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); - if (err < 0) - return err; - - err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); - if (err < 0) - return err; - - data[1] = (data[1] & 0xfe) | val; - err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, - data, 2); - return err; -} - -static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[HFLIP_IDX]; - PDEBUG(D_V4L2, "Read horizontal flip %d", *val); - - return 0; -} - -static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 data[2] = {0x00, 0x00}; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Set horizontal flip to %d", val); - - sensor_settings[HFLIP_IDX] = val; - - /* The mt9m111 is flipped by default */ - val = !val; - - /* Set the correct page map */ - err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); - if (err < 0) - return err; - - err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); - if (err < 0) - return err; - - data[1] = (data[1] & 0xfd) | ((val << 1) & 0x02); - err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, - data, 2); - return err; -} - -static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[GAIN_IDX]; - PDEBUG(D_V4L2, "Read gain %d", *val); - - return 0; -} - -static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev, - __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - int err; - u8 data[2]; - - err = m5602_read_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2); - if (err < 0) - return err; - - sensor_settings[AUTO_WHITE_BALANCE_IDX] = val & 0x01; - data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1)); - - err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2); - - PDEBUG(D_V4L2, "Set auto white balance %d", val); - return err; -} - -static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev, - __s32 *val) { - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[AUTO_WHITE_BALANCE_IDX]; - PDEBUG(D_V4L2, "Read auto white balance %d", *val); - return 0; -} - -static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) -{ - int err, tmp; - u8 data[2] = {0x00, 0x00}; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - sensor_settings[GAIN_IDX] = val; - - /* Set the correct page map */ - err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); - if (err < 0) - return err; - - if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2) - return -EINVAL; - - if ((val >= INITIAL_MAX_GAIN * 2 * 2) && - (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2)) - tmp = (1 << 10) | (val << 9) | - (val << 8) | (val / 8); - else if ((val >= INITIAL_MAX_GAIN * 2) && - (val < INITIAL_MAX_GAIN * 2 * 2)) - tmp = (1 << 9) | (1 << 8) | (val / 4); - else if ((val >= INITIAL_MAX_GAIN) && - (val < INITIAL_MAX_GAIN * 2)) - tmp = (1 << 8) | (val / 2); - else - tmp = val; - - data[1] = (tmp & 0xff); - data[0] = (tmp & 0xff00) >> 8; - PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp, - data[1], data[0]); - - err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN, - data, 2); - - return err; -} - -static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 data[2]; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - sensor_settings[GREEN_BALANCE_IDX] = val; - data[1] = (val & 0xff); - data[0] = (val & 0xff00) >> 8; - - PDEBUG(D_V4L2, "Set green balance %d", val); - err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN, - data, 2); - if (err < 0) - return err; - - return m5602_write_sensor(sd, MT9M111_SC_GREEN_2_GAIN, - data, 2); -} - -static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[GREEN_BALANCE_IDX]; - PDEBUG(D_V4L2, "Read green balance %d", *val); - return 0; -} - -static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) -{ - u8 data[2]; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - sensor_settings[BLUE_BALANCE_IDX] = val; - data[1] = (val & 0xff); - data[0] = (val & 0xff00) >> 8; - - PDEBUG(D_V4L2, "Set blue balance %d", val); - - return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN, - data, 2); -} - -static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[BLUE_BALANCE_IDX]; - PDEBUG(D_V4L2, "Read blue balance %d", *val); - return 0; -} - -static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) -{ - u8 data[2]; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - sensor_settings[RED_BALANCE_IDX] = val; - data[1] = (val & 0xff); - data[0] = (val & 0xff00) >> 8; - - PDEBUG(D_V4L2, "Set red balance %d", val); - - return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN, - data, 2); -} - -static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[RED_BALANCE_IDX]; - PDEBUG(D_V4L2, "Read red balance %d", *val); - return 0; -} - -static void mt9m111_dump_registers(struct sd *sd) -{ - u8 address, value[2] = {0x00, 0x00}; - - pr_info("Dumping the mt9m111 register state\n"); - - pr_info("Dumping the mt9m111 sensor core registers\n"); - value[1] = MT9M111_SENSOR_CORE; - m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); - for (address = 0; address < 0xff; address++) { - m5602_read_sensor(sd, address, value, 2); - pr_info("register 0x%x contains 0x%x%x\n", - address, value[0], value[1]); - } - - pr_info("Dumping the mt9m111 color pipeline registers\n"); - value[1] = MT9M111_COLORPIPE; - m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); - for (address = 0; address < 0xff; address++) { - m5602_read_sensor(sd, address, value, 2); - pr_info("register 0x%x contains 0x%x%x\n", - address, value[0], value[1]); - } - - pr_info("Dumping the mt9m111 camera control registers\n"); - value[1] = MT9M111_CAMERA_CONTROL; - m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); - for (address = 0; address < 0xff; address++) { - m5602_read_sensor(sd, address, value, 2); - pr_info("register 0x%x contains 0x%x%x\n", - address, value[0], value[1]); - } - - pr_info("mt9m111 register state dump complete\n"); -} diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/drivers/media/video/gspca/m5602/m5602_mt9m111.h deleted file mode 100644 index 8c672b5c8c6a..000000000000 --- a/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Driver for the mt9m111 sensor - * - * Copyright (C) 2008 Erik Andrén - * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. - * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> - * - * Portions of code to USB interface and ALi driver software, - * Copyright (c) 2006 Willem Duinker - * v4l2 interface modeled after the V4L2 driver - * for SN9C10x PC Camera Controllers - * - * Some defines taken from the mt9m111 sensor driver - * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#ifndef M5602_MT9M111_H_ -#define M5602_MT9M111_H_ - -#include "m5602_sensor.h" - -/*****************************************************************************/ - -#define MT9M111_SC_CHIPVER 0x00 -#define MT9M111_SC_ROWSTART 0x01 -#define MT9M111_SC_COLSTART 0x02 -#define MT9M111_SC_WINDOW_HEIGHT 0x03 -#define MT9M111_SC_WINDOW_WIDTH 0x04 -#define MT9M111_SC_HBLANK_CONTEXT_B 0x05 -#define MT9M111_SC_VBLANK_CONTEXT_B 0x06 -#define MT9M111_SC_HBLANK_CONTEXT_A 0x07 -#define MT9M111_SC_VBLANK_CONTEXT_A 0x08 -#define MT9M111_SC_SHUTTER_WIDTH 0x09 -#define MT9M111_SC_ROW_SPEED 0x0a -#define MT9M111_SC_EXTRA_DELAY 0x0b -#define MT9M111_SC_SHUTTER_DELAY 0x0c -#define MT9M111_SC_RESET 0x0d -#define MT9M111_SC_R_MODE_CONTEXT_B 0x20 -#define MT9M111_SC_R_MODE_CONTEXT_A 0x21 -#define MT9M111_SC_FLASH_CONTROL 0x23 -#define MT9M111_SC_GREEN_1_GAIN 0x2b -#define MT9M111_SC_BLUE_GAIN 0x2c -#define MT9M111_SC_RED_GAIN 0x2d -#define MT9M111_SC_GREEN_2_GAIN 0x2e -#define MT9M111_SC_GLOBAL_GAIN 0x2f - -#define MT9M111_CONTEXT_CONTROL 0xc8 -#define MT9M111_PAGE_MAP 0xf0 -#define MT9M111_BYTEWISE_ADDRESS 0xf1 - -#define MT9M111_CP_OPERATING_MODE_CTL 0x06 -#define MT9M111_CP_LUMA_OFFSET 0x34 -#define MT9M111_CP_LUMA_CLIP 0x35 -#define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A 0x3a -#define MT9M111_CP_LENS_CORRECTION_1 0x3b -#define MT9M111_CP_DEFECT_CORR_CONTEXT_A 0x4c -#define MT9M111_CP_DEFECT_CORR_CONTEXT_B 0x4d -#define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B 0x9b -#define MT9M111_CP_GLOBAL_CLK_CONTROL 0xb3 - -#define MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18 0x65 -#define MT9M111_CC_AWB_PARAMETER_7 0x28 - -#define MT9M111_SENSOR_CORE 0x00 -#define MT9M111_COLORPIPE 0x01 -#define MT9M111_CAMERA_CONTROL 0x02 - -#define MT9M111_RESET (1 << 0) -#define MT9M111_RESTART (1 << 1) -#define MT9M111_ANALOG_STANDBY (1 << 2) -#define MT9M111_CHIP_ENABLE (1 << 3) -#define MT9M111_CHIP_DISABLE (0 << 3) -#define MT9M111_OUTPUT_DISABLE (1 << 4) -#define MT9M111_SHOW_BAD_FRAMES (1 << 0) -#define MT9M111_RESTART_BAD_FRAMES (1 << 1) -#define MT9M111_SYNCHRONIZE_CHANGES (1 << 7) - -#define MT9M111_RMB_OVER_SIZED (1 << 0) -#define MT9M111_RMB_MIRROR_ROWS (1 << 0) -#define MT9M111_RMB_MIRROR_COLS (1 << 1) -#define MT9M111_RMB_ROW_SKIP_2X (1 << 2) -#define MT9M111_RMB_COLUMN_SKIP_2X (1 << 3) -#define MT9M111_RMB_ROW_SKIP_4X (1 << 4) -#define MT9M111_RMB_COLUMN_SKIP_4X (1 << 5) - -#define MT9M111_COLOR_MATRIX_BYPASS (1 << 4) -#define MT9M111_SEL_CONTEXT_B (1 << 3) - -#define MT9M111_TRISTATE_PIN_IN_STANDBY (1 << 1) -#define MT9M111_SOC_SOFT_STANDBY (1 << 0) - -#define MT9M111_2D_DEFECT_CORRECTION_ENABLE (1 << 0) - -#define INITIAL_MAX_GAIN 64 -#define MT9M111_DEFAULT_GAIN 283 -#define MT9M111_GREEN_GAIN_DEFAULT 0x20 -#define MT9M111_BLUE_GAIN_DEFAULT 0x20 -#define MT9M111_RED_GAIN_DEFAULT 0x20 - -/*****************************************************************************/ - -/* Kernel module parameters */ -extern int force_sensor; -extern bool dump_sensor; - -int mt9m111_probe(struct sd *sd); -int mt9m111_init(struct sd *sd); -int mt9m111_start(struct sd *sd); -void mt9m111_disconnect(struct sd *sd); - -static const struct m5602_sensor mt9m111 = { - .name = "MT9M111", - - .i2c_slave_id = 0xba, - .i2c_regW = 2, - - .probe = mt9m111_probe, - .init = mt9m111_init, - .disconnect = mt9m111_disconnect, - .start = mt9m111_start, -}; - -static const unsigned char preinit_mt9m111[][4] = { - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, - {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, - MT9M111_RESET | - MT9M111_RESTART | - MT9M111_ANALOG_STANDBY | - MT9M111_CHIP_DISABLE, - MT9M111_SHOW_BAD_FRAMES | - MT9M111_RESTART_BAD_FRAMES | - MT9M111_SYNCHRONIZE_CHANGES}, - - {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, - - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, - - {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00} -}; - -static const unsigned char init_mt9m111[][4] = { - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, - {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, - - {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, - {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, - MT9M111_CP_OPERATING_MODE_CTL}, - {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, - {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, - MT9M111_2D_DEFECT_CORRECTION_ENABLE}, - {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, - MT9M111_2D_DEFECT_CORRECTION_ENABLE}, - {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, - {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, - {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, - {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, - {SENSOR, 0xcd, 0x00, 0x0e}, - {SENSOR, 0xd0, 0x00, 0x40}, - - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, - {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, - {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, - - {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, - {SENSOR, 0x33, 0x03, 0x49}, - {SENSOR, 0x34, 0xc0, 0x19}, - {SENSOR, 0x3f, 0x20, 0x20}, - {SENSOR, 0x40, 0x20, 0x20}, - {SENSOR, 0x5a, 0xc0, 0x0a}, - {SENSOR, 0x70, 0x7b, 0x0a}, - {SENSOR, 0x71, 0xff, 0x00}, - {SENSOR, 0x72, 0x19, 0x0e}, - {SENSOR, 0x73, 0x18, 0x0f}, - {SENSOR, 0x74, 0x57, 0x32}, - {SENSOR, 0x75, 0x56, 0x34}, - {SENSOR, 0x76, 0x73, 0x35}, - {SENSOR, 0x77, 0x30, 0x12}, - {SENSOR, 0x78, 0x79, 0x02}, - {SENSOR, 0x79, 0x75, 0x06}, - {SENSOR, 0x7a, 0x77, 0x0a}, - {SENSOR, 0x7b, 0x78, 0x09}, - {SENSOR, 0x7c, 0x7d, 0x06}, - {SENSOR, 0x7d, 0x31, 0x10}, - {SENSOR, 0x7e, 0x00, 0x7e}, - {SENSOR, 0x80, 0x59, 0x04}, - {SENSOR, 0x81, 0x59, 0x04}, - {SENSOR, 0x82, 0x57, 0x0a}, - {SENSOR, 0x83, 0x58, 0x0b}, - {SENSOR, 0x84, 0x47, 0x0c}, - {SENSOR, 0x85, 0x48, 0x0e}, - {SENSOR, 0x86, 0x5b, 0x02}, - {SENSOR, 0x87, 0x00, 0x5c}, - {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, MT9M111_SEL_CONTEXT_B}, - {SENSOR, 0x60, 0x00, 0x80}, - {SENSOR, 0x61, 0x00, 0x00}, - {SENSOR, 0x62, 0x00, 0x00}, - {SENSOR, 0x63, 0x00, 0x00}, - {SENSOR, 0x64, 0x00, 0x00}, - - {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, /* 13 */ - {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, /* 18 */ - {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, /* 1024 */ - {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, /* 1296 */ - {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, /* 352 */ - {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, /* 17 */ - {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, /* 352 */ - {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, /* 17 */ - {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, /* 271 */ - {SENSOR, 0x30, 0x04, 0x00}, - /* Set number of blank rows chosen to 400 */ - {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90}, -}; - -static const unsigned char start_mt9m111[][4] = { - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, -}; -#endif diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.c b/drivers/media/video/gspca/m5602/m5602_ov7660.c deleted file mode 100644 index 9a14835c128f..000000000000 --- a/drivers/media/video/gspca/m5602/m5602_ov7660.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Driver for the ov7660 sensor - * - * Copyright (C) 2009 Erik Andrén - * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. - * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> - * - * Portions of code to USB interface and ALi driver software, - * Copyright (c) 2006 Willem Duinker - * v4l2 interface modeled after the V4L2 driver - * for SN9C10x PC Camera Controllers - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "m5602_ov7660.h" - -static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val); -static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val); -static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev, - __s32 *val); -static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev, - __s32 val); -static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); -static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); -static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val); -static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val); -static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); -static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val); -static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); -static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val); - -static const struct ctrl ov7660_ctrls[] = { -#define GAIN_IDX 1 - { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "gain", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x1, - .default_value = OV7660_DEFAULT_GAIN, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = ov7660_set_gain, - .get = ov7660_get_gain - }, -#define BLUE_BALANCE_IDX 2 -#define RED_BALANCE_IDX 3 -#define AUTO_WHITE_BALANCE_IDX 4 - { - { - .id = V4L2_CID_AUTO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto white balance", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1 - }, - .set = ov7660_set_auto_white_balance, - .get = ov7660_get_auto_white_balance - }, -#define AUTO_GAIN_CTRL_IDX 5 - { - { - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto gain control", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1 - }, - .set = ov7660_set_auto_gain, - .get = ov7660_get_auto_gain - }, -#define AUTO_EXPOSURE_IDX 6 - { - { - .id = V4L2_CID_EXPOSURE_AUTO, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto exposure", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1 - }, - .set = ov7660_set_auto_exposure, - .get = ov7660_get_auto_exposure - }, -#define HFLIP_IDX 7 - { - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "horizontal flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = ov7660_set_hflip, - .get = ov7660_get_hflip - }, -#define VFLIP_IDX 8 - { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = ov7660_set_vflip, - .get = ov7660_get_vflip - }, - -}; - -static struct v4l2_pix_format ov7660_modes[] = { - { - 640, - 480, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - 640 * 480, - .bytesperline = 640, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - } -}; - -static void ov7660_dump_registers(struct sd *sd); - -int ov7660_probe(struct sd *sd) -{ - int err = 0, i; - u8 prod_id = 0, ver_id = 0; - - s32 *sensor_settings; - - if (force_sensor) { - if (force_sensor == OV7660_SENSOR) { - pr_info("Forcing an %s sensor\n", ov7660.name); - goto sensor_found; - } - /* If we want to force another sensor, - don't try to probe this one */ - return -ENODEV; - } - - /* Do the preinit */ - for (i = 0; i < ARRAY_SIZE(preinit_ov7660) && !err; i++) { - u8 data[2]; - - if (preinit_ov7660[i][0] == BRIDGE) { - err = m5602_write_bridge(sd, - preinit_ov7660[i][1], - preinit_ov7660[i][2]); - } else { - data[0] = preinit_ov7660[i][2]; - err = m5602_write_sensor(sd, - preinit_ov7660[i][1], data, 1); - } - } - if (err < 0) - return err; - - if (m5602_read_sensor(sd, OV7660_PID, &prod_id, 1)) - return -ENODEV; - - if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1)) - return -ENODEV; - - pr_info("Sensor reported 0x%x%x\n", prod_id, ver_id); - - if ((prod_id == 0x76) && (ver_id == 0x60)) { - pr_info("Detected a ov7660 sensor\n"); - goto sensor_found; - } - return -ENODEV; - -sensor_found: - sensor_settings = kmalloc( - ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL); - if (!sensor_settings) - return -ENOMEM; - - sd->gspca_dev.cam.cam_mode = ov7660_modes; - sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes); - sd->desc->ctrls = ov7660_ctrls; - sd->desc->nctrls = ARRAY_SIZE(ov7660_ctrls); - - for (i = 0; i < ARRAY_SIZE(ov7660_ctrls); i++) - sensor_settings[i] = ov7660_ctrls[i].qctrl.default_value; - sd->sensor_priv = sensor_settings; - - return 0; -} - -int ov7660_init(struct sd *sd) -{ - int i, err = 0; - s32 *sensor_settings = sd->sensor_priv; - - /* Init the sensor */ - for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) { - u8 data[2]; - - if (init_ov7660[i][0] == BRIDGE) { - err = m5602_write_bridge(sd, - init_ov7660[i][1], - init_ov7660[i][2]); - } else { - data[0] = init_ov7660[i][2]; - err = m5602_write_sensor(sd, - init_ov7660[i][1], data, 1); - } - } - - if (dump_sensor) - ov7660_dump_registers(sd); - - err = ov7660_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); - if (err < 0) - return err; - - err = ov7660_set_auto_white_balance(&sd->gspca_dev, - sensor_settings[AUTO_WHITE_BALANCE_IDX]); - if (err < 0) - return err; - - err = ov7660_set_auto_gain(&sd->gspca_dev, - sensor_settings[AUTO_GAIN_CTRL_IDX]); - if (err < 0) - return err; - - err = ov7660_set_auto_exposure(&sd->gspca_dev, - sensor_settings[AUTO_EXPOSURE_IDX]); - if (err < 0) - return err; - err = ov7660_set_hflip(&sd->gspca_dev, - sensor_settings[HFLIP_IDX]); - if (err < 0) - return err; - - err = ov7660_set_vflip(&sd->gspca_dev, - sensor_settings[VFLIP_IDX]); - - return err; -} - -int ov7660_start(struct sd *sd) -{ - return 0; -} - -int ov7660_stop(struct sd *sd) -{ - return 0; -} - -void ov7660_disconnect(struct sd *sd) -{ - ov7660_stop(sd); - - sd->sensor = NULL; - kfree(sd->sensor_priv); -} - -static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[GAIN_IDX]; - PDEBUG(D_V4L2, "Read gain %d", *val); - return 0; -} - -static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Setting gain to %d", val); - - sensor_settings[GAIN_IDX] = val; - - err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1); - return err; -} - - -static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev, - __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[AUTO_WHITE_BALANCE_IDX]; - return 0; -} - -static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev, - __s32 val) -{ - int err; - u8 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Set auto white balance to %d", val); - - sensor_settings[AUTO_WHITE_BALANCE_IDX] = val; - err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1); - if (err < 0) - return err; - - i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1)); - err = m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1); - - return err; -} - -static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[AUTO_GAIN_CTRL_IDX]; - PDEBUG(D_V4L2, "Read auto gain control %d", *val); - return 0; -} - -static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Set auto gain control to %d", val); - - sensor_settings[AUTO_GAIN_CTRL_IDX] = val; - err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1); - if (err < 0) - return err; - - i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2)); - - return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1); -} - -static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[AUTO_EXPOSURE_IDX]; - PDEBUG(D_V4L2, "Read auto exposure control %d", *val); - return 0; -} - -static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, - __s32 val) -{ - int err; - u8 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Set auto exposure control to %d", val); - - sensor_settings[AUTO_EXPOSURE_IDX] = val; - err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1); - if (err < 0) - return err; - - i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0)); - - return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1); -} - -static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[HFLIP_IDX]; - PDEBUG(D_V4L2, "Read horizontal flip %d", *val); - return 0; -} - -static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Set horizontal flip to %d", val); - - sensor_settings[HFLIP_IDX] = val; - - i2c_data = ((val & 0x01) << 5) | - (sensor_settings[VFLIP_IDX] << 4); - - err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1); - - return err; -} - -static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[VFLIP_IDX]; - PDEBUG(D_V4L2, "Read vertical flip %d", *val); - - return 0; -} - -static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Set vertical flip to %d", val); - sensor_settings[VFLIP_IDX] = val; - - i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5); - err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1); - if (err < 0) - return err; - - /* When vflip is toggled we need to readjust the bridge hsync/vsync */ - if (gspca_dev->streaming) - err = ov7660_start(sd); - - return err; -} - -static void ov7660_dump_registers(struct sd *sd) -{ - int address; - pr_info("Dumping the ov7660 register state\n"); - for (address = 0; address < 0xa9; address++) { - u8 value; - m5602_read_sensor(sd, address, &value, 1); - pr_info("register 0x%x contains 0x%x\n", address, value); - } - - pr_info("ov7660 register state dump complete\n"); - - pr_info("Probing for which registers that are read/write\n"); - for (address = 0; address < 0xff; address++) { - u8 old_value, ctrl_value; - u8 test_value[2] = {0xff, 0xff}; - - m5602_read_sensor(sd, address, &old_value, 1); - m5602_write_sensor(sd, address, test_value, 1); - m5602_read_sensor(sd, address, &ctrl_value, 1); - - if (ctrl_value == test_value[0]) - pr_info("register 0x%x is writeable\n", address); - else - pr_info("register 0x%x is read only\n", address); - - /* Restore original value */ - m5602_write_sensor(sd, address, &old_value, 1); - } -} diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.h b/drivers/media/video/gspca/m5602/m5602_ov7660.h deleted file mode 100644 index 2b6a13b508f7..000000000000 --- a/drivers/media/video/gspca/m5602/m5602_ov7660.h +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Driver for the ov7660 sensor - * - * Copyright (C) 2009 Erik Andrén - * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. - * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> - * - * Portions of code to USB interface and ALi driver software, - * Copyright (c) 2006 Willem Duinker - * v4l2 interface modeled after the V4L2 driver - * for SN9C10x PC Camera Controllers - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#ifndef M5602_OV7660_H_ -#define M5602_OV7660_H_ - -#include "m5602_sensor.h" - -#define OV7660_GAIN 0x00 -#define OV7660_BLUE_GAIN 0x01 -#define OV7660_RED_GAIN 0x02 -#define OV7660_VREF 0x03 -#define OV7660_COM1 0x04 -#define OV7660_BAVE 0x05 -#define OV7660_GEAVE 0x06 -#define OV7660_AECHH 0x07 -#define OV7660_RAVE 0x08 -#define OV7660_COM2 0x09 -#define OV7660_PID 0x0a -#define OV7660_VER 0x0b -#define OV7660_COM3 0x0c -#define OV7660_COM4 0x0d -#define OV7660_COM5 0x0e -#define OV7660_COM6 0x0f -#define OV7660_AECH 0x10 -#define OV7660_CLKRC 0x11 -#define OV7660_COM7 0x12 -#define OV7660_COM8 0x13 -#define OV7660_COM9 0x14 -#define OV7660_COM10 0x15 -#define OV7660_RSVD16 0x16 -#define OV7660_HSTART 0x17 -#define OV7660_HSTOP 0x18 -#define OV7660_VSTART 0x19 -#define OV7660_VSTOP 0x1a -#define OV7660_PSHFT 0x1b -#define OV7660_MIDH 0x1c -#define OV7660_MIDL 0x1d -#define OV7660_MVFP 0x1e -#define OV7660_LAEC 0x1f -#define OV7660_BOS 0x20 -#define OV7660_GBOS 0x21 -#define OV7660_GROS 0x22 -#define OV7660_ROS 0x23 -#define OV7660_AEW 0x24 -#define OV7660_AEB 0x25 -#define OV7660_VPT 0x26 -#define OV7660_BBIAS 0x27 -#define OV7660_GbBIAS 0x28 -#define OV7660_RSVD29 0x29 -#define OV7660_RBIAS 0x2c -#define OV7660_HREF 0x32 -#define OV7660_ADC 0x37 -#define OV7660_OFON 0x39 -#define OV7660_TSLB 0x3a -#define OV7660_COM12 0x3c -#define OV7660_COM13 0x3d -#define OV7660_LCC1 0x62 -#define OV7660_LCC2 0x63 -#define OV7660_LCC3 0x64 -#define OV7660_LCC4 0x65 -#define OV7660_LCC5 0x66 -#define OV7660_HV 0x69 -#define OV7660_RSVDA1 0xa1 - -#define OV7660_DEFAULT_GAIN 0x0e -#define OV7660_DEFAULT_RED_GAIN 0x80 -#define OV7660_DEFAULT_BLUE_GAIN 0x80 -#define OV7660_DEFAULT_SATURATION 0x00 -#define OV7660_DEFAULT_EXPOSURE 0x20 - -/* Kernel module parameters */ -extern int force_sensor; -extern bool dump_sensor; - -int ov7660_probe(struct sd *sd); -int ov7660_init(struct sd *sd); -int ov7660_start(struct sd *sd); -int ov7660_stop(struct sd *sd); -void ov7660_disconnect(struct sd *sd); - -static const struct m5602_sensor ov7660 = { - .name = "ov7660", - .i2c_slave_id = 0x42, - .i2c_regW = 1, - .probe = ov7660_probe, - .init = ov7660_init, - .start = ov7660_start, - .stop = ov7660_stop, - .disconnect = ov7660_disconnect, -}; - -static const unsigned char preinit_ov7660[][4] = { - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d}, - {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x03}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x03}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - - {SENSOR, OV7660_OFON, 0x0c}, - {SENSOR, OV7660_COM2, 0x11}, - {SENSOR, OV7660_COM7, 0x05}, - - {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00} -}; - -static const unsigned char init_ov7660[][4] = { - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d}, - {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, - {SENSOR, OV7660_COM7, 0x80}, - {SENSOR, OV7660_CLKRC, 0x80}, - {SENSOR, OV7660_COM9, 0x4c}, - {SENSOR, OV7660_OFON, 0x43}, - {SENSOR, OV7660_COM12, 0x28}, - {SENSOR, OV7660_COM8, 0x00}, - {SENSOR, OV7660_COM10, 0x40}, - {SENSOR, OV7660_HSTART, 0x0c}, - {SENSOR, OV7660_HSTOP, 0x61}, - {SENSOR, OV7660_HREF, 0xa4}, - {SENSOR, OV7660_PSHFT, 0x0b}, - {SENSOR, OV7660_VSTART, 0x01}, - {SENSOR, OV7660_VSTOP, 0x7a}, - {SENSOR, OV7660_VSTOP, 0x00}, - {SENSOR, OV7660_COM7, 0x05}, - {SENSOR, OV7660_COM6, 0x42}, - {SENSOR, OV7660_BBIAS, 0x94}, - {SENSOR, OV7660_GbBIAS, 0x94}, - {SENSOR, OV7660_RSVD29, 0x94}, - {SENSOR, OV7660_RBIAS, 0x94}, - {SENSOR, OV7660_COM1, 0x00}, - {SENSOR, OV7660_AECH, 0x00}, - {SENSOR, OV7660_AECHH, 0x00}, - {SENSOR, OV7660_ADC, 0x05}, - {SENSOR, OV7660_COM13, 0x00}, - {SENSOR, OV7660_RSVDA1, 0x23}, - {SENSOR, OV7660_TSLB, 0x0d}, - {SENSOR, OV7660_HV, 0x80}, - {SENSOR, OV7660_LCC1, 0x00}, - {SENSOR, OV7660_LCC2, 0x00}, - {SENSOR, OV7660_LCC3, 0x10}, - {SENSOR, OV7660_LCC4, 0x40}, - {SENSOR, OV7660_LCC5, 0x01}, - - {SENSOR, OV7660_AECH, 0x20}, - {SENSOR, OV7660_COM1, 0x00}, - {SENSOR, OV7660_OFON, 0x0c}, - {SENSOR, OV7660_COM2, 0x11}, - {SENSOR, OV7660_COM7, 0x05}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, - {SENSOR, OV7660_AECH, 0x5f}, - {SENSOR, OV7660_COM1, 0x03}, - {SENSOR, OV7660_OFON, 0x0c}, - {SENSOR, OV7660_COM2, 0x11}, - {SENSOR, OV7660_COM7, 0x05}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x01}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, - - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, - {BRIDGE, M5602_XB_SIG_INI, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x08}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x27}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0xa7}, - {BRIDGE, M5602_XB_SIG_INI, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, -}; -#endif diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c deleted file mode 100644 index 2114a8b90ec9..000000000000 --- a/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ /dev/null @@ -1,881 +0,0 @@ -/* - * Driver for the ov9650 sensor - * - * Copyright (C) 2008 Erik Andrén - * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. - * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> - * - * Portions of code to USB interface and ALi driver software, - * Copyright (c) 2006 Willem Duinker - * v4l2 interface modeled after the V4L2 driver - * for SN9C10x PC Camera Controllers - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "m5602_ov9650.h" - -static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); -static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); -static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val); -static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val); -static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); -static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); -static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); -static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); -static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); -static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val); -static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); -static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val); -static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, - __s32 *val); -static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, - __s32 val); -static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); -static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); -static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val); -static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val); - -/* Vertically and horizontally flips the image if matched, needed for machines - where the sensor is mounted upside down */ -static - const - struct dmi_system_id ov9650_flip_dmi_table[] = { - { - .ident = "ASUS A6Ja", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "A6J") - } - }, - { - .ident = "ASUS A6JC", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "A6JC") - } - }, - { - .ident = "ASUS A6K", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "A6K") - } - }, - { - .ident = "ASUS A6Kt", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt") - } - }, - { - .ident = "ASUS A6VA", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "A6VA") - } - }, - { - - .ident = "ASUS A6VC", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "A6VC") - } - }, - { - .ident = "ASUS A6VM", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "A6VM") - } - }, - { - .ident = "ASUS A7V", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "A7V") - } - }, - { - .ident = "Alienware Aurora m9700", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "alienware"), - DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700") - } - }, - {} -}; - -static const struct ctrl ov9650_ctrls[] = { -#define EXPOSURE_IDX 0 - { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0x1ff, - .step = 0x4, - .default_value = EXPOSURE_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = ov9650_set_exposure, - .get = ov9650_get_exposure - }, -#define GAIN_IDX 1 - { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "gain", - .minimum = 0x00, - .maximum = 0x3ff, - .step = 0x1, - .default_value = GAIN_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = ov9650_set_gain, - .get = ov9650_get_gain - }, -#define RED_BALANCE_IDX 2 - { - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x1, - .default_value = RED_GAIN_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = ov9650_set_red_balance, - .get = ov9650_get_red_balance - }, -#define BLUE_BALANCE_IDX 3 - { - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x1, - .default_value = BLUE_GAIN_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = ov9650_set_blue_balance, - .get = ov9650_get_blue_balance - }, -#define HFLIP_IDX 4 - { - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "horizontal flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = ov9650_set_hflip, - .get = ov9650_get_hflip - }, -#define VFLIP_IDX 5 - { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = ov9650_set_vflip, - .get = ov9650_get_vflip - }, -#define AUTO_WHITE_BALANCE_IDX 6 - { - { - .id = V4L2_CID_AUTO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto white balance", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1 - }, - .set = ov9650_set_auto_white_balance, - .get = ov9650_get_auto_white_balance - }, -#define AUTO_GAIN_CTRL_IDX 7 - { - { - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto gain control", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1 - }, - .set = ov9650_set_auto_gain, - .get = ov9650_get_auto_gain - }, -#define AUTO_EXPOSURE_IDX 8 - { - { - .id = V4L2_CID_EXPOSURE_AUTO, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto exposure", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1 - }, - .set = ov9650_set_auto_exposure, - .get = ov9650_get_auto_exposure - } - -}; - -static struct v4l2_pix_format ov9650_modes[] = { - { - 176, - 144, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - 176 * 144, - .bytesperline = 176, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 9 - }, { - 320, - 240, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - 320 * 240, - .bytesperline = 320, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 8 - }, { - 352, - 288, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - 352 * 288, - .bytesperline = 352, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 9 - }, { - 640, - 480, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - 640 * 480, - .bytesperline = 640, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 9 - } -}; - -static void ov9650_dump_registers(struct sd *sd); - -int ov9650_probe(struct sd *sd) -{ - int err = 0; - u8 prod_id = 0, ver_id = 0, i; - s32 *sensor_settings; - - if (force_sensor) { - if (force_sensor == OV9650_SENSOR) { - pr_info("Forcing an %s sensor\n", ov9650.name); - goto sensor_found; - } - /* If we want to force another sensor, - don't try to probe this one */ - return -ENODEV; - } - - PDEBUG(D_PROBE, "Probing for an ov9650 sensor"); - - /* Run the pre-init before probing the sensor */ - for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) { - u8 data = preinit_ov9650[i][2]; - if (preinit_ov9650[i][0] == SENSOR) - err = m5602_write_sensor(sd, - preinit_ov9650[i][1], &data, 1); - else - err = m5602_write_bridge(sd, - preinit_ov9650[i][1], data); - } - - if (err < 0) - return err; - - if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1)) - return -ENODEV; - - if (m5602_read_sensor(sd, OV9650_VER, &ver_id, 1)) - return -ENODEV; - - if ((prod_id == 0x96) && (ver_id == 0x52)) { - pr_info("Detected an ov9650 sensor\n"); - goto sensor_found; - } - return -ENODEV; - -sensor_found: - sensor_settings = kmalloc( - ARRAY_SIZE(ov9650_ctrls) * sizeof(s32), GFP_KERNEL); - if (!sensor_settings) - return -ENOMEM; - - sd->gspca_dev.cam.cam_mode = ov9650_modes; - sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes); - sd->desc->ctrls = ov9650_ctrls; - sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls); - - for (i = 0; i < ARRAY_SIZE(ov9650_ctrls); i++) - sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value; - sd->sensor_priv = sensor_settings; - return 0; -} - -int ov9650_init(struct sd *sd) -{ - int i, err = 0; - u8 data; - s32 *sensor_settings = sd->sensor_priv; - - if (dump_sensor) - ov9650_dump_registers(sd); - - for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) { - data = init_ov9650[i][2]; - if (init_ov9650[i][0] == SENSOR) - err = m5602_write_sensor(sd, init_ov9650[i][1], - &data, 1); - else - err = m5602_write_bridge(sd, init_ov9650[i][1], data); - } - - err = ov9650_set_exposure(&sd->gspca_dev, - sensor_settings[EXPOSURE_IDX]); - if (err < 0) - return err; - - err = ov9650_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); - if (err < 0) - return err; - - err = ov9650_set_red_balance(&sd->gspca_dev, - sensor_settings[RED_BALANCE_IDX]); - if (err < 0) - return err; - - err = ov9650_set_blue_balance(&sd->gspca_dev, - sensor_settings[BLUE_BALANCE_IDX]); - if (err < 0) - return err; - - err = ov9650_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); - if (err < 0) - return err; - - err = ov9650_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); - if (err < 0) - return err; - - err = ov9650_set_auto_exposure(&sd->gspca_dev, - sensor_settings[AUTO_EXPOSURE_IDX]); - if (err < 0) - return err; - - err = ov9650_set_auto_white_balance(&sd->gspca_dev, - sensor_settings[AUTO_WHITE_BALANCE_IDX]); - if (err < 0) - return err; - - err = ov9650_set_auto_gain(&sd->gspca_dev, - sensor_settings[AUTO_GAIN_CTRL_IDX]); - return err; -} - -int ov9650_start(struct sd *sd) -{ - u8 data; - int i, err = 0; - struct cam *cam = &sd->gspca_dev.cam; - s32 *sensor_settings = sd->sensor_priv; - - int width = cam->cam_mode[sd->gspca_dev.curr_mode].width; - int height = cam->cam_mode[sd->gspca_dev.curr_mode].height; - int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv; - int hor_offs = OV9650_LEFT_OFFSET; - - if ((!dmi_check_system(ov9650_flip_dmi_table) && - sensor_settings[VFLIP_IDX]) || - (dmi_check_system(ov9650_flip_dmi_table) && - !sensor_settings[VFLIP_IDX])) - ver_offs--; - - if (width <= 320) - hor_offs /= 2; - - /* Synthesize the vsync/hsync setup */ - for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) { - if (res_init_ov9650[i][0] == BRIDGE) - err = m5602_write_bridge(sd, res_init_ov9650[i][1], - res_init_ov9650[i][2]); - else if (res_init_ov9650[i][0] == SENSOR) { - data = res_init_ov9650[i][2]; - err = m5602_write_sensor(sd, - res_init_ov9650[i][1], &data, 1); - } - } - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, - ((ver_offs >> 8) & 0xff)); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff)); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff)); - if (err < 0) - return err; - - for (i = 0; i < 2 && !err; i++) - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, - (hor_offs >> 8) & 0xff); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, - ((width + hor_offs) >> 8) & 0xff); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, - ((width + hor_offs) & 0xff)); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); - if (err < 0) - return err; - - switch (width) { - case 640: - PDEBUG(D_V4L2, "Configuring camera for VGA mode"); - - data = OV9650_VGA_SELECT | OV9650_RGB_SELECT | - OV9650_RAW_RGB_SELECT; - err = m5602_write_sensor(sd, OV9650_COM7, &data, 1); - break; - - case 352: - PDEBUG(D_V4L2, "Configuring camera for CIF mode"); - - data = OV9650_CIF_SELECT | OV9650_RGB_SELECT | - OV9650_RAW_RGB_SELECT; - err = m5602_write_sensor(sd, OV9650_COM7, &data, 1); - break; - - case 320: - PDEBUG(D_V4L2, "Configuring camera for QVGA mode"); - - data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT | - OV9650_RAW_RGB_SELECT; - err = m5602_write_sensor(sd, OV9650_COM7, &data, 1); - break; - - case 176: - PDEBUG(D_V4L2, "Configuring camera for QCIF mode"); - - data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT | - OV9650_RAW_RGB_SELECT; - err = m5602_write_sensor(sd, OV9650_COM7, &data, 1); - break; - } - return err; -} - -int ov9650_stop(struct sd *sd) -{ - u8 data = OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X; - return m5602_write_sensor(sd, OV9650_COM2, &data, 1); -} - -void ov9650_disconnect(struct sd *sd) -{ - ov9650_stop(sd); - - sd->sensor = NULL; - kfree(sd->sensor_priv); -} - -static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[EXPOSURE_IDX]; - PDEBUG(D_V4L2, "Read exposure %d", *val); - return 0; -} - -static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - u8 i2c_data; - int err; - - PDEBUG(D_V4L2, "Set exposure to %d", val); - - sensor_settings[EXPOSURE_IDX] = val; - /* The 6 MSBs */ - i2c_data = (val >> 10) & 0x3f; - err = m5602_write_sensor(sd, OV9650_AECHM, - &i2c_data, 1); - if (err < 0) - return err; - - /* The 8 middle bits */ - i2c_data = (val >> 2) & 0xff; - err = m5602_write_sensor(sd, OV9650_AECH, - &i2c_data, 1); - if (err < 0) - return err; - - /* The 2 LSBs */ - i2c_data = val & 0x03; - err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1); - return err; -} - -static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[GAIN_IDX]; - PDEBUG(D_V4L2, "Read gain %d", *val); - return 0; -} - -static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Setting gain to %d", val); - - sensor_settings[GAIN_IDX] = val; - - /* The 2 MSB */ - /* Read the OV9650_VREF register first to avoid - corrupting the VREF high and low bits */ - err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); - if (err < 0) - return err; - - /* Mask away all uninteresting bits */ - i2c_data = ((val & 0x0300) >> 2) | - (i2c_data & 0x3f); - err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1); - if (err < 0) - return err; - - /* The 8 LSBs */ - i2c_data = val & 0xff; - err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); - return err; -} - -static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[RED_BALANCE_IDX]; - PDEBUG(D_V4L2, "Read red gain %d", *val); - return 0; -} - -static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Set red gain to %d", val); - - sensor_settings[RED_BALANCE_IDX] = val; - - i2c_data = val & 0xff; - err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1); - return err; -} - -static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[BLUE_BALANCE_IDX]; - PDEBUG(D_V4L2, "Read blue gain %d", *val); - - return 0; -} - -static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Set blue gain to %d", val); - - sensor_settings[BLUE_BALANCE_IDX] = val; - - i2c_data = val & 0xff; - err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1); - return err; -} - -static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[HFLIP_IDX]; - PDEBUG(D_V4L2, "Read horizontal flip %d", *val); - return 0; -} - -static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Set horizontal flip to %d", val); - - sensor_settings[HFLIP_IDX] = val; - - if (!dmi_check_system(ov9650_flip_dmi_table)) - i2c_data = ((val & 0x01) << 5) | - (sensor_settings[VFLIP_IDX] << 4); - else - i2c_data = ((val & 0x01) << 5) | - (!sensor_settings[VFLIP_IDX] << 4); - - err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); - - return err; -} - -static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[VFLIP_IDX]; - PDEBUG(D_V4L2, "Read vertical flip %d", *val); - - return 0; -} - -static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Set vertical flip to %d", val); - sensor_settings[VFLIP_IDX] = val; - - if (dmi_check_system(ov9650_flip_dmi_table)) - val = !val; - - i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5); - err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); - if (err < 0) - return err; - - /* When vflip is toggled we need to readjust the bridge hsync/vsync */ - if (gspca_dev->streaming) - err = ov9650_start(sd); - - return err; -} - -static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[AUTO_EXPOSURE_IDX]; - PDEBUG(D_V4L2, "Read auto exposure control %d", *val); - return 0; -} - -static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev, - __s32 val) -{ - int err; - u8 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Set auto exposure control to %d", val); - - sensor_settings[AUTO_EXPOSURE_IDX] = val; - err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); - if (err < 0) - return err; - - i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0)); - - return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1); -} - -static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, - __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[AUTO_WHITE_BALANCE_IDX]; - return 0; -} - -static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, - __s32 val) -{ - int err; - u8 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Set auto white balance to %d", val); - - sensor_settings[AUTO_WHITE_BALANCE_IDX] = val; - err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); - if (err < 0) - return err; - - i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1)); - err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1); - - return err; -} - -static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[AUTO_GAIN_CTRL_IDX]; - PDEBUG(D_V4L2, "Read auto gain control %d", *val); - return 0; -} - -static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - PDEBUG(D_V4L2, "Set auto gain control to %d", val); - - sensor_settings[AUTO_GAIN_CTRL_IDX] = val; - err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); - if (err < 0) - return err; - - i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2)); - - return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1); -} - -static void ov9650_dump_registers(struct sd *sd) -{ - int address; - pr_info("Dumping the ov9650 register state\n"); - for (address = 0; address < 0xa9; address++) { - u8 value; - m5602_read_sensor(sd, address, &value, 1); - pr_info("register 0x%x contains 0x%x\n", address, value); - } - - pr_info("ov9650 register state dump complete\n"); - - pr_info("Probing for which registers that are read/write\n"); - for (address = 0; address < 0xff; address++) { - u8 old_value, ctrl_value; - u8 test_value[2] = {0xff, 0xff}; - - m5602_read_sensor(sd, address, &old_value, 1); - m5602_write_sensor(sd, address, test_value, 1); - m5602_read_sensor(sd, address, &ctrl_value, 1); - - if (ctrl_value == test_value[0]) - pr_info("register 0x%x is writeable\n", address); - else - pr_info("register 0x%x is read only\n", address); - - /* Restore original value */ - m5602_write_sensor(sd, address, &old_value, 1); - } -} diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.h b/drivers/media/video/gspca/m5602/m5602_ov9650.h deleted file mode 100644 index f7aa5bf68983..000000000000 --- a/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Driver for the ov9650 sensor - * - * Copyright (C) 2008 Erik Andrén - * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. - * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> - * - * Portions of code to USB interface and ALi driver software, - * Copyright (c) 2006 Willem Duinker - * v4l2 interface modeled after the V4L2 driver - * for SN9C10x PC Camera Controllers - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#ifndef M5602_OV9650_H_ -#define M5602_OV9650_H_ - -#include <linux/dmi.h> -#include "m5602_sensor.h" - -/*****************************************************************************/ - -#define OV9650_GAIN 0x00 -#define OV9650_BLUE 0x01 -#define OV9650_RED 0x02 -#define OV9650_VREF 0x03 -#define OV9650_COM1 0x04 -#define OV9650_BAVE 0x05 -#define OV9650_GEAVE 0x06 -#define OV9650_RSVD7 0x07 -#define OV9650_COM2 0x09 -#define OV9650_PID 0x0a -#define OV9650_VER 0x0b -#define OV9650_COM3 0x0c -#define OV9650_COM4 0x0d -#define OV9650_COM5 0x0e -#define OV9650_COM6 0x0f -#define OV9650_AECH 0x10 -#define OV9650_CLKRC 0x11 -#define OV9650_COM7 0x12 -#define OV9650_COM8 0x13 -#define OV9650_COM9 0x14 -#define OV9650_COM10 0x15 -#define OV9650_RSVD16 0x16 -#define OV9650_HSTART 0x17 -#define OV9650_HSTOP 0x18 -#define OV9650_VSTRT 0x19 -#define OV9650_VSTOP 0x1a -#define OV9650_PSHFT 0x1b -#define OV9650_MVFP 0x1e -#define OV9650_AEW 0x24 -#define OV9650_AEB 0x25 -#define OV9650_VPT 0x26 -#define OV9650_BBIAS 0x27 -#define OV9650_GbBIAS 0x28 -#define OV9650_Gr_COM 0x29 -#define OV9650_RBIAS 0x2c -#define OV9650_HREF 0x32 -#define OV9650_CHLF 0x33 -#define OV9650_ARBLM 0x34 -#define OV9650_RSVD35 0x35 -#define OV9650_RSVD36 0x36 -#define OV9650_ADC 0x37 -#define OV9650_ACOM38 0x38 -#define OV9650_OFON 0x39 -#define OV9650_TSLB 0x3a -#define OV9650_COM12 0x3c -#define OV9650_COM13 0x3d -#define OV9650_COM15 0x40 -#define OV9650_COM16 0x41 -#define OV9650_LCC1 0x62 -#define OV9650_LCC2 0x63 -#define OV9650_LCC3 0x64 -#define OV9650_LCC4 0x65 -#define OV9650_LCC5 0x66 -#define OV9650_HV 0x69 -#define OV9650_DBLV 0x6b -#define OV9650_COM21 0x8b -#define OV9650_COM22 0x8c -#define OV9650_COM24 0x8e -#define OV9650_DBLC1 0x8f -#define OV9650_RSVD94 0x94 -#define OV9650_RSVD95 0x95 -#define OV9650_RSVD96 0x96 -#define OV9650_LCCFB 0x9d -#define OV9650_LCCFR 0x9e -#define OV9650_AECHM 0xa1 -#define OV9650_COM26 0xa5 -#define OV9650_ACOMA8 0xa8 -#define OV9650_ACOMA9 0xa9 - -#define OV9650_REGISTER_RESET (1 << 7) -#define OV9650_VGA_SELECT (1 << 6) -#define OV9650_CIF_SELECT (1 << 5) -#define OV9650_QVGA_SELECT (1 << 4) -#define OV9650_QCIF_SELECT (1 << 3) -#define OV9650_RGB_SELECT (1 << 2) -#define OV9650_RAW_RGB_SELECT (1 << 0) - -#define OV9650_FAST_AGC_AEC (1 << 7) -#define OV9650_AEC_UNLIM_STEP_SIZE (1 << 6) -#define OV9650_BANDING (1 << 5) -#define OV9650_AGC_EN (1 << 2) -#define OV9650_AWB_EN (1 << 1) -#define OV9650_AEC_EN (1 << 0) - -#define OV9650_VARIOPIXEL (1 << 2) -#define OV9650_SYSTEM_CLK_SEL (1 << 7) -#define OV9650_SLAM_MODE (1 << 4) - -#define OV9650_QVGA_VARIOPIXEL (1 << 7) - -#define OV9650_VFLIP (1 << 4) -#define OV9650_HFLIP (1 << 5) - -#define OV9650_SOFT_SLEEP (1 << 4) -#define OV9650_OUTPUT_DRIVE_2X (1 << 0) - -#define OV9650_DENOISE_ENABLE (1 << 5) -#define OV9650_WHITE_PIXEL_ENABLE (1 << 1) -#define OV9650_WHITE_PIXEL_OPTION (1 << 0) - -#define OV9650_LEFT_OFFSET 0x62 - -#define GAIN_DEFAULT 0x14 -#define RED_GAIN_DEFAULT 0x70 -#define BLUE_GAIN_DEFAULT 0x20 -#define EXPOSURE_DEFAULT 0x1ff - -/*****************************************************************************/ - -/* Kernel module parameters */ -extern int force_sensor; -extern bool dump_sensor; - -int ov9650_probe(struct sd *sd); -int ov9650_init(struct sd *sd); -int ov9650_start(struct sd *sd); -int ov9650_stop(struct sd *sd); -void ov9650_disconnect(struct sd *sd); - -static const struct m5602_sensor ov9650 = { - .name = "OV9650", - .i2c_slave_id = 0x60, - .i2c_regW = 1, - .probe = ov9650_probe, - .init = ov9650_init, - .start = ov9650_start, - .stop = ov9650_stop, - .disconnect = ov9650_disconnect, -}; - -static const unsigned char preinit_ov9650[][3] = { - /* [INITCAM] */ - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, - - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, - {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a}, - /* Reset chip */ - {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET}, - /* Enable double clock */ - {SENSOR, OV9650_CLKRC, 0x80}, - /* Do something out of spec with the power */ - {SENSOR, OV9650_OFON, 0x40} -}; - -static const unsigned char init_ov9650[][3] = { - /* [INITCAM] */ - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, - - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, - {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a}, - - /* Reset chip */ - {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET}, - /* One extra reset is needed in order to make the sensor behave - properly when resuming from ram, could be a timing issue */ - {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET}, - - /* Enable double clock */ - {SENSOR, OV9650_CLKRC, 0x80}, - /* Do something out of spec with the power */ - {SENSOR, OV9650_OFON, 0x40}, - - /* Set fast AGC/AEC algorithm with unlimited step size */ - {SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC | - OV9650_AEC_UNLIM_STEP_SIZE}, - - {SENSOR, OV9650_CHLF, 0x10}, - {SENSOR, OV9650_ARBLM, 0xbf}, - {SENSOR, OV9650_ACOM38, 0x81}, - /* Turn off color matrix coefficient double option */ - {SENSOR, OV9650_COM16, 0x00}, - /* Enable color matrix for RGB/YUV, Delay Y channel, - set output Y/UV delay to 1 */ - {SENSOR, OV9650_COM13, 0x19}, - /* Enable digital BLC, Set output mode to U Y V Y */ - {SENSOR, OV9650_TSLB, 0x0c}, - /* Limit the AGC/AEC stable upper region */ - {SENSOR, OV9650_COM24, 0x00}, - /* Enable HREF and some out of spec things */ - {SENSOR, OV9650_COM12, 0x73}, - /* Set all DBLC offset signs to positive and - do some out of spec stuff */ - {SENSOR, OV9650_DBLC1, 0xdf}, - {SENSOR, OV9650_COM21, 0x06}, - {SENSOR, OV9650_RSVD35, 0x91}, - /* Necessary, no camera stream without it */ - {SENSOR, OV9650_RSVD16, 0x06}, - {SENSOR, OV9650_RSVD94, 0x99}, - {SENSOR, OV9650_RSVD95, 0x99}, - {SENSOR, OV9650_RSVD96, 0x04}, - /* Enable full range output */ - {SENSOR, OV9650_COM15, 0x0}, - /* Enable HREF at optical black, enable ADBLC bias, - enable ADBLC, reset timings at format change */ - {SENSOR, OV9650_COM6, 0x4b}, - /* Subtract 32 from the B channel bias */ - {SENSOR, OV9650_BBIAS, 0xa0}, - /* Subtract 32 from the Gb channel bias */ - {SENSOR, OV9650_GbBIAS, 0xa0}, - /* Do not bypass the analog BLC and to some out of spec stuff */ - {SENSOR, OV9650_Gr_COM, 0x00}, - /* Subtract 32 from the R channel bias */ - {SENSOR, OV9650_RBIAS, 0xa0}, - /* Subtract 32 from the R channel bias */ - {SENSOR, OV9650_RBIAS, 0x0}, - {SENSOR, OV9650_COM26, 0x80}, - {SENSOR, OV9650_ACOMA9, 0x98}, - /* Set the AGC/AEC stable region upper limit */ - {SENSOR, OV9650_AEW, 0x68}, - /* Set the AGC/AEC stable region lower limit */ - {SENSOR, OV9650_AEB, 0x5c}, - /* Set the high and low limit nibbles to 3 */ - {SENSOR, OV9650_VPT, 0xc3}, - /* Set the Automatic Gain Ceiling (AGC) to 128x, - drop VSYNC at frame drop, - limit exposure timing, - drop frame when the AEC step is larger than the exposure gap */ - {SENSOR, OV9650_COM9, 0x6e}, - /* Set VSYNC negative, Set RESET to SLHS (slave mode horizontal sync) - and set PWDN to SLVS (slave mode vertical sync) */ - {SENSOR, OV9650_COM10, 0x42}, - /* Set horizontal column start high to default value */ - {SENSOR, OV9650_HSTART, 0x1a}, /* 210 */ - /* Set horizontal column end */ - {SENSOR, OV9650_HSTOP, 0xbf}, /* 1534 */ - /* Complementing register to the two writes above */ - {SENSOR, OV9650_HREF, 0xb2}, - /* Set vertical row start high bits */ - {SENSOR, OV9650_VSTRT, 0x02}, - /* Set vertical row end low bits */ - {SENSOR, OV9650_VSTOP, 0x7e}, - /* Set complementing vertical frame control */ - {SENSOR, OV9650_VREF, 0x10}, - {SENSOR, OV9650_ADC, 0x04}, - {SENSOR, OV9650_HV, 0x40}, - - /* Enable denoise, and white-pixel erase */ - {SENSOR, OV9650_COM22, OV9650_DENOISE_ENABLE | - OV9650_WHITE_PIXEL_ENABLE | - OV9650_WHITE_PIXEL_OPTION}, - - /* Enable VARIOPIXEL */ - {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL}, - {SENSOR, OV9650_COM4, OV9650_QVGA_VARIOPIXEL}, - - /* Put the sensor in soft sleep mode */ - {SENSOR, OV9650_COM2, OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X}, -}; - -static const unsigned char res_init_ov9650[][3] = { - {SENSOR, OV9650_COM2, OV9650_OUTPUT_DRIVE_2X}, - - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, - {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01} -}; -#endif diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c deleted file mode 100644 index b8771698cbcb..000000000000 --- a/drivers/media/video/gspca/m5602/m5602_po1030.c +++ /dev/null @@ -1,763 +0,0 @@ -/* - * Driver for the po1030 sensor - * - * Copyright (c) 2008 Erik Andrén - * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. - * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> - * - * Portions of code to USB interface and ALi driver software, - * Copyright (c) 2006 Willem Duinker - * v4l2 interface modeled after the V4L2 driver - * for SN9C10x PC Camera Controllers - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "m5602_po1030.h" - -static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); -static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val); -static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val); -static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val); -static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); -static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); -static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); -static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); -static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val); -static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val); -static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); -static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val); -static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); -static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val); -static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev, - __s32 val); -static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev, - __s32 *val); -static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev, - __s32 val); -static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev, - __s32 *val); - -static struct v4l2_pix_format po1030_modes[] = { - { - 640, - 480, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = 640 * 480, - .bytesperline = 640, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2 - } -}; - -static const struct ctrl po1030_ctrls[] = { -#define GAIN_IDX 0 - { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "gain", - .minimum = 0x00, - .maximum = 0x4f, - .step = 0x1, - .default_value = PO1030_GLOBAL_GAIN_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = po1030_set_gain, - .get = po1030_get_gain - }, -#define EXPOSURE_IDX 1 - { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0x02ff, - .step = 0x1, - .default_value = PO1030_EXPOSURE_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = po1030_set_exposure, - .get = po1030_get_exposure - }, -#define RED_BALANCE_IDX 2 - { - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x1, - .default_value = PO1030_RED_GAIN_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = po1030_set_red_balance, - .get = po1030_get_red_balance - }, -#define BLUE_BALANCE_IDX 3 - { - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x1, - .default_value = PO1030_BLUE_GAIN_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = po1030_set_blue_balance, - .get = po1030_get_blue_balance - }, -#define HFLIP_IDX 4 - { - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "horizontal flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - .set = po1030_set_hflip, - .get = po1030_get_hflip - }, -#define VFLIP_IDX 5 - { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - .set = po1030_set_vflip, - .get = po1030_get_vflip - }, -#define AUTO_WHITE_BALANCE_IDX 6 - { - { - .id = V4L2_CID_AUTO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto white balance", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - .set = po1030_set_auto_white_balance, - .get = po1030_get_auto_white_balance - }, -#define AUTO_EXPOSURE_IDX 7 - { - { - .id = V4L2_CID_EXPOSURE_AUTO, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto exposure", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - .set = po1030_set_auto_exposure, - .get = po1030_get_auto_exposure - }, -#define GREEN_BALANCE_IDX 8 - { - { - .id = M5602_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x1, - .default_value = PO1030_GREEN_GAIN_DEFAULT, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = po1030_set_green_balance, - .get = po1030_get_green_balance - }, -}; - -static void po1030_dump_registers(struct sd *sd); - -int po1030_probe(struct sd *sd) -{ - u8 dev_id_h = 0, i; - s32 *sensor_settings; - - if (force_sensor) { - if (force_sensor == PO1030_SENSOR) { - pr_info("Forcing a %s sensor\n", po1030.name); - goto sensor_found; - } - /* If we want to force another sensor, don't try to probe this - * one */ - return -ENODEV; - } - - PDEBUG(D_PROBE, "Probing for a po1030 sensor"); - - /* Run the pre-init to actually probe the unit */ - for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) { - u8 data = preinit_po1030[i][2]; - if (preinit_po1030[i][0] == SENSOR) - m5602_write_sensor(sd, - preinit_po1030[i][1], &data, 1); - else - m5602_write_bridge(sd, preinit_po1030[i][1], data); - } - - if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1)) - return -ENODEV; - - if (dev_id_h == 0x30) { - pr_info("Detected a po1030 sensor\n"); - goto sensor_found; - } - return -ENODEV; - -sensor_found: - sensor_settings = kmalloc( - ARRAY_SIZE(po1030_ctrls) * sizeof(s32), GFP_KERNEL); - if (!sensor_settings) - return -ENOMEM; - - sd->gspca_dev.cam.cam_mode = po1030_modes; - sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes); - sd->desc->ctrls = po1030_ctrls; - sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls); - - for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++) - sensor_settings[i] = po1030_ctrls[i].qctrl.default_value; - sd->sensor_priv = sensor_settings; - - return 0; -} - -int po1030_init(struct sd *sd) -{ - s32 *sensor_settings = sd->sensor_priv; - int i, err = 0; - - /* Init the sensor */ - for (i = 0; i < ARRAY_SIZE(init_po1030) && !err; i++) { - u8 data[2] = {0x00, 0x00}; - - switch (init_po1030[i][0]) { - case BRIDGE: - err = m5602_write_bridge(sd, - init_po1030[i][1], - init_po1030[i][2]); - break; - - case SENSOR: - data[0] = init_po1030[i][2]; - err = m5602_write_sensor(sd, - init_po1030[i][1], data, 1); - break; - - default: - pr_info("Invalid stream command, exiting init\n"); - return -EINVAL; - } - } - if (err < 0) - return err; - - if (dump_sensor) - po1030_dump_registers(sd); - - err = po1030_set_exposure(&sd->gspca_dev, - sensor_settings[EXPOSURE_IDX]); - if (err < 0) - return err; - - err = po1030_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); - if (err < 0) - return err; - - err = po1030_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); - if (err < 0) - return err; - - err = po1030_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); - if (err < 0) - return err; - - err = po1030_set_red_balance(&sd->gspca_dev, - sensor_settings[RED_BALANCE_IDX]); - if (err < 0) - return err; - - err = po1030_set_blue_balance(&sd->gspca_dev, - sensor_settings[BLUE_BALANCE_IDX]); - if (err < 0) - return err; - - err = po1030_set_green_balance(&sd->gspca_dev, - sensor_settings[GREEN_BALANCE_IDX]); - if (err < 0) - return err; - - err = po1030_set_auto_white_balance(&sd->gspca_dev, - sensor_settings[AUTO_WHITE_BALANCE_IDX]); - if (err < 0) - return err; - - err = po1030_set_auto_exposure(&sd->gspca_dev, - sensor_settings[AUTO_EXPOSURE_IDX]); - return err; -} - -int po1030_start(struct sd *sd) -{ - struct cam *cam = &sd->gspca_dev.cam; - int i, err = 0; - int width = cam->cam_mode[sd->gspca_dev.curr_mode].width; - int height = cam->cam_mode[sd->gspca_dev.curr_mode].height; - int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv; - u8 data; - - switch (width) { - case 320: - data = PO1030_SUBSAMPLING; - err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1); - if (err < 0) - return err; - - data = ((width + 3) >> 8) & 0xff; - err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1); - if (err < 0) - return err; - - data = (width + 3) & 0xff; - err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1); - if (err < 0) - return err; - - data = ((height + 1) >> 8) & 0xff; - err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1); - if (err < 0) - return err; - - data = (height + 1) & 0xff; - err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1); - - height += 6; - width -= 1; - break; - - case 640: - data = 0; - err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1); - if (err < 0) - return err; - - data = ((width + 7) >> 8) & 0xff; - err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1); - if (err < 0) - return err; - - data = (width + 7) & 0xff; - err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1); - if (err < 0) - return err; - - data = ((height + 3) >> 8) & 0xff; - err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1); - if (err < 0) - return err; - - data = (height + 3) & 0xff; - err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1); - - height += 12; - width -= 2; - break; - } - err = m5602_write_bridge(sd, M5602_XB_SENSOR_TYPE, 0x0c); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_LINE_OF_FRAME_H, 0x81); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_PIX_OF_LINE_H, 0x82); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0x01); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, - ((ver_offs >> 8) & 0xff)); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff)); - if (err < 0) - return err; - - for (i = 0; i < 2 && !err; i++) - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff)); - if (err < 0) - return err; - - for (i = 0; i < 2 && !err; i++) - err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); - - for (i = 0; i < 2 && !err; i++) - err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); - - for (i = 0; i < 2 && !err; i++) - err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width >> 8) & 0xff); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width & 0xff)); - if (err < 0) - return err; - - err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0); - return err; -} - -static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[EXPOSURE_IDX]; - PDEBUG(D_V4L2, "Exposure read as %d", *val); - return 0; -} - -static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - u8 i2c_data; - int err; - - sensor_settings[EXPOSURE_IDX] = val; - PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff); - - i2c_data = ((val & 0xff00) >> 8); - PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x", - i2c_data); - - err = m5602_write_sensor(sd, PO1030_INTEGLINES_H, - &i2c_data, 1); - if (err < 0) - return err; - - i2c_data = (val & 0xff); - PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x", - i2c_data); - err = m5602_write_sensor(sd, PO1030_INTEGLINES_M, - &i2c_data, 1); - - return err; -} - -static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[GAIN_IDX]; - PDEBUG(D_V4L2, "Read global gain %d", *val); - return 0; -} - -static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - u8 i2c_data; - int err; - - sensor_settings[GAIN_IDX] = val; - - i2c_data = val & 0xff; - PDEBUG(D_V4L2, "Set global gain to %d", i2c_data); - err = m5602_write_sensor(sd, PO1030_GLOBALGAIN, - &i2c_data, 1); - return err; -} - -static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[HFLIP_IDX]; - PDEBUG(D_V4L2, "Read hflip %d", *val); - - return 0; -} - -static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - u8 i2c_data; - int err; - - sensor_settings[HFLIP_IDX] = val; - - PDEBUG(D_V4L2, "Set hflip %d", val); - err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1); - if (err < 0) - return err; - - i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7); - - err = m5602_write_sensor(sd, PO1030_CONTROL2, - &i2c_data, 1); - - return err; -} - -static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[VFLIP_IDX]; - PDEBUG(D_V4L2, "Read vflip %d", *val); - - return 0; -} - -static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - u8 i2c_data; - int err; - - sensor_settings[VFLIP_IDX] = val; - - PDEBUG(D_V4L2, "Set vflip %d", val); - err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1); - if (err < 0) - return err; - - i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6); - - err = m5602_write_sensor(sd, PO1030_CONTROL2, - &i2c_data, 1); - - return err; -} - -static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[RED_BALANCE_IDX]; - PDEBUG(D_V4L2, "Read red gain %d", *val); - return 0; -} - -static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - u8 i2c_data; - int err; - - sensor_settings[RED_BALANCE_IDX] = val; - - i2c_data = val & 0xff; - PDEBUG(D_V4L2, "Set red gain to %d", i2c_data); - err = m5602_write_sensor(sd, PO1030_RED_GAIN, - &i2c_data, 1); - return err; -} - -static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[BLUE_BALANCE_IDX]; - PDEBUG(D_V4L2, "Read blue gain %d", *val); - - return 0; -} - -static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - u8 i2c_data; - int err; - - sensor_settings[BLUE_BALANCE_IDX] = val; - - i2c_data = val & 0xff; - PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data); - err = m5602_write_sensor(sd, PO1030_BLUE_GAIN, - &i2c_data, 1); - - return err; -} - -static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[GREEN_BALANCE_IDX]; - PDEBUG(D_V4L2, "Read green gain %d", *val); - - return 0; -} - -static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - u8 i2c_data; - int err; - - sensor_settings[GREEN_BALANCE_IDX] = val; - i2c_data = val & 0xff; - PDEBUG(D_V4L2, "Set green gain to %d", i2c_data); - - err = m5602_write_sensor(sd, PO1030_GREEN_1_GAIN, - &i2c_data, 1); - if (err < 0) - return err; - - return m5602_write_sensor(sd, PO1030_GREEN_2_GAIN, - &i2c_data, 1); -} - -static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev, - __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[AUTO_WHITE_BALANCE_IDX]; - PDEBUG(D_V4L2, "Auto white balancing is %d", *val); - - return 0; -} - -static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev, - __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - u8 i2c_data; - int err; - - sensor_settings[AUTO_WHITE_BALANCE_IDX] = val; - - err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1); - if (err < 0) - return err; - - PDEBUG(D_V4L2, "Set auto white balance to %d", val); - i2c_data = (i2c_data & 0xfe) | (val & 0x01); - err = m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1); - return err; -} - -static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev, - __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[AUTO_EXPOSURE_IDX]; - PDEBUG(D_V4L2, "Auto exposure is %d", *val); - return 0; -} - -static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev, - __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - u8 i2c_data; - int err; - - sensor_settings[AUTO_EXPOSURE_IDX] = val; - err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1); - if (err < 0) - return err; - - PDEBUG(D_V4L2, "Set auto exposure to %d", val); - i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1); - return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1); -} - -void po1030_disconnect(struct sd *sd) -{ - sd->sensor = NULL; - kfree(sd->sensor_priv); -} - -static void po1030_dump_registers(struct sd *sd) -{ - int address; - u8 value = 0; - - pr_info("Dumping the po1030 sensor core registers\n"); - for (address = 0; address < 0x7f; address++) { - m5602_read_sensor(sd, address, &value, 1); - pr_info("register 0x%x contains 0x%x\n", address, value); - } - - pr_info("po1030 register state dump complete\n"); - - pr_info("Probing for which registers that are read/write\n"); - for (address = 0; address < 0xff; address++) { - u8 old_value, ctrl_value; - u8 test_value[2] = {0xff, 0xff}; - - m5602_read_sensor(sd, address, &old_value, 1); - m5602_write_sensor(sd, address, test_value, 1); - m5602_read_sensor(sd, address, &ctrl_value, 1); - - if (ctrl_value == test_value[0]) - pr_info("register 0x%x is writeable\n", address); - else - pr_info("register 0x%x is read only\n", address); - - /* Restore original value */ - m5602_write_sensor(sd, address, &old_value, 1); - } -} diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.h b/drivers/media/video/gspca/m5602/m5602_po1030.h deleted file mode 100644 index 81a2bcb88fe3..000000000000 --- a/drivers/media/video/gspca/m5602/m5602_po1030.h +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Driver for the po1030 sensor. - * - * Copyright (c) 2008 Erik Andrén - * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. - * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> - * - * Portions of code to USB interface and ALi driver software, - * Copyright (c) 2006 Willem Duinker - * v4l2 interface modeled after the V4L2 driver - * for SN9C10x PC Camera Controllers - * - * Register defines taken from Pascal Stangs Procyon Armlib - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#ifndef M5602_PO1030_H_ -#define M5602_PO1030_H_ - -#include "m5602_sensor.h" - -/*****************************************************************************/ - -#define PO1030_DEVID_H 0x00 -#define PO1030_DEVID_L 0x01 -#define PO1030_FRAMEWIDTH_H 0x04 -#define PO1030_FRAMEWIDTH_L 0x05 -#define PO1030_FRAMEHEIGHT_H 0x06 -#define PO1030_FRAMEHEIGHT_L 0x07 -#define PO1030_WINDOWX_H 0x08 -#define PO1030_WINDOWX_L 0x09 -#define PO1030_WINDOWY_H 0x0a -#define PO1030_WINDOWY_L 0x0b -#define PO1030_WINDOWWIDTH_H 0x0c -#define PO1030_WINDOWWIDTH_L 0x0d -#define PO1030_WINDOWHEIGHT_H 0x0e -#define PO1030_WINDOWHEIGHT_L 0x0f - -#define PO1030_GLOBALIBIAS 0x12 -#define PO1030_PIXELIBIAS 0x13 - -#define PO1030_GLOBALGAIN 0x15 -#define PO1030_RED_GAIN 0x16 -#define PO1030_GREEN_1_GAIN 0x17 -#define PO1030_BLUE_GAIN 0x18 -#define PO1030_GREEN_2_GAIN 0x19 - -#define PO1030_INTEGLINES_H 0x1a -#define PO1030_INTEGLINES_M 0x1b -#define PO1030_INTEGLINES_L 0x1c - -#define PO1030_CONTROL1 0x1d -#define PO1030_CONTROL2 0x1e -#define PO1030_CONTROL3 0x1f -#define PO1030_CONTROL4 0x20 - -#define PO1030_PERIOD50_H 0x23 -#define PO1030_PERIOD50_L 0x24 -#define PO1030_PERIOD60_H 0x25 -#define PO1030_PERIOD60_L 0x26 -#define PO1030_REGCLK167 0x27 -#define PO1030_FLICKER_DELTA50 0x28 -#define PO1030_FLICKERDELTA60 0x29 - -#define PO1030_ADCOFFSET 0x2c - -/* Gamma Correction Coeffs */ -#define PO1030_GC0 0x2d -#define PO1030_GC1 0x2e -#define PO1030_GC2 0x2f -#define PO1030_GC3 0x30 -#define PO1030_GC4 0x31 -#define PO1030_GC5 0x32 -#define PO1030_GC6 0x33 -#define PO1030_GC7 0x34 - -/* Color Transform Matrix */ -#define PO1030_CT0 0x35 -#define PO1030_CT1 0x36 -#define PO1030_CT2 0x37 -#define PO1030_CT3 0x38 -#define PO1030_CT4 0x39 -#define PO1030_CT5 0x3a -#define PO1030_CT6 0x3b -#define PO1030_CT7 0x3c -#define PO1030_CT8 0x3d - -#define PO1030_AUTOCTRL1 0x3e -#define PO1030_AUTOCTRL2 0x3f - -#define PO1030_YTARGET 0x40 -#define PO1030_GLOBALGAINMIN 0x41 -#define PO1030_GLOBALGAINMAX 0x42 - -#define PO1030_AWB_RED_TUNING 0x47 -#define PO1030_AWB_BLUE_TUNING 0x48 - -/* Output format control */ -#define PO1030_OUTFORMCTRL1 0x5a -#define PO1030_OUTFORMCTRL2 0x5b -#define PO1030_OUTFORMCTRL3 0x5c -#define PO1030_OUTFORMCTRL4 0x5d -#define PO1030_OUTFORMCTRL5 0x5e - -#define PO1030_EDGE_ENH_OFF 0x5f -#define PO1030_EGA 0x60 - -#define PO1030_Cb_U_GAIN 0x63 -#define PO1030_Cr_V_GAIN 0x64 - -#define PO1030_YCONTRAST 0x74 -#define PO1030_YSATURATION 0x75 - -#define PO1030_HFLIP (1 << 7) -#define PO1030_VFLIP (1 << 6) - -#define PO1030_HREF_ENABLE (1 << 6) - -#define PO1030_RAW_RGB_BAYER 0x4 - -#define PO1030_FRAME_EQUAL (1 << 3) -#define PO1030_AUTO_SUBSAMPLING (1 << 4) - -#define PO1030_WEIGHT_WIN_2X (1 << 3) - -#define PO1030_SHUTTER_MODE (1 << 6) -#define PO1030_AUTO_SUBSAMPLING (1 << 4) -#define PO1030_FRAME_EQUAL (1 << 3) - -#define PO1030_SENSOR_RESET (1 << 5) - -#define PO1030_SUBSAMPLING (1 << 6) - -/*****************************************************************************/ - -#define PO1030_GLOBAL_GAIN_DEFAULT 0x12 -#define PO1030_EXPOSURE_DEFAULT 0x0085 -#define PO1030_BLUE_GAIN_DEFAULT 0x36 -#define PO1030_RED_GAIN_DEFAULT 0x36 -#define PO1030_GREEN_GAIN_DEFAULT 0x40 - -/*****************************************************************************/ - -/* Kernel module parameters */ -extern int force_sensor; -extern bool dump_sensor; - -int po1030_probe(struct sd *sd); -int po1030_init(struct sd *sd); -int po1030_start(struct sd *sd); -void po1030_disconnect(struct sd *sd); - -static const struct m5602_sensor po1030 = { - .name = "PO1030", - - .i2c_slave_id = 0xdc, - .i2c_regW = 1, - - .probe = po1030_probe, - .init = po1030_init, - .start = po1030_start, - .disconnect = po1030_disconnect, -}; - -static const unsigned char preinit_po1030[][3] = { - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, - - {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)}, - - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x00} -}; - -static const unsigned char init_po1030[][3] = { - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, - {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, - - {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)}, - - {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, - - {SENSOR, PO1030_AUTOCTRL2, 0x04}, - - {SENSOR, PO1030_OUTFORMCTRL2, PO1030_RAW_RGB_BAYER}, - {SENSOR, PO1030_AUTOCTRL1, PO1030_WEIGHT_WIN_2X}, - - {SENSOR, PO1030_CONTROL2, 0x03}, - {SENSOR, 0x21, 0x90}, - {SENSOR, PO1030_YTARGET, 0x60}, - {SENSOR, 0x59, 0x13}, - {SENSOR, PO1030_OUTFORMCTRL1, PO1030_HREF_ENABLE}, - {SENSOR, PO1030_EDGE_ENH_OFF, 0x00}, - {SENSOR, PO1030_EGA, 0x80}, - {SENSOR, 0x78, 0x14}, - {SENSOR, 0x6f, 0x01}, - {SENSOR, PO1030_GLOBALGAINMAX, 0x14}, - {SENSOR, PO1030_Cb_U_GAIN, 0x38}, - {SENSOR, PO1030_Cr_V_GAIN, 0x38}, - {SENSOR, PO1030_CONTROL1, PO1030_SHUTTER_MODE | - PO1030_AUTO_SUBSAMPLING | - PO1030_FRAME_EQUAL}, - {SENSOR, PO1030_GC0, 0x10}, - {SENSOR, PO1030_GC1, 0x20}, - {SENSOR, PO1030_GC2, 0x40}, - {SENSOR, PO1030_GC3, 0x60}, - {SENSOR, PO1030_GC4, 0x80}, - {SENSOR, PO1030_GC5, 0xa0}, - {SENSOR, PO1030_GC6, 0xc0}, - {SENSOR, PO1030_GC7, 0xff}, - - /* Set the width to 751 */ - {SENSOR, PO1030_FRAMEWIDTH_H, 0x02}, - {SENSOR, PO1030_FRAMEWIDTH_L, 0xef}, - - /* Set the height to 540 */ - {SENSOR, PO1030_FRAMEHEIGHT_H, 0x02}, - {SENSOR, PO1030_FRAMEHEIGHT_L, 0x1c}, - - /* Set the x window to 1 */ - {SENSOR, PO1030_WINDOWX_H, 0x00}, - {SENSOR, PO1030_WINDOWX_L, 0x01}, - - /* Set the y window to 1 */ - {SENSOR, PO1030_WINDOWY_H, 0x00}, - {SENSOR, PO1030_WINDOWY_L, 0x01}, - - /* with a very low lighted environment increase the exposure but - * decrease the FPS (Frame Per Second) */ - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, - - {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, -}; -#endif diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c deleted file mode 100644 index cc8ec3f7e8dc..000000000000 --- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ /dev/null @@ -1,726 +0,0 @@ -/* - * Driver for the s5k4aa sensor - * - * Copyright (C) 2008 Erik Andrén - * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. - * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> - * - * Portions of code to USB interface and ALi driver software, - * Copyright (c) 2006 Willem Duinker - * v4l2 interface modeled after the V4L2 driver - * for SN9C10x PC Camera Controllers - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "m5602_s5k4aa.h" - -static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); -static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val); -static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); -static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val); -static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); -static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val); -static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val); -static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val); -static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val); -static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val); -static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); -static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val); - -static - const - struct dmi_system_id s5k4aa_vflip_dmi_table[] = { - { - .ident = "BRUNEINIT", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "BRUNENIT"), - DMI_MATCH(DMI_PRODUCT_NAME, "BRUNENIT"), - DMI_MATCH(DMI_BOARD_VERSION, "00030D0000000001") - } - }, { - .ident = "Fujitsu-Siemens Amilo Xa 2528", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), - DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528") - } - }, { - .ident = "Fujitsu-Siemens Amilo Xi 2428", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), - DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2428") - } - }, { - .ident = "Fujitsu-Siemens Amilo Xi 2528", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), - DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2528") - } - }, { - .ident = "Fujitsu-Siemens Amilo Xi 2550", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), - DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550") - } - }, { - .ident = "Fujitsu-Siemens Amilo Pa 2548", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), - DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2548") - } - }, { - .ident = "MSI GX700", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), - DMI_MATCH(DMI_PRODUCT_NAME, "GX700"), - DMI_MATCH(DMI_BIOS_DATE, "12/02/2008") - } - }, { - .ident = "MSI GX700", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), - DMI_MATCH(DMI_PRODUCT_NAME, "GX700"), - DMI_MATCH(DMI_BIOS_DATE, "07/26/2007") - } - }, { - .ident = "MSI GX700", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), - DMI_MATCH(DMI_PRODUCT_NAME, "GX700"), - DMI_MATCH(DMI_BIOS_DATE, "07/19/2007") - } - }, { - .ident = "MSI GX700/GX705/EX700", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), - DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700") - } - }, { - .ident = "MSI L735", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), - DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X") - } - }, { - .ident = "Lenovo Y300", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "L3000 Y300"), - DMI_MATCH(DMI_PRODUCT_NAME, "Y300") - } - }, - { } -}; - -static struct v4l2_pix_format s5k4aa_modes[] = { - { - 640, - 480, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - 640 * 480, - .bytesperline = 640, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - }, - { - 1280, - 1024, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - 1280 * 1024, - .bytesperline = 1280, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - } -}; - -static const struct ctrl s5k4aa_ctrls[] = { -#define VFLIP_IDX 0 - { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = s5k4aa_set_vflip, - .get = s5k4aa_get_vflip - }, -#define HFLIP_IDX 1 - { - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "horizontal flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = s5k4aa_set_hflip, - .get = s5k4aa_get_hflip - }, -#define GAIN_IDX 2 - { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Gain", - .minimum = 0, - .maximum = 127, - .step = 1, - .default_value = S5K4AA_DEFAULT_GAIN, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = s5k4aa_set_gain, - .get = s5k4aa_get_gain - }, -#define EXPOSURE_IDX 3 - { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Exposure", - .minimum = 13, - .maximum = 0xfff, - .step = 1, - .default_value = 0x100, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = s5k4aa_set_exposure, - .get = s5k4aa_get_exposure - }, -#define NOISE_SUPP_IDX 4 - { - { - .id = V4L2_CID_PRIVATE_BASE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Noise suppression (smoothing)", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, - }, - .set = s5k4aa_set_noise, - .get = s5k4aa_get_noise - }, -#define BRIGHTNESS_IDX 5 - { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, - .maximum = 0x1f, - .step = 1, - .default_value = S5K4AA_DEFAULT_BRIGHTNESS, - }, - .set = s5k4aa_set_brightness, - .get = s5k4aa_get_brightness - }, - -}; - -static void s5k4aa_dump_registers(struct sd *sd); - -int s5k4aa_probe(struct sd *sd) -{ - u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75}; - int i, err = 0; - s32 *sensor_settings; - - if (force_sensor) { - if (force_sensor == S5K4AA_SENSOR) { - pr_info("Forcing a %s sensor\n", s5k4aa.name); - goto sensor_found; - } - /* If we want to force another sensor, don't try to probe this - * one */ - return -ENODEV; - } - - PDEBUG(D_PROBE, "Probing for a s5k4aa sensor"); - - /* Preinit the sensor */ - for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) { - u8 data[2] = {0x00, 0x00}; - - switch (preinit_s5k4aa[i][0]) { - case BRIDGE: - err = m5602_write_bridge(sd, - preinit_s5k4aa[i][1], - preinit_s5k4aa[i][2]); - break; - - case SENSOR: - data[0] = preinit_s5k4aa[i][2]; - err = m5602_write_sensor(sd, - preinit_s5k4aa[i][1], - data, 1); - break; - - case SENSOR_LONG: - data[0] = preinit_s5k4aa[i][2]; - data[1] = preinit_s5k4aa[i][3]; - err = m5602_write_sensor(sd, - preinit_s5k4aa[i][1], - data, 2); - break; - default: - pr_info("Invalid stream command, exiting init\n"); - return -EINVAL; - } - } - - /* Test some registers, but we don't know their exact meaning yet */ - if (m5602_read_sensor(sd, 0x00, prod_id, 2)) - return -ENODEV; - if (m5602_read_sensor(sd, 0x02, prod_id+2, 2)) - return -ENODEV; - if (m5602_read_sensor(sd, 0x04, prod_id+4, 2)) - return -ENODEV; - - if (memcmp(prod_id, expected_prod_id, sizeof(prod_id))) - return -ENODEV; - else - pr_info("Detected a s5k4aa sensor\n"); - -sensor_found: - sensor_settings = kmalloc( - ARRAY_SIZE(s5k4aa_ctrls) * sizeof(s32), GFP_KERNEL); - if (!sensor_settings) - return -ENOMEM; - - sd->gspca_dev.cam.cam_mode = s5k4aa_modes; - sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes); - sd->desc->ctrls = s5k4aa_ctrls; - sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls); - - for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++) - sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value; - sd->sensor_priv = sensor_settings; - - return 0; -} - -int s5k4aa_start(struct sd *sd) -{ - int i, err = 0; - u8 data[2]; - struct cam *cam = &sd->gspca_dev.cam; - s32 *sensor_settings = sd->sensor_priv; - - switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) { - case 1280: - PDEBUG(D_V4L2, "Configuring camera for SXGA mode"); - - for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) { - switch (SXGA_s5k4aa[i][0]) { - case BRIDGE: - err = m5602_write_bridge(sd, - SXGA_s5k4aa[i][1], - SXGA_s5k4aa[i][2]); - break; - - case SENSOR: - data[0] = SXGA_s5k4aa[i][2]; - err = m5602_write_sensor(sd, - SXGA_s5k4aa[i][1], - data, 1); - break; - - case SENSOR_LONG: - data[0] = SXGA_s5k4aa[i][2]; - data[1] = SXGA_s5k4aa[i][3]; - err = m5602_write_sensor(sd, - SXGA_s5k4aa[i][1], - data, 2); - break; - - default: - pr_err("Invalid stream command, exiting init\n"); - return -EINVAL; - } - } - err = s5k4aa_set_noise(&sd->gspca_dev, 0); - if (err < 0) - return err; - break; - - case 640: - PDEBUG(D_V4L2, "Configuring camera for VGA mode"); - - for (i = 0; i < ARRAY_SIZE(VGA_s5k4aa); i++) { - switch (VGA_s5k4aa[i][0]) { - case BRIDGE: - err = m5602_write_bridge(sd, - VGA_s5k4aa[i][1], - VGA_s5k4aa[i][2]); - break; - - case SENSOR: - data[0] = VGA_s5k4aa[i][2]; - err = m5602_write_sensor(sd, - VGA_s5k4aa[i][1], - data, 1); - break; - - case SENSOR_LONG: - data[0] = VGA_s5k4aa[i][2]; - data[1] = VGA_s5k4aa[i][3]; - err = m5602_write_sensor(sd, - VGA_s5k4aa[i][1], - data, 2); - break; - - default: - pr_err("Invalid stream command, exiting init\n"); - return -EINVAL; - } - } - err = s5k4aa_set_noise(&sd->gspca_dev, 1); - if (err < 0) - return err; - break; - } - if (err < 0) - return err; - - err = s5k4aa_set_exposure(&sd->gspca_dev, - sensor_settings[EXPOSURE_IDX]); - if (err < 0) - return err; - - err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); - if (err < 0) - return err; - - err = s5k4aa_set_brightness(&sd->gspca_dev, - sensor_settings[BRIGHTNESS_IDX]); - if (err < 0) - return err; - - err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]); - if (err < 0) - return err; - - err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); - if (err < 0) - return err; - - return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); -} - -int s5k4aa_init(struct sd *sd) -{ - int i, err = 0; - - for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) { - u8 data[2] = {0x00, 0x00}; - - switch (init_s5k4aa[i][0]) { - case BRIDGE: - err = m5602_write_bridge(sd, - init_s5k4aa[i][1], - init_s5k4aa[i][2]); - break; - - case SENSOR: - data[0] = init_s5k4aa[i][2]; - err = m5602_write_sensor(sd, - init_s5k4aa[i][1], data, 1); - break; - - case SENSOR_LONG: - data[0] = init_s5k4aa[i][2]; - data[1] = init_s5k4aa[i][3]; - err = m5602_write_sensor(sd, - init_s5k4aa[i][1], data, 2); - break; - default: - pr_info("Invalid stream command, exiting init\n"); - return -EINVAL; - } - } - - if (dump_sensor) - s5k4aa_dump_registers(sd); - - return err; -} - -static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[EXPOSURE_IDX]; - PDEBUG(D_V4L2, "Read exposure %d", *val); - - return 0; -} - -static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - u8 data = S5K4AA_PAGE_MAP_2; - int err; - - sensor_settings[EXPOSURE_IDX] = val; - PDEBUG(D_V4L2, "Set exposure to %d", val); - err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); - if (err < 0) - return err; - data = (val >> 8) & 0xff; - err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1); - if (err < 0) - return err; - data = val & 0xff; - err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); - - return err; -} - -static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[VFLIP_IDX]; - PDEBUG(D_V4L2, "Read vertical flip %d", *val); - - return 0; -} - -static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - u8 data = S5K4AA_PAGE_MAP_2; - int err; - - sensor_settings[VFLIP_IDX] = val; - - PDEBUG(D_V4L2, "Set vertical flip to %d", val); - err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); - if (err < 0) - return err; - - err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1); - if (err < 0) - return err; - - if (dmi_check_system(s5k4aa_vflip_dmi_table)) - val = !val; - - data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7)); - err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); - if (err < 0) - return err; - - err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); - if (err < 0) - return err; - if (val) - data &= 0xfe; - else - data |= 0x01; - err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); - return err; -} - -static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[HFLIP_IDX]; - PDEBUG(D_V4L2, "Read horizontal flip %d", *val); - - return 0; -} - -static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - u8 data = S5K4AA_PAGE_MAP_2; - int err; - - sensor_settings[HFLIP_IDX] = val; - - PDEBUG(D_V4L2, "Set horizontal flip to %d", val); - err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); - if (err < 0) - return err; - - err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1); - if (err < 0) - return err; - - if (dmi_check_system(s5k4aa_vflip_dmi_table)) - val = !val; - - data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6)); - err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); - if (err < 0) - return err; - - err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); - if (err < 0) - return err; - if (val) - data &= 0xfe; - else - data |= 0x01; - err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); - return err; -} - -static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[GAIN_IDX]; - PDEBUG(D_V4L2, "Read gain %d", *val); - return 0; -} - -static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - u8 data = S5K4AA_PAGE_MAP_2; - int err; - - sensor_settings[GAIN_IDX] = val; - - PDEBUG(D_V4L2, "Set gain to %d", val); - err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); - if (err < 0) - return err; - - data = val & 0xff; - err = m5602_write_sensor(sd, S5K4AA_GAIN, &data, 1); - - return err; -} - -static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[BRIGHTNESS_IDX]; - PDEBUG(D_V4L2, "Read brightness %d", *val); - return 0; -} - -static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - u8 data = S5K4AA_PAGE_MAP_2; - int err; - - sensor_settings[BRIGHTNESS_IDX] = val; - - PDEBUG(D_V4L2, "Set brightness to %d", val); - err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); - if (err < 0) - return err; - - data = val & 0xff; - return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1); -} - -static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - - *val = sensor_settings[NOISE_SUPP_IDX]; - PDEBUG(D_V4L2, "Read noise %d", *val); - return 0; -} - -static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 *sensor_settings = sd->sensor_priv; - u8 data = S5K4AA_PAGE_MAP_2; - int err; - - sensor_settings[NOISE_SUPP_IDX] = val; - - PDEBUG(D_V4L2, "Set noise to %d", val); - err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); - if (err < 0) - return err; - - data = val & 0x01; - return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1); -} - -void s5k4aa_disconnect(struct sd *sd) -{ - sd->sensor = NULL; - kfree(sd->sensor_priv); -} - -static void s5k4aa_dump_registers(struct sd *sd) -{ - int address; - u8 page, old_page; - m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1); - for (page = 0; page < 16; page++) { - m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1); - pr_info("Dumping the s5k4aa register state for page 0x%x\n", - page); - for (address = 0; address <= 0xff; address++) { - u8 value = 0; - m5602_read_sensor(sd, address, &value, 1); - pr_info("register 0x%x contains 0x%x\n", - address, value); - } - } - pr_info("s5k4aa register state dump complete\n"); - - for (page = 0; page < 16; page++) { - m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1); - pr_info("Probing for which registers that are read/write for page 0x%x\n", - page); - for (address = 0; address <= 0xff; address++) { - u8 old_value, ctrl_value, test_value = 0xff; - - m5602_read_sensor(sd, address, &old_value, 1); - m5602_write_sensor(sd, address, &test_value, 1); - m5602_read_sensor(sd, address, &ctrl_value, 1); - - if (ctrl_value == test_value) - pr_info("register 0x%x is writeable\n", - address); - else - pr_info("register 0x%x is read only\n", - address); - - /* Restore original value */ - m5602_write_sensor(sd, address, &old_value, 1); - } - } - pr_info("Read/write register probing complete\n"); - m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1); -} diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h deleted file mode 100644 index 8e0035e731c7..000000000000 --- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Driver for the s5k4aa sensor - * - * Copyright (C) 2008 Erik Andrén - * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. - * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> - * - * Portions of code to USB interface and ALi driver software, - * Copyright (c) 2006 Willem Duinker - * v4l2 interface modeled after the V4L2 driver - * for SN9C10x PC Camera Controllers - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#ifndef M5602_S5K4AA_H_ -#define M5602_S5K4AA_H_ - -#include <linux/dmi.h> - -#include "m5602_sensor.h" - -/*****************************************************************************/ - -#define S5K4AA_PAGE_MAP 0xec - -#define S5K4AA_PAGE_MAP_0 0x00 -#define S5K4AA_PAGE_MAP_1 0x01 -#define S5K4AA_PAGE_MAP_2 0x02 - -/* Sensor register definitions for page 0x02 */ -#define S5K4AA_READ_MODE 0x03 -#define S5K4AA_ROWSTART_HI 0x04 -#define S5K4AA_ROWSTART_LO 0x05 -#define S5K4AA_COLSTART_HI 0x06 -#define S5K4AA_COLSTART_LO 0x07 -#define S5K4AA_WINDOW_HEIGHT_HI 0x08 -#define S5K4AA_WINDOW_HEIGHT_LO 0x09 -#define S5K4AA_WINDOW_WIDTH_HI 0x0a -#define S5K4AA_WINDOW_WIDTH_LO 0x0b -#define S5K4AA_GLOBAL_GAIN__ 0x0f -/* sync lost, if too low, reduces frame rate if too high */ -#define S5K4AA_H_BLANK_HI__ 0x1d -#define S5K4AA_H_BLANK_LO__ 0x1e -#define S5K4AA_EXPOSURE_HI 0x17 -#define S5K4AA_EXPOSURE_LO 0x18 -#define S5K4AA_BRIGHTNESS 0x1f /* (digital?) gain : 5 bits */ -#define S5K4AA_GAIN 0x20 /* (analogue?) gain : 7 bits */ -#define S5K4AA_NOISE_SUPP 0x37 - -#define S5K4AA_RM_ROW_SKIP_4X 0x08 -#define S5K4AA_RM_ROW_SKIP_2X 0x04 -#define S5K4AA_RM_COL_SKIP_4X 0x02 -#define S5K4AA_RM_COL_SKIP_2X 0x01 -#define S5K4AA_RM_H_FLIP 0x40 -#define S5K4AA_RM_V_FLIP 0x80 - -#define S5K4AA_DEFAULT_GAIN 0x5f -#define S5K4AA_DEFAULT_BRIGHTNESS 0x10 - -/*****************************************************************************/ - -/* Kernel module parameters */ -extern int force_sensor; -extern bool dump_sensor; - -int s5k4aa_probe(struct sd *sd); -int s5k4aa_init(struct sd *sd); -int s5k4aa_start(struct sd *sd); -void s5k4aa_disconnect(struct sd *sd); - -static const struct m5602_sensor s5k4aa = { - .name = "S5K4AA", - .i2c_slave_id = 0x5a, - .i2c_regW = 2, - - .probe = s5k4aa_probe, - .init = s5k4aa_init, - .start = s5k4aa_start, - .disconnect = s5k4aa_disconnect, -}; - -static const unsigned char preinit_s5k4aa[][4] = { - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, - {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, - - {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00}, - - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, - - {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00} -}; - -static const unsigned char init_s5k4aa[][4] = { - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, - {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, - - {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00}, - - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, - - {SENSOR, S5K4AA_PAGE_MAP, 0x07, 0x00}, - {SENSOR, 0x36, 0x01, 0x00}, - {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00}, - {SENSOR, 0x7b, 0xff, 0x00}, - {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, - {SENSOR, 0x0c, 0x05, 0x00}, - {SENSOR, 0x02, 0x0e, 0x00}, - {SENSOR, S5K4AA_READ_MODE, 0xa0, 0x00}, - {SENSOR, 0x37, 0x00, 0x00}, -}; - -static const unsigned char VGA_s5k4aa[][4] = { - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - /* VSYNC_PARA, VSYNC_PARA : img height 480 = 0x01e0 */ - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - /* HSYNC_PARA, HSYNC_PARA : img width 640 = 0x0280 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x80, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */ - - {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, - {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X - | S5K4AA_RM_COL_SKIP_2X, 0x00}, - /* 0x37 : Fix image stability when light is too bright and improves - * image quality in 640x480, but worsens it in 1280x1024 */ - {SENSOR, 0x37, 0x01, 0x00}, - /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */ - {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_ROWSTART_LO, 0x29, 0x00}, - {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00}, - /* window_height_hi, window_height_lo : 960 = 0x03c0 */ - {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00}, - {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc0, 0x00}, - /* window_width_hi, window_width_lo : 1280 = 0x0500 */ - {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00}, - {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00}, - {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00}, - {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, /* helps to sync... */ - {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00}, - {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00}, - {SENSOR, 0x11, 0x04, 0x00}, - {SENSOR, 0x12, 0xc3, 0x00}, - {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, - {SENSOR, 0x02, 0x0e, 0x00}, -}; - -static const unsigned char SXGA_s5k4aa[][4] = { - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - /* VSYNC_PARA, VSYNC_PARA : img height 1024 = 0x0400 */ - {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - /* HSYNC_PARA, HSYNC_PARA : img width 1280 = 0x0500 */ - {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */ - - {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, - {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP, 0x00}, - {SENSOR, 0x37, 0x01, 0x00}, - {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_ROWSTART_LO, 0x09, 0x00}, - {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, - {SENSOR, S5K4AA_COLSTART_LO, 0x0a, 0x00}, - {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x04, 0x00}, - {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0x00, 0x00}, - {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00}, - {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00}, - {SENSOR, S5K4AA_H_BLANK_HI__, 0x01, 0x00}, - {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, - {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00}, - {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00}, - {SENSOR, 0x11, 0x04, 0x00}, - {SENSOR, 0x12, 0xc3, 0x00}, - {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, - {SENSOR, 0x02, 0x0e, 0x00}, -}; -#endif diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c deleted file mode 100644 index 1de743a02b02..000000000000 --- a/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Driver for the s5k83a sensor - * - * Copyright (C) 2008 Erik Andrén - * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. - * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> - * - * Portions of code to USB interface and ALi driver software, - * Copyright (c) 2006 Willem Duinker - * v4l2 interface modeled after the V4L2 driver - * for SN9C10x PC Camera Controllers - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/kthread.h> -#include "m5602_s5k83a.h" - -static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val); -static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val); -static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val); -static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); -static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val); -static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); -static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); -static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val); -static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); -static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val); - -static struct v4l2_pix_format s5k83a_modes[] = { - { - 640, - 480, - V4L2_PIX_FMT_SBGGR8, - V4L2_FIELD_NONE, - .sizeimage = - 640 * 480, - .bytesperline = 640, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - } -}; - -static const struct ctrl s5k83a_ctrls[] = { -#define GAIN_IDX 0 - { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "gain", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = S5K83A_DEFAULT_GAIN, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = s5k83a_set_gain, - .get = s5k83a_get_gain - - }, -#define BRIGHTNESS_IDX 1 - { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "brightness", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = S5K83A_DEFAULT_BRIGHTNESS, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = s5k83a_set_brightness, - .get = s5k83a_get_brightness, - }, -#define EXPOSURE_IDX 2 - { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = S5K83A_MAXIMUM_EXPOSURE, - .step = 0x01, - .default_value = S5K83A_DEFAULT_EXPOSURE, - .flags = V4L2_CTRL_FLAG_SLIDER - }, - .set = s5k83a_set_exposure, - .get = s5k83a_get_exposure - }, -#define HFLIP_IDX 3 - { - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "horizontal flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = s5k83a_set_hflip, - .get = s5k83a_get_hflip - }, -#define VFLIP_IDX 4 - { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical flip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0 - }, - .set = s5k83a_set_vflip, - .get = s5k83a_get_vflip - } -}; - -static void s5k83a_dump_registers(struct sd *sd); -static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data); -static int s5k83a_set_led_indication(struct sd *sd, u8 val); -static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, - __s32 vflip, __s32 hflip); - -int s5k83a_probe(struct sd *sd) -{ - struct s5k83a_priv *sens_priv; - u8 prod_id = 0, ver_id = 0; - int i, err = 0; - - if (force_sensor) { - if (force_sensor == S5K83A_SENSOR) { - pr_info("Forcing a %s sensor\n", s5k83a.name); - goto sensor_found; - } - /* If we want to force another sensor, don't try to probe this - * one */ - return -ENODEV; - } - - PDEBUG(D_PROBE, "Probing for a s5k83a sensor"); - - /* Preinit the sensor */ - for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) { - u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]}; - if (preinit_s5k83a[i][0] == SENSOR) - err = m5602_write_sensor(sd, preinit_s5k83a[i][1], - data, 2); - else - err = m5602_write_bridge(sd, preinit_s5k83a[i][1], - data[0]); - } - - /* We don't know what register (if any) that contain the product id - * Just pick the first addresses that seem to produce the same results - * on multiple machines */ - if (m5602_read_sensor(sd, 0x00, &prod_id, 1)) - return -ENODEV; - - if (m5602_read_sensor(sd, 0x01, &ver_id, 1)) - return -ENODEV; - - if ((prod_id == 0xff) || (ver_id == 0xff)) - return -ENODEV; - else - pr_info("Detected a s5k83a sensor\n"); - -sensor_found: - sens_priv = kmalloc( - sizeof(struct s5k83a_priv), GFP_KERNEL); - if (!sens_priv) - return -ENOMEM; - - sens_priv->settings = - kmalloc(sizeof(s32)*ARRAY_SIZE(s5k83a_ctrls), GFP_KERNEL); - if (!sens_priv->settings) { - kfree(sens_priv); - return -ENOMEM; - } - - sd->gspca_dev.cam.cam_mode = s5k83a_modes; - sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes); - sd->desc->ctrls = s5k83a_ctrls; - sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls); - - /* null the pointer! thread is't running now */ - sens_priv->rotation_thread = NULL; - - for (i = 0; i < ARRAY_SIZE(s5k83a_ctrls); i++) - sens_priv->settings[i] = s5k83a_ctrls[i].qctrl.default_value; - - sd->sensor_priv = sens_priv; - return 0; -} - -int s5k83a_init(struct sd *sd) -{ - int i, err = 0; - s32 *sensor_settings = - ((struct s5k83a_priv *) sd->sensor_priv)->settings; - - for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) { - u8 data[2] = {0x00, 0x00}; - - switch (init_s5k83a[i][0]) { - case BRIDGE: - err = m5602_write_bridge(sd, - init_s5k83a[i][1], - init_s5k83a[i][2]); - break; - - case SENSOR: - data[0] = init_s5k83a[i][2]; - err = m5602_write_sensor(sd, - init_s5k83a[i][1], data, 1); - break; - - case SENSOR_LONG: - data[0] = init_s5k83a[i][2]; - data[1] = init_s5k83a[i][3]; - err = m5602_write_sensor(sd, - init_s5k83a[i][1], data, 2); - break; - default: - pr_info("Invalid stream command, exiting init\n"); - return -EINVAL; - } - } - - if (dump_sensor) - s5k83a_dump_registers(sd); - - err = s5k83a_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); - if (err < 0) - return err; - - err = s5k83a_set_brightness(&sd->gspca_dev, - sensor_settings[BRIGHTNESS_IDX]); - if (err < 0) - return err; - - err = s5k83a_set_exposure(&sd->gspca_dev, - sensor_settings[EXPOSURE_IDX]); - if (err < 0) - return err; - - err = s5k83a_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); - if (err < 0) - return err; - - err = s5k83a_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); - - return err; -} - -static int rotation_thread_function(void *data) -{ - struct sd *sd = (struct sd *) data; - struct s5k83a_priv *sens_priv = sd->sensor_priv; - u8 reg, previous_rotation = 0; - __s32 vflip, hflip; - - set_current_state(TASK_INTERRUPTIBLE); - while (!schedule_timeout(100)) { - if (mutex_lock_interruptible(&sd->gspca_dev.usb_lock)) - break; - - s5k83a_get_rotation(sd, ®); - if (previous_rotation != reg) { - previous_rotation = reg; - pr_info("Camera was flipped\n"); - - s5k83a_get_vflip((struct gspca_dev *) sd, &vflip); - s5k83a_get_hflip((struct gspca_dev *) sd, &hflip); - - if (reg) { - vflip = !vflip; - hflip = !hflip; - } - s5k83a_set_flip_real((struct gspca_dev *) sd, - vflip, hflip); - } - - mutex_unlock(&sd->gspca_dev.usb_lock); - set_current_state(TASK_INTERRUPTIBLE); - } - - /* return to "front" flip */ - if (previous_rotation) { - s5k83a_get_vflip((struct gspca_dev *) sd, &vflip); - s5k83a_get_hflip((struct gspca_dev *) sd, &hflip); - s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip); - } - - sens_priv->rotation_thread = NULL; - return 0; -} - -int s5k83a_start(struct sd *sd) -{ - int i, err = 0; - struct s5k83a_priv *sens_priv = sd->sensor_priv; - - /* Create another thread, polling the GPIO ports of the camera to check - if it got rotated. This is how the windows driver does it so we have - to assume that there is no better way of accomplishing this */ - sens_priv->rotation_thread = kthread_create(rotation_thread_function, - sd, "rotation thread"); - wake_up_process(sens_priv->rotation_thread); - - /* Preinit the sensor */ - for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) { - u8 data[2] = {start_s5k83a[i][2], start_s5k83a[i][3]}; - if (start_s5k83a[i][0] == SENSOR) - err = m5602_write_sensor(sd, start_s5k83a[i][1], - data, 2); - else - err = m5602_write_bridge(sd, start_s5k83a[i][1], - data[0]); - } - if (err < 0) - return err; - - return s5k83a_set_led_indication(sd, 1); -} - -int s5k83a_stop(struct sd *sd) -{ - struct s5k83a_priv *sens_priv = sd->sensor_priv; - - if (sens_priv->rotation_thread) - kthread_stop(sens_priv->rotation_thread); - - return s5k83a_set_led_indication(sd, 0); -} - -void s5k83a_disconnect(struct sd *sd) -{ - struct s5k83a_priv *sens_priv = sd->sensor_priv; - - s5k83a_stop(sd); - - sd->sensor = NULL; - kfree(sens_priv->settings); - kfree(sens_priv); -} - -static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct s5k83a_priv *sens_priv = sd->sensor_priv; - - *val = sens_priv->settings[GAIN_IDX]; - return 0; -} - -static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 data[2]; - struct sd *sd = (struct sd *) gspca_dev; - struct s5k83a_priv *sens_priv = sd->sensor_priv; - - sens_priv->settings[GAIN_IDX] = val; - - data[0] = 0x00; - data[1] = 0x20; - err = m5602_write_sensor(sd, 0x14, data, 2); - if (err < 0) - return err; - - data[0] = 0x01; - data[1] = 0x00; - err = m5602_write_sensor(sd, 0x0d, data, 2); - if (err < 0) - return err; - - /* FIXME: This is not sane, we need to figure out the composition - of these registers */ - data[0] = val >> 3; /* gain, high 5 bits */ - data[1] = val >> 1; /* gain, high 7 bits */ - err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2); - - return err; -} - -static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct s5k83a_priv *sens_priv = sd->sensor_priv; - - *val = sens_priv->settings[BRIGHTNESS_IDX]; - return 0; -} - -static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 data[1]; - struct sd *sd = (struct sd *) gspca_dev; - struct s5k83a_priv *sens_priv = sd->sensor_priv; - - sens_priv->settings[BRIGHTNESS_IDX] = val; - data[0] = val; - err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1); - return err; -} - -static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct s5k83a_priv *sens_priv = sd->sensor_priv; - - *val = sens_priv->settings[EXPOSURE_IDX]; - return 0; -} - -static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 data[2]; - struct sd *sd = (struct sd *) gspca_dev; - struct s5k83a_priv *sens_priv = sd->sensor_priv; - - sens_priv->settings[EXPOSURE_IDX] = val; - data[0] = 0; - data[1] = val; - err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2); - return err; -} - -static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct s5k83a_priv *sens_priv = sd->sensor_priv; - - *val = sens_priv->settings[VFLIP_IDX]; - return 0; -} - -static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, - __s32 vflip, __s32 hflip) -{ - int err; - u8 data[1]; - struct sd *sd = (struct sd *) gspca_dev; - - data[0] = 0x05; - err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); - if (err < 0) - return err; - - /* six bit is vflip, seven is hflip */ - data[0] = S5K83A_FLIP_MASK; - data[0] = (vflip) ? data[0] | 0x40 : data[0]; - data[0] = (hflip) ? data[0] | 0x80 : data[0]; - - err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1); - if (err < 0) - return err; - - data[0] = (vflip) ? 0x0b : 0x0a; - err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1); - if (err < 0) - return err; - - data[0] = (hflip) ? 0x0a : 0x0b; - err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1); - return err; -} - -static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 reg; - __s32 hflip; - struct sd *sd = (struct sd *) gspca_dev; - struct s5k83a_priv *sens_priv = sd->sensor_priv; - - sens_priv->settings[VFLIP_IDX] = val; - - s5k83a_get_hflip(gspca_dev, &hflip); - - err = s5k83a_get_rotation(sd, ®); - if (err < 0) - return err; - if (reg) { - val = !val; - hflip = !hflip; - } - - err = s5k83a_set_flip_real(gspca_dev, val, hflip); - return err; -} - -static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct s5k83a_priv *sens_priv = sd->sensor_priv; - - *val = sens_priv->settings[HFLIP_IDX]; - return 0; -} - -static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u8 reg; - __s32 vflip; - struct sd *sd = (struct sd *) gspca_dev; - struct s5k83a_priv *sens_priv = sd->sensor_priv; - - sens_priv->settings[HFLIP_IDX] = val; - - s5k83a_get_vflip(gspca_dev, &vflip); - - err = s5k83a_get_rotation(sd, ®); - if (err < 0) - return err; - if (reg) { - val = !val; - vflip = !vflip; - } - - err = s5k83a_set_flip_real(gspca_dev, vflip, val); - return err; -} - -static int s5k83a_set_led_indication(struct sd *sd, u8 val) -{ - int err = 0; - u8 data[1]; - - err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, data); - if (err < 0) - return err; - - if (val) - data[0] = data[0] | S5K83A_GPIO_LED_MASK; - else - data[0] = data[0] & ~S5K83A_GPIO_LED_MASK; - - err = m5602_write_bridge(sd, M5602_XB_GPIO_DAT, data[0]); - - return err; -} - -/* Get camera rotation on Acer notebooks */ -static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data) -{ - int err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, reg_data); - *reg_data = (*reg_data & S5K83A_GPIO_ROTATION_MASK) ? 0 : 1; - return err; -} - -static void s5k83a_dump_registers(struct sd *sd) -{ - int address; - u8 page, old_page; - m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); - - for (page = 0; page < 16; page++) { - m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); - pr_info("Dumping the s5k83a register state for page 0x%x\n", - page); - for (address = 0; address <= 0xff; address++) { - u8 val = 0; - m5602_read_sensor(sd, address, &val, 1); - pr_info("register 0x%x contains 0x%x\n", address, val); - } - } - pr_info("s5k83a register state dump complete\n"); - - for (page = 0; page < 16; page++) { - m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); - pr_info("Probing for which registers that are read/write for page 0x%x\n", - page); - for (address = 0; address <= 0xff; address++) { - u8 old_val, ctrl_val, test_val = 0xff; - - m5602_read_sensor(sd, address, &old_val, 1); - m5602_write_sensor(sd, address, &test_val, 1); - m5602_read_sensor(sd, address, &ctrl_val, 1); - - if (ctrl_val == test_val) - pr_info("register 0x%x is writeable\n", - address); - else - pr_info("register 0x%x is read only\n", - address); - - /* Restore original val */ - m5602_write_sensor(sd, address, &old_val, 1); - } - } - pr_info("Read/write register probing complete\n"); - m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); -} diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/drivers/media/video/gspca/m5602/m5602_s5k83a.h deleted file mode 100644 index 79952247b534..000000000000 --- a/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Driver for the s5k83a sensor - * - * Copyright (C) 2008 Erik Andrén - * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. - * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> - * - * Portions of code to USB interface and ALi driver software, - * Copyright (c) 2006 Willem Duinker - * v4l2 interface modeled after the V4L2 driver - * for SN9C10x PC Camera Controllers - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#ifndef M5602_S5K83A_H_ -#define M5602_S5K83A_H_ - -#include "m5602_sensor.h" - -#define S5K83A_FLIP 0x01 -#define S5K83A_HFLIP_TUNE 0x03 -#define S5K83A_VFLIP_TUNE 0x05 -#define S5K83A_BRIGHTNESS 0x0a -#define S5K83A_EXPOSURE 0x18 -#define S5K83A_GAIN 0x1b -#define S5K83A_PAGE_MAP 0xec - -#define S5K83A_DEFAULT_GAIN 0x71 -#define S5K83A_DEFAULT_BRIGHTNESS 0x7e -#define S5K83A_DEFAULT_EXPOSURE 0x00 -#define S5K83A_MAXIMUM_EXPOSURE 0x3c -#define S5K83A_FLIP_MASK 0x10 -#define S5K83A_GPIO_LED_MASK 0x10 -#define S5K83A_GPIO_ROTATION_MASK 0x40 - -/*****************************************************************************/ - -/* Kernel module parameters */ -extern int force_sensor; -extern bool dump_sensor; - -int s5k83a_probe(struct sd *sd); -int s5k83a_init(struct sd *sd); -int s5k83a_start(struct sd *sd); -int s5k83a_stop(struct sd *sd); -void s5k83a_disconnect(struct sd *sd); - -static const struct m5602_sensor s5k83a = { - .name = "S5K83A", - .probe = s5k83a_probe, - .init = s5k83a_init, - .start = s5k83a_start, - .stop = s5k83a_stop, - .disconnect = s5k83a_disconnect, - .i2c_slave_id = 0x5a, - .i2c_regW = 2, -}; - -struct s5k83a_priv { - /* We use another thread periodically - probing the orientation of the camera */ - struct task_struct *rotation_thread; - s32 *settings; -}; - -static const unsigned char preinit_s5k83a[][4] = { - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, - {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, - - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, -}; - -/* This could probably be considerably shortened. - I don't have the hardware to experiment with it, patches welcome -*/ -static const unsigned char init_s5k83a[][4] = { - /* The following sequence is useless after a clean boot - but is necessary after resume from suspend */ - {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, - {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, - {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, - {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, - {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, - - {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00}, - {SENSOR, 0xaf, 0x01, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00}, - {SENSOR, 0x7b, 0xff, 0x00}, - {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, - {SENSOR, 0x01, 0x50, 0x00}, - {SENSOR, 0x12, 0x20, 0x00}, - {SENSOR, 0x17, 0x40, 0x00}, - {SENSOR, 0x1c, 0x00, 0x00}, - {SENSOR, 0x02, 0x70, 0x00}, - {SENSOR, 0x03, 0x0b, 0x00}, - {SENSOR, 0x04, 0xf0, 0x00}, - {SENSOR, 0x05, 0x0b, 0x00}, - {SENSOR, 0x06, 0x71, 0x00}, - {SENSOR, 0x07, 0xe8, 0x00}, /* 488 */ - {SENSOR, 0x08, 0x02, 0x00}, - {SENSOR, 0x09, 0x88, 0x00}, /* 648 */ - {SENSOR, 0x14, 0x00, 0x00}, - {SENSOR, 0x15, 0x20, 0x00}, /* 32 */ - {SENSOR, 0x19, 0x00, 0x00}, - {SENSOR, 0x1a, 0x98, 0x00}, /* 152 */ - {SENSOR, 0x0f, 0x02, 0x00}, - {SENSOR, 0x10, 0xe5, 0x00}, /* 741 */ - /* normal colors - (this is value after boot, but after tries can be different) */ - {SENSOR, 0x00, 0x06, 0x00}, -}; - -static const unsigned char start_s5k83a[][4] = { - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, - {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, - {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, - {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, - {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, /* 484 */ - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, - {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, /* 639 */ - {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, - {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, -}; -#endif diff --git a/drivers/media/video/gspca/m5602/m5602_sensor.h b/drivers/media/video/gspca/m5602/m5602_sensor.h deleted file mode 100644 index edff4f1f586f..000000000000 --- a/drivers/media/video/gspca/m5602/m5602_sensor.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * USB Driver for ALi m5602 based webcams - * - * Copyright (C) 2008 Erik Andrén - * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. - * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> - * - * Portions of code to USB interface and ALi driver software, - * Copyright (c) 2006 Willem Duinker - * v4l2 interface modeled after the V4L2 driver - * for SN9C10x PC Camera Controllers - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#ifndef M5602_SENSOR_H_ -#define M5602_SENSOR_H_ - -#include "m5602_bridge.h" - -#define M5602_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 0) -#define M5602_V4L2_CID_NOISE_SUPPRESION (V4L2_CID_PRIVATE_BASE + 1) - -/* Enumerates all supported sensors */ -enum sensors { - OV9650_SENSOR = 1, - S5K83A_SENSOR = 2, - S5K4AA_SENSOR = 3, - MT9M111_SENSOR = 4, - PO1030_SENSOR = 5, - OV7660_SENSOR = 6, -}; - -/* Enumerates all possible instruction types */ -enum instruction { - BRIDGE, - SENSOR, - SENSOR_LONG -}; - -struct m5602_sensor { - /* Defines the name of a sensor */ - char name[32]; - - /* What i2c address the sensor is connected to */ - u8 i2c_slave_id; - - /* Width of each i2c register (in bytes) */ - u8 i2c_regW; - - /* Probes if the sensor is connected */ - int (*probe)(struct sd *sd); - - /* Performs a initialization sequence */ - int (*init)(struct sd *sd); - - /* Executed when the camera starts to send data */ - int (*start)(struct sd *sd); - - /* Executed when the camera ends to send data */ - int (*stop)(struct sd *sd); - - /* Executed when the device is disconnected */ - void (*disconnect)(struct sd *sd); -}; - -#endif diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c deleted file mode 100644 index ff2c5abf115b..000000000000 --- a/drivers/media/video/gspca/mars.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Mars-Semi MR97311A library - * Copyright (C) 2005 <bradlch@hotmail.com> - * - * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "mars" - -#include "gspca.h" -#include "jpeg.h" - -MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); -MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver"); -MODULE_LICENSE("GPL"); - -#define QUALITY 50 - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - struct v4l2_ctrl *brightness; - struct v4l2_ctrl *saturation; - struct v4l2_ctrl *sharpness; - struct v4l2_ctrl *gamma; - struct { /* illuminator control cluster */ - struct v4l2_ctrl *illum_top; - struct v4l2_ctrl *illum_bottom; - }; - u8 jpeg_hdr[JPEG_HDR_SZ]; -}; - -/* V4L2 controls supported by the driver */ -static void setbrightness(struct gspca_dev *gspca_dev, s32 val); -static void setcolors(struct gspca_dev *gspca_dev, s32 val); -static void setgamma(struct gspca_dev *gspca_dev, s32 val); -static void setsharpness(struct gspca_dev *gspca_dev, s32 val); - -static const struct v4l2_pix_format vga_mode[] = { - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, -}; - -static const __u8 mi_data[0x20] = { -/* 01 02 03 04 05 06 07 08 */ - 0x48, 0x22, 0x01, 0x47, 0x10, 0x00, 0x00, 0x00, -/* 09 0a 0b 0c 0d 0e 0f 10 */ - 0x00, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01, -/* 11 12 13 14 15 16 17 18 */ - 0x30, 0x00, 0x04, 0x00, 0x06, 0x01, 0xe2, 0x02, -/* 19 1a 1b 1c 1d 1e 1f 20 */ - 0x82, 0x00, 0x20, 0x17, 0x80, 0x08, 0x0c, 0x00 -}; - -/* write <len> bytes from gspca_dev->usb_buf */ -static void reg_w(struct gspca_dev *gspca_dev, - int len) -{ - int alen, ret; - - if (gspca_dev->usb_err < 0) - return; - - ret = usb_bulk_msg(gspca_dev->dev, - usb_sndbulkpipe(gspca_dev->dev, 4), - gspca_dev->usb_buf, - len, - &alen, - 500); /* timeout in milliseconds */ - if (ret < 0) { - pr_err("reg write [%02x] error %d\n", - gspca_dev->usb_buf[0], ret); - gspca_dev->usb_err = ret; - } -} - -static void mi_w(struct gspca_dev *gspca_dev, - u8 addr, - u8 value) -{ - gspca_dev->usb_buf[0] = 0x1f; - gspca_dev->usb_buf[1] = 0; /* control byte */ - gspca_dev->usb_buf[2] = addr; - gspca_dev->usb_buf[3] = value; - - reg_w(gspca_dev, 4); -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 val) -{ - gspca_dev->usb_buf[0] = 0x61; - gspca_dev->usb_buf[1] = val; - reg_w(gspca_dev, 2); -} - -static void setcolors(struct gspca_dev *gspca_dev, s32 val) -{ - gspca_dev->usb_buf[0] = 0x5f; - gspca_dev->usb_buf[1] = val << 3; - gspca_dev->usb_buf[2] = ((val >> 2) & 0xf8) | 0x04; - reg_w(gspca_dev, 3); -} - -static void setgamma(struct gspca_dev *gspca_dev, s32 val) -{ - gspca_dev->usb_buf[0] = 0x06; - gspca_dev->usb_buf[1] = val * 0x40; - reg_w(gspca_dev, 2); -} - -static void setsharpness(struct gspca_dev *gspca_dev, s32 val) -{ - gspca_dev->usb_buf[0] = 0x67; - gspca_dev->usb_buf[1] = val * 4 + 3; - reg_w(gspca_dev, 2); -} - -static void setilluminators(struct gspca_dev *gspca_dev, bool top, bool bottom) -{ - /* both are off if not streaming */ - gspca_dev->usb_buf[0] = 0x22; - if (top) - gspca_dev->usb_buf[1] = 0x76; - else if (bottom) - gspca_dev->usb_buf[1] = 0x7a; - else - gspca_dev->usb_buf[1] = 0x7e; - reg_w(gspca_dev, 2); -} - -static int mars_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (ctrl->id == V4L2_CID_ILLUMINATORS_1) { - /* only one can be on at a time */ - if (ctrl->is_new && ctrl->val) - sd->illum_bottom->val = 0; - if (sd->illum_bottom->is_new && sd->illum_bottom->val) - sd->illum_top->val = 0; - } - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_SATURATION: - setcolors(gspca_dev, ctrl->val); - break; - case V4L2_CID_GAMMA: - setgamma(gspca_dev, ctrl->val); - break; - case V4L2_CID_ILLUMINATORS_1: - setilluminators(gspca_dev, sd->illum_top->val, - sd->illum_bottom->val); - break; - case V4L2_CID_SHARPNESS: - setsharpness(gspca_dev, ctrl->val); - break; - default: - return -EINVAL; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops mars_ctrl_ops = { - .s_ctrl = mars_s_ctrl, -}; - -/* this function is called at probe time */ -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 6); - sd->brightness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 30, 1, 15); - sd->saturation = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops, - V4L2_CID_SATURATION, 0, 255, 1, 200); - sd->gamma = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops, - V4L2_CID_GAMMA, 0, 3, 1, 1); - sd->sharpness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops, - V4L2_CID_SHARPNESS, 0, 2, 1, 1); - sd->illum_top = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops, - V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0); - sd->illum_top->flags |= V4L2_CTRL_FLAG_UPDATE; - sd->illum_bottom = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops, - V4L2_CID_ILLUMINATORS_2, 0, 1, 1, 0); - sd->illum_bottom->flags |= V4L2_CTRL_FLAG_UPDATE; - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - v4l2_ctrl_cluster(2, &sd->illum_top); - return 0; -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct cam *cam; - - cam = &gspca_dev->cam; - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - return 0; -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 *data; - int i; - - /* create the JPEG header */ - jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, - 0x21); /* JPEG 422 */ - jpeg_set_qual(sd->jpeg_hdr, QUALITY); - - data = gspca_dev->usb_buf; - - data[0] = 0x01; /* address */ - data[1] = 0x01; - reg_w(gspca_dev, 2); - - /* - Initialize the MR97113 chip register - */ - data[0] = 0x00; /* address */ - data[1] = 0x0c | 0x01; /* reg 0 */ - data[2] = 0x01; /* reg 1 */ - data[3] = gspca_dev->width / 8; /* h_size , reg 2 */ - data[4] = gspca_dev->height / 8; /* v_size , reg 3 */ - data[5] = 0x30; /* reg 4, MI, PAS5101 : - * 0x30 for 24mhz , 0x28 for 12mhz */ - data[6] = 0x02; /* reg 5, H start - was 0x04 */ - data[7] = v4l2_ctrl_g_ctrl(sd->gamma) * 0x40; /* reg 0x06: gamma */ - data[8] = 0x01; /* reg 7, V start - was 0x03 */ -/* if (h_size == 320 ) */ -/* data[9]= 0x56; * reg 8, 24MHz, 2:1 scale down */ -/* else */ - data[9] = 0x52; /* reg 8, 24MHz, no scale down */ -/*jfm: from win trace*/ - data[10] = 0x18; - - reg_w(gspca_dev, 11); - - data[0] = 0x23; /* address */ - data[1] = 0x09; /* reg 35, append frame header */ - - reg_w(gspca_dev, 2); - - data[0] = 0x3c; /* address */ -/* if (gspca_dev->width == 1280) */ -/* data[1] = 200; * reg 60, pc-cam frame size - * (unit: 4KB) 800KB */ -/* else */ - data[1] = 50; /* 50 reg 60, pc-cam frame size - * (unit: 4KB) 200KB */ - reg_w(gspca_dev, 2); - - /* auto dark-gain */ - data[0] = 0x5e; /* address */ - data[1] = 0; /* reg 94, Y Gain (auto) */ -/*jfm: from win trace*/ - /* reg 0x5f/0x60 (LE) = saturation */ - /* h (60): xxxx x100 - * l (5f): xxxx x000 */ - data[2] = v4l2_ctrl_g_ctrl(sd->saturation) << 3; - data[3] = ((v4l2_ctrl_g_ctrl(sd->saturation) >> 2) & 0xf8) | 0x04; - data[4] = v4l2_ctrl_g_ctrl(sd->brightness); /* reg 0x61 = brightness */ - data[5] = 0x00; - - reg_w(gspca_dev, 6); - - data[0] = 0x67; -/*jfm: from win trace*/ - data[1] = v4l2_ctrl_g_ctrl(sd->sharpness) * 4 + 3; - data[2] = 0x14; - reg_w(gspca_dev, 3); - - data[0] = 0x69; - data[1] = 0x2f; - data[2] = 0x28; - data[3] = 0x42; - reg_w(gspca_dev, 4); - - data[0] = 0x63; - data[1] = 0x07; - reg_w(gspca_dev, 2); -/*jfm: win trace - many writes here to reg 0x64*/ - - /* initialize the MI sensor */ - for (i = 0; i < sizeof mi_data; i++) - mi_w(gspca_dev, i + 1, mi_data[i]); - - data[0] = 0x00; - data[1] = 0x4d; /* ISOC transferring enable... */ - reg_w(gspca_dev, 2); - - setilluminators(gspca_dev, v4l2_ctrl_g_ctrl(sd->illum_top), - v4l2_ctrl_g_ctrl(sd->illum_bottom)); - - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (v4l2_ctrl_g_ctrl(sd->illum_top) || - v4l2_ctrl_g_ctrl(sd->illum_bottom)) { - setilluminators(gspca_dev, false, false); - msleep(20); - } - - gspca_dev->usb_buf[0] = 1; - gspca_dev->usb_buf[1] = 0; - reg_w(gspca_dev, 2); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - int p; - - if (len < 6) { -/* gspca_dev->last_packet_type = DISCARD_PACKET; */ - return; - } - for (p = 0; p < len - 6; p++) { - if (data[0 + p] == 0xff - && data[1 + p] == 0xff - && data[2 + p] == 0x00 - && data[3 + p] == 0xff - && data[4 + p] == 0x96) { - if (data[5 + p] == 0x64 - || data[5 + p] == 0x65 - || data[5 + p] == 0x66 - || data[5 + p] == 0x67) { - PDEBUG(D_PACK, "sof offset: %d len: %d", - p, len); - gspca_frame_add(gspca_dev, LAST_PACKET, - data, p); - - /* put the JPEG header */ - gspca_frame_add(gspca_dev, FIRST_PACKET, - sd->jpeg_hdr, JPEG_HDR_SZ); - data += p + 16; - len -= p + 16; - break; - } - } - } - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x093a, 0x050f)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c deleted file mode 100644 index 8f4714df5990..000000000000 --- a/drivers/media/video/gspca/mr97310a.c +++ /dev/null @@ -1,1091 +0,0 @@ -/* - * Mars MR97310A library - * - * The original mr97310a driver, which supported the Aiptek Pencam VGA+, is - * Copyright (C) 2009 Kyle Guinn <elyk03@gmail.com> - * - * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+ - * and for the routines for detecting and classifying these various cameras, - * is Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu> - * - * Support for the control settings for the CIF cameras is - * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> and - * Thomas Kaiser <thomas@kaiser-linux.li> - * - * Support for the control settings for the VGA cameras is - * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu> - * - * Several previously unsupported cameras are owned and have been tested by - * Hans de Goede <hdegoede@redhat.com> and - * Thomas Kaiser <thomas@kaiser-linux.li> and - * Theodore Kilgore <kilgota@auburn.edu> and - * Edmond Rodriguez <erodrig_97@yahoo.com> and - * Aurelien Jacobs <aurel@gnuage.org> - * - * The MR97311A support in gspca/mars.c has been helpful in understanding some - * of the registers in these cameras. - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "mr97310a" - -#include "gspca.h" - -#define CAM_TYPE_CIF 0 -#define CAM_TYPE_VGA 1 - -#define MR97310A_BRIGHTNESS_DEFAULT 0 - -#define MR97310A_EXPOSURE_MIN 0 -#define MR97310A_EXPOSURE_MAX 4095 -#define MR97310A_EXPOSURE_DEFAULT 1000 - -#define MR97310A_GAIN_MIN 0 -#define MR97310A_GAIN_MAX 31 -#define MR97310A_GAIN_DEFAULT 25 - -#define MR97310A_CONTRAST_MIN 0 -#define MR97310A_CONTRAST_MAX 31 -#define MR97310A_CONTRAST_DEFAULT 23 - -#define MR97310A_CS_GAIN_MIN 0 -#define MR97310A_CS_GAIN_MAX 0x7ff -#define MR97310A_CS_GAIN_DEFAULT 0x110 - -#define MR97310A_CID_CLOCKDIV (V4L2_CTRL_CLASS_USER + 0x1000) -#define MR97310A_MIN_CLOCKDIV_MIN 3 -#define MR97310A_MIN_CLOCKDIV_MAX 8 -#define MR97310A_MIN_CLOCKDIV_DEFAULT 3 - -MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>," - "Theodore Kilgore <kilgota@auburn.edu>"); -MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* global parameters */ -static int force_sensor_type = -1; -module_param(force_sensor_type, int, 0644); -MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)"); - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - struct { /* exposure/min_clockdiv control cluster */ - struct v4l2_ctrl *exposure; - struct v4l2_ctrl *min_clockdiv; - }; - u8 sof_read; - u8 cam_type; /* 0 is CIF and 1 is VGA */ - u8 sensor_type; /* We use 0 and 1 here, too. */ - u8 do_lcd_stop; - u8 adj_colors; -}; - -struct sensor_w_data { - u8 reg; - u8 flags; - u8 data[16]; - int len; -}; - -static void sd_stopN(struct gspca_dev *gspca_dev); - -static const struct v4l2_pix_format vga_mode[] = { - {160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 4}, - {176, 144, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 3}, - {320, 240, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, - {352, 288, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; - -/* the bytes to write are in gspca_dev->usb_buf */ -static int mr_write(struct gspca_dev *gspca_dev, int len) -{ - int rc; - - rc = usb_bulk_msg(gspca_dev->dev, - usb_sndbulkpipe(gspca_dev->dev, 4), - gspca_dev->usb_buf, len, NULL, 500); - if (rc < 0) - pr_err("reg write [%02x] error %d\n", - gspca_dev->usb_buf[0], rc); - return rc; -} - -/* the bytes are read into gspca_dev->usb_buf */ -static int mr_read(struct gspca_dev *gspca_dev, int len) -{ - int rc; - - rc = usb_bulk_msg(gspca_dev->dev, - usb_rcvbulkpipe(gspca_dev->dev, 3), - gspca_dev->usb_buf, len, NULL, 500); - if (rc < 0) - pr_err("reg read [%02x] error %d\n", - gspca_dev->usb_buf[0], rc); - return rc; -} - -static int sensor_write_reg(struct gspca_dev *gspca_dev, u8 reg, u8 flags, - const u8 *data, int len) -{ - gspca_dev->usb_buf[0] = 0x1f; - gspca_dev->usb_buf[1] = flags; - gspca_dev->usb_buf[2] = reg; - memcpy(gspca_dev->usb_buf + 3, data, len); - - return mr_write(gspca_dev, len + 3); -} - -static int sensor_write_regs(struct gspca_dev *gspca_dev, - const struct sensor_w_data *data, int len) -{ - int i, rc; - - for (i = 0; i < len; i++) { - rc = sensor_write_reg(gspca_dev, data[i].reg, data[i].flags, - data[i].data, data[i].len); - if (rc < 0) - return rc; - } - - return 0; -} - -static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 buf, confirm_reg; - int rc; - - buf = data; - if (sd->cam_type == CAM_TYPE_CIF) { - rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1); - confirm_reg = sd->sensor_type ? 0x13 : 0x11; - } else { - rc = sensor_write_reg(gspca_dev, reg, 0x00, &buf, 1); - confirm_reg = 0x11; - } - if (rc < 0) - return rc; - - buf = 0x01; - rc = sensor_write_reg(gspca_dev, confirm_reg, 0x00, &buf, 1); - if (rc < 0) - return rc; - - return 0; -} - -static int cam_get_response16(struct gspca_dev *gspca_dev, u8 reg, int verbose) -{ - int err_code; - - gspca_dev->usb_buf[0] = reg; - err_code = mr_write(gspca_dev, 1); - if (err_code < 0) - return err_code; - - err_code = mr_read(gspca_dev, 16); - if (err_code < 0) - return err_code; - - if (verbose) - PDEBUG(D_PROBE, "Register: %02x reads %02x%02x%02x", reg, - gspca_dev->usb_buf[0], - gspca_dev->usb_buf[1], - gspca_dev->usb_buf[2]); - - return 0; -} - -static int zero_the_pointer(struct gspca_dev *gspca_dev) -{ - __u8 *data = gspca_dev->usb_buf; - int err_code; - u8 status = 0; - int tries = 0; - - err_code = cam_get_response16(gspca_dev, 0x21, 0); - if (err_code < 0) - return err_code; - - data[0] = 0x19; - data[1] = 0x51; - err_code = mr_write(gspca_dev, 2); - if (err_code < 0) - return err_code; - - err_code = cam_get_response16(gspca_dev, 0x21, 0); - if (err_code < 0) - return err_code; - - data[0] = 0x19; - data[1] = 0xba; - err_code = mr_write(gspca_dev, 2); - if (err_code < 0) - return err_code; - - err_code = cam_get_response16(gspca_dev, 0x21, 0); - if (err_code < 0) - return err_code; - - data[0] = 0x19; - data[1] = 0x00; - err_code = mr_write(gspca_dev, 2); - if (err_code < 0) - return err_code; - - err_code = cam_get_response16(gspca_dev, 0x21, 0); - if (err_code < 0) - return err_code; - - data[0] = 0x19; - data[1] = 0x00; - err_code = mr_write(gspca_dev, 2); - if (err_code < 0) - return err_code; - - while (status != 0x0a && tries < 256) { - err_code = cam_get_response16(gspca_dev, 0x21, 0); - status = data[0]; - tries++; - if (err_code < 0) - return err_code; - } - if (status != 0x0a) - PDEBUG(D_ERR, "status is %02x", status); - - tries = 0; - while (tries < 4) { - data[0] = 0x19; - data[1] = 0x00; - err_code = mr_write(gspca_dev, 2); - if (err_code < 0) - return err_code; - - err_code = cam_get_response16(gspca_dev, 0x21, 0); - status = data[0]; - tries++; - if (err_code < 0) - return err_code; - } - - data[0] = 0x19; - err_code = mr_write(gspca_dev, 1); - if (err_code < 0) - return err_code; - - err_code = mr_read(gspca_dev, 16); - if (err_code < 0) - return err_code; - - return 0; -} - -static int stream_start(struct gspca_dev *gspca_dev) -{ - gspca_dev->usb_buf[0] = 0x01; - gspca_dev->usb_buf[1] = 0x01; - return mr_write(gspca_dev, 2); -} - -static void stream_stop(struct gspca_dev *gspca_dev) -{ - gspca_dev->usb_buf[0] = 0x01; - gspca_dev->usb_buf[1] = 0x00; - if (mr_write(gspca_dev, 2) < 0) - PDEBUG(D_ERR, "Stream Stop failed"); -} - -static void lcd_stop(struct gspca_dev *gspca_dev) -{ - gspca_dev->usb_buf[0] = 0x19; - gspca_dev->usb_buf[1] = 0x54; - if (mr_write(gspca_dev, 2) < 0) - PDEBUG(D_ERR, "LCD Stop failed"); -} - -static int isoc_enable(struct gspca_dev *gspca_dev) -{ - gspca_dev->usb_buf[0] = 0x00; - gspca_dev->usb_buf[1] = 0x4d; /* ISOC transferring enable... */ - return mr_write(gspca_dev, 2); -} - -/* This function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - int err_code; - - cam = &gspca_dev->cam; - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - sd->do_lcd_stop = 0; - - /* Several of the supported CIF cameras share the same USB ID but - * require different initializations and different control settings. - * The same is true of the VGA cameras. Therefore, we are forced - * to start the initialization process in order to determine which - * camera is present. Some of the supported cameras require the - * memory pointer to be set to 0 as the very first item of business - * or else they will not stream. So we do that immediately. - */ - err_code = zero_the_pointer(gspca_dev); - if (err_code < 0) - return err_code; - - err_code = stream_start(gspca_dev); - if (err_code < 0) - return err_code; - - /* Now, the query for sensor type. */ - err_code = cam_get_response16(gspca_dev, 0x07, 1); - if (err_code < 0) - return err_code; - - if (id->idProduct == 0x0110 || id->idProduct == 0x010e) { - sd->cam_type = CAM_TYPE_CIF; - cam->nmodes--; - /* - * All but one of the known CIF cameras share the same USB ID, - * but two different init routines are in use, and the control - * settings are different, too. We need to detect which camera - * of the two known varieties is connected! - * - * A list of known CIF cameras follows. They all report either - * 0200 for type 0 or 0300 for type 1. - * If you have another to report, please do - * - * Name sd->sensor_type reported by - * - * Sakar 56379 Spy-shot 0 T. Kilgore - * Innovage 0 T. Kilgore - * Vivitar Mini 0 H. De Goede - * Vivitar Mini 0 E. Rodriguez - * Vivitar Mini 1 T. Kilgore - * Elta-Media 8212dc 1 T. Kaiser - * Philips dig. keych. 1 T. Kilgore - * Trust Spyc@m 100 1 A. Jacobs - */ - switch (gspca_dev->usb_buf[0]) { - case 2: - sd->sensor_type = 0; - break; - case 3: - sd->sensor_type = 1; - break; - default: - pr_err("Unknown CIF Sensor id : %02x\n", - gspca_dev->usb_buf[1]); - return -ENODEV; - } - PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d", - sd->sensor_type); - } else { - sd->cam_type = CAM_TYPE_VGA; - - /* - * Here is a table of the responses to the query for sensor - * type, from the known MR97310A VGA cameras. Six different - * cameras of which five share the same USB ID. - * - * Name gspca_dev->usb_buf[] sd->sensor_type - * sd->do_lcd_stop - * Aiptek Pencam VGA+ 0300 0 1 - * ION digital 0300 0 1 - * Argus DC-1620 0450 1 0 - * Argus QuickClix 0420 1 1 - * Sakar 77379 Digital 0350 0 1 - * Sakar 1638x CyberPix 0120 0 2 - * - * Based upon these results, we assume default settings - * and then correct as necessary, as follows. - * - */ - - sd->sensor_type = 1; - sd->do_lcd_stop = 0; - sd->adj_colors = 0; - if (gspca_dev->usb_buf[0] == 0x01) { - sd->sensor_type = 2; - } else if ((gspca_dev->usb_buf[0] != 0x03) && - (gspca_dev->usb_buf[0] != 0x04)) { - pr_err("Unknown VGA Sensor id Byte 0: %02x\n", - gspca_dev->usb_buf[0]); - pr_err("Defaults assumed, may not work\n"); - pr_err("Please report this\n"); - } - /* Sakar Digital color needs to be adjusted. */ - if ((gspca_dev->usb_buf[0] == 0x03) && - (gspca_dev->usb_buf[1] == 0x50)) - sd->adj_colors = 1; - if (gspca_dev->usb_buf[0] == 0x04) { - sd->do_lcd_stop = 1; - switch (gspca_dev->usb_buf[1]) { - case 0x50: - sd->sensor_type = 0; - PDEBUG(D_PROBE, "sensor_type corrected to 0"); - break; - case 0x20: - /* Nothing to do here. */ - break; - default: - pr_err("Unknown VGA Sensor id Byte 1: %02x\n", - gspca_dev->usb_buf[1]); - pr_err("Defaults assumed, may not work\n"); - pr_err("Please report this\n"); - } - } - PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d", - sd->sensor_type); - } - /* Stop streaming as we've started it only to probe the sensor type. */ - sd_stopN(gspca_dev); - - if (force_sensor_type != -1) { - sd->sensor_type = !!force_sensor_type; - PDEBUG(D_PROBE, "Forcing sensor type to: %d", - sd->sensor_type); - } - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - return 0; -} - -static int start_cif_cam(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - __u8 *data = gspca_dev->usb_buf; - int err_code; - static const __u8 startup_string[] = { - 0x00, - 0x0d, - 0x01, - 0x00, /* Hsize/8 for 352 or 320 */ - 0x00, /* Vsize/4 for 288 or 240 */ - 0x13, /* or 0xbb, depends on sensor */ - 0x00, /* Hstart, depends on res. */ - 0x00, /* reserved ? */ - 0x00, /* Vstart, depends on res. and sensor */ - 0x50, /* 0x54 to get 176 or 160 */ - 0xc0 - }; - - /* Note: Some of the above descriptions guessed from MR97113A driver */ - - memcpy(data, startup_string, 11); - if (sd->sensor_type) - data[5] = 0xbb; - - switch (gspca_dev->width) { - case 160: - data[9] |= 0x04; /* reg 8, 2:1 scale down from 320 */ - /* fall thru */ - case 320: - default: - data[3] = 0x28; /* reg 2, H size/8 */ - data[4] = 0x3c; /* reg 3, V size/4 */ - data[6] = 0x14; /* reg 5, H start */ - data[8] = 0x1a + sd->sensor_type; /* reg 7, V start */ - break; - case 176: - data[9] |= 0x04; /* reg 8, 2:1 scale down from 352 */ - /* fall thru */ - case 352: - data[3] = 0x2c; /* reg 2, H size/8 */ - data[4] = 0x48; /* reg 3, V size/4 */ - data[6] = 0x06; /* reg 5, H start */ - data[8] = 0x06 - sd->sensor_type; /* reg 7, V start */ - break; - } - err_code = mr_write(gspca_dev, 11); - if (err_code < 0) - return err_code; - - if (!sd->sensor_type) { - static const struct sensor_w_data cif_sensor0_init_data[] = { - {0x02, 0x00, {0x03, 0x5a, 0xb5, 0x01, - 0x0f, 0x14, 0x0f, 0x10}, 8}, - {0x0c, 0x00, {0x04, 0x01, 0x01, 0x00, 0x1f}, 5}, - {0x12, 0x00, {0x07}, 1}, - {0x1f, 0x00, {0x06}, 1}, - {0x27, 0x00, {0x04}, 1}, - {0x29, 0x00, {0x0c}, 1}, - {0x40, 0x00, {0x40, 0x00, 0x04}, 3}, - {0x50, 0x00, {0x60}, 1}, - {0x60, 0x00, {0x06}, 1}, - {0x6b, 0x00, {0x85, 0x85, 0xc8, 0xc8, 0xc8, 0xc8}, 6}, - {0x72, 0x00, {0x1e, 0x56}, 2}, - {0x75, 0x00, {0x58, 0x40, 0xa2, 0x02, 0x31, 0x02, - 0x31, 0x80, 0x00}, 9}, - {0x11, 0x00, {0x01}, 1}, - {0, 0, {0}, 0} - }; - err_code = sensor_write_regs(gspca_dev, cif_sensor0_init_data, - ARRAY_SIZE(cif_sensor0_init_data)); - } else { /* sd->sensor_type = 1 */ - static const struct sensor_w_data cif_sensor1_init_data[] = { - /* Reg 3,4, 7,8 get set by the controls */ - {0x02, 0x00, {0x10}, 1}, - {0x05, 0x01, {0x22}, 1}, /* 5/6 also seen as 65h/32h */ - {0x06, 0x01, {0x00}, 1}, - {0x09, 0x02, {0x0e}, 1}, - {0x0a, 0x02, {0x05}, 1}, - {0x0b, 0x02, {0x05}, 1}, - {0x0c, 0x02, {0x0f}, 1}, - {0x0d, 0x02, {0x07}, 1}, - {0x0e, 0x02, {0x0c}, 1}, - {0x0f, 0x00, {0x00}, 1}, - {0x10, 0x00, {0x06}, 1}, - {0x11, 0x00, {0x07}, 1}, - {0x12, 0x00, {0x00}, 1}, - {0x13, 0x00, {0x01}, 1}, - {0, 0, {0}, 0} - }; - /* Without this command the cam won't work with USB-UHCI */ - gspca_dev->usb_buf[0] = 0x0a; - gspca_dev->usb_buf[1] = 0x00; - err_code = mr_write(gspca_dev, 2); - if (err_code < 0) - return err_code; - err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data, - ARRAY_SIZE(cif_sensor1_init_data)); - } - return err_code; -} - -static int start_vga_cam(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - __u8 *data = gspca_dev->usb_buf; - int err_code; - static const __u8 startup_string[] = - {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b, 0x00, 0x00, - 0x00, 0x50, 0xc0}; - /* What some of these mean is explained in start_cif_cam(), above */ - - memcpy(data, startup_string, 11); - if (!sd->sensor_type) { - data[5] = 0x00; - data[10] = 0x91; - } - if (sd->sensor_type == 2) { - data[5] = 0x00; - data[10] = 0x18; - } - - switch (gspca_dev->width) { - case 160: - data[9] |= 0x0c; /* reg 8, 4:1 scale down */ - /* fall thru */ - case 320: - data[9] |= 0x04; /* reg 8, 2:1 scale down */ - /* fall thru */ - case 640: - default: - data[3] = 0x50; /* reg 2, H size/8 */ - data[4] = 0x78; /* reg 3, V size/4 */ - data[6] = 0x04; /* reg 5, H start */ - data[8] = 0x03; /* reg 7, V start */ - if (sd->sensor_type == 2) { - data[6] = 2; - data[8] = 1; - } - if (sd->do_lcd_stop) - data[8] = 0x04; /* Bayer tile shifted */ - break; - - case 176: - data[9] |= 0x04; /* reg 8, 2:1 scale down */ - /* fall thru */ - case 352: - data[3] = 0x2c; /* reg 2, H size */ - data[4] = 0x48; /* reg 3, V size */ - data[6] = 0x94; /* reg 5, H start */ - data[8] = 0x63; /* reg 7, V start */ - if (sd->do_lcd_stop) - data[8] = 0x64; /* Bayer tile shifted */ - break; - } - - err_code = mr_write(gspca_dev, 11); - if (err_code < 0) - return err_code; - - if (!sd->sensor_type) { - static const struct sensor_w_data vga_sensor0_init_data[] = { - {0x01, 0x00, {0x0c, 0x00, 0x04}, 3}, - {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4}, - {0x20, 0x00, {0x00, 0x80, 0x00, 0x08}, 4}, - {0x25, 0x00, {0x03, 0xa9, 0x80}, 3}, - {0x30, 0x00, {0x30, 0x18, 0x10, 0x18}, 4}, - {0, 0, {0}, 0} - }; - err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, - ARRAY_SIZE(vga_sensor0_init_data)); - } else if (sd->sensor_type == 1) { - static const struct sensor_w_data color_adj[] = { - {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, - /* adjusted blue, green, red gain correct - too much blue from the Sakar Digital */ - 0x05, 0x01, 0x04}, 8} - }; - - static const struct sensor_w_data color_no_adj[] = { - {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, - /* default blue, green, red gain settings */ - 0x07, 0x00, 0x01}, 8} - }; - - static const struct sensor_w_data vga_sensor1_init_data[] = { - {0x11, 0x04, {0x01}, 1}, - {0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01, - /* These settings may be better for some cameras */ - /* {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, */ - 0x00, 0x0a}, 7}, - {0x11, 0x04, {0x01}, 1}, - {0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6}, - {0x11, 0x04, {0x01}, 1}, - {0, 0, {0}, 0} - }; - - if (sd->adj_colors) - err_code = sensor_write_regs(gspca_dev, color_adj, - ARRAY_SIZE(color_adj)); - else - err_code = sensor_write_regs(gspca_dev, color_no_adj, - ARRAY_SIZE(color_no_adj)); - - if (err_code < 0) - return err_code; - - err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, - ARRAY_SIZE(vga_sensor1_init_data)); - } else { /* sensor type == 2 */ - static const struct sensor_w_data vga_sensor2_init_data[] = { - - {0x01, 0x00, {0x48}, 1}, - {0x02, 0x00, {0x22}, 1}, - /* Reg 3 msb and 4 is lsb of the exposure setting*/ - {0x05, 0x00, {0x10}, 1}, - {0x06, 0x00, {0x00}, 1}, - {0x07, 0x00, {0x00}, 1}, - {0x08, 0x00, {0x00}, 1}, - {0x09, 0x00, {0x00}, 1}, - /* The following are used in the gain control - * which is BTW completely borked in the OEM driver - * The values for each color go from 0 to 0x7ff - *{0x0a, 0x00, {0x01}, 1}, green1 gain msb - *{0x0b, 0x00, {0x10}, 1}, green1 gain lsb - *{0x0c, 0x00, {0x01}, 1}, red gain msb - *{0x0d, 0x00, {0x10}, 1}, red gain lsb - *{0x0e, 0x00, {0x01}, 1}, blue gain msb - *{0x0f, 0x00, {0x10}, 1}, blue gain lsb - *{0x10, 0x00, {0x01}, 1}, green2 gain msb - *{0x11, 0x00, {0x10}, 1}, green2 gain lsb - */ - {0x12, 0x00, {0x00}, 1}, - {0x13, 0x00, {0x04}, 1}, /* weird effect on colors */ - {0x14, 0x00, {0x00}, 1}, - {0x15, 0x00, {0x06}, 1}, - {0x16, 0x00, {0x01}, 1}, - {0x17, 0x00, {0xe2}, 1}, /* vertical alignment */ - {0x18, 0x00, {0x02}, 1}, - {0x19, 0x00, {0x82}, 1}, /* don't mess with */ - {0x1a, 0x00, {0x00}, 1}, - {0x1b, 0x00, {0x20}, 1}, - /* {0x1c, 0x00, {0x17}, 1}, contrast control */ - {0x1d, 0x00, {0x80}, 1}, /* moving causes a mess */ - {0x1e, 0x00, {0x08}, 1}, /* moving jams the camera */ - {0x1f, 0x00, {0x0c}, 1}, - {0x20, 0x00, {0x00}, 1}, - {0, 0, {0}, 0} - }; - err_code = sensor_write_regs(gspca_dev, vga_sensor2_init_data, - ARRAY_SIZE(vga_sensor2_init_data)); - } - return err_code; -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int err_code; - - sd->sof_read = 0; - - /* Some of the VGA cameras require the memory pointer - * to be set to 0 again. We have been forced to start the - * stream in sd_config() to detect the hardware, and closed it. - * Thus, we need here to do a completely fresh and clean start. */ - err_code = zero_the_pointer(gspca_dev); - if (err_code < 0) - return err_code; - - err_code = stream_start(gspca_dev); - if (err_code < 0) - return err_code; - - if (sd->cam_type == CAM_TYPE_CIF) { - err_code = start_cif_cam(gspca_dev); - } else { - err_code = start_vga_cam(gspca_dev); - } - if (err_code < 0) - return err_code; - - return isoc_enable(gspca_dev); -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - stream_stop(gspca_dev); - /* Not all the cams need this, but even if not, probably a good idea */ - zero_the_pointer(gspca_dev); - if (sd->do_lcd_stop) - lcd_stop(gspca_dev); -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 sign_reg = 7; /* This reg and the next one used on CIF cams. */ - u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */ - static const u8 quick_clix_table[] = - /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ - { 0, 4, 8, 12, 1, 2, 3, 5, 6, 9, 7, 10, 13, 11, 14, 15}; - if (sd->cam_type == CAM_TYPE_VGA) { - sign_reg += 4; - value_reg += 4; - } - - /* Note register 7 is also seen as 0x8x or 0xCx in some dumps */ - if (val > 0) { - sensor_write1(gspca_dev, sign_reg, 0x00); - } else { - sensor_write1(gspca_dev, sign_reg, 0x01); - val = 257 - val; - } - /* Use lookup table for funky Argus QuickClix brightness */ - if (sd->do_lcd_stop) - val = quick_clix_table[val]; - - sensor_write1(gspca_dev, value_reg, val); -} - -static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 min_clockdiv) -{ - struct sd *sd = (struct sd *) gspca_dev; - int exposure = MR97310A_EXPOSURE_DEFAULT; - u8 buf[2]; - - if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { - /* This cam does not like exposure settings < 300, - so scale 0 - 4095 to 300 - 4095 */ - exposure = (expo * 9267) / 10000 + 300; - sensor_write1(gspca_dev, 3, exposure >> 4); - sensor_write1(gspca_dev, 4, exposure & 0x0f); - } else if (sd->sensor_type == 2) { - exposure = expo; - exposure >>= 3; - sensor_write1(gspca_dev, 3, exposure >> 8); - sensor_write1(gspca_dev, 4, exposure & 0xff); - } else { - /* We have both a clock divider and an exposure register. - We first calculate the clock divider, as that determines - the maximum exposure and then we calculate the exposure - register setting (which goes from 0 - 511). - - Note our 0 - 4095 exposure is mapped to 0 - 511 - milliseconds exposure time */ - u8 clockdiv = (60 * expo + 7999) / 8000; - - /* Limit framerate to not exceed usb bandwidth */ - if (clockdiv < min_clockdiv && gspca_dev->width >= 320) - clockdiv = min_clockdiv; - else if (clockdiv < 2) - clockdiv = 2; - - if (sd->cam_type == CAM_TYPE_VGA && clockdiv < 4) - clockdiv = 4; - - /* Frame exposure time in ms = 1000 * clockdiv / 60 -> - exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */ - exposure = (60 * 511 * expo) / (8000 * clockdiv); - if (exposure > 511) - exposure = 511; - - /* exposure register value is reversed! */ - exposure = 511 - exposure; - - buf[0] = exposure & 0xff; - buf[1] = exposure >> 8; - sensor_write_reg(gspca_dev, 0x0e, 0, buf, 2); - sensor_write1(gspca_dev, 0x02, clockdiv); - } -} - -static void setgain(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 gainreg; - - if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) - sensor_write1(gspca_dev, 0x0e, val); - else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2) - for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) { - sensor_write1(gspca_dev, gainreg, val >> 8); - sensor_write1(gspca_dev, gainreg + 1, val & 0xff); - } - else - sensor_write1(gspca_dev, 0x10, val); -} - -static void setcontrast(struct gspca_dev *gspca_dev, s32 val) -{ - sensor_write1(gspca_dev, 0x1c, val); -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_CONTRAST: - setcontrast(gspca_dev, ctrl->val); - break; - case V4L2_CID_EXPOSURE: - setexposure(gspca_dev, sd->exposure->val, - sd->min_clockdiv ? sd->min_clockdiv->val : 0); - break; - case V4L2_CID_GAIN: - setgain(gspca_dev, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - static const struct v4l2_ctrl_config clockdiv = { - .ops = &sd_ctrl_ops, - .id = MR97310A_CID_CLOCKDIV, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Minimum Clock Divider", - .min = MR97310A_MIN_CLOCKDIV_MIN, - .max = MR97310A_MIN_CLOCKDIV_MAX, - .step = 1, - .def = MR97310A_MIN_CLOCKDIV_DEFAULT, - }; - bool has_brightness = false; - bool has_argus_brightness = false; - bool has_contrast = false; - bool has_gain = false; - bool has_cs_gain = false; - bool has_exposure = false; - bool has_clockdiv = false; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 4); - - /* Setup controls depending on camera type */ - if (sd->cam_type == CAM_TYPE_CIF) { - /* No brightness for sensor_type 0 */ - if (sd->sensor_type == 0) - has_exposure = has_gain = has_clockdiv = true; - else - has_exposure = has_gain = has_brightness = true; - } else { - /* All controls need to be disabled if VGA sensor_type is 0 */ - if (sd->sensor_type == 0) - ; /* no controls! */ - else if (sd->sensor_type == 2) - has_exposure = has_cs_gain = has_contrast = true; - else if (sd->do_lcd_stop) - has_exposure = has_gain = has_argus_brightness = - has_clockdiv = true; - else - has_exposure = has_gain = has_brightness = - has_clockdiv = true; - } - - /* Separate brightness control description for Argus QuickClix as it has - * different limits from the other mr97310a cameras, and separate gain - * control for Sakar CyberPix camera. */ - /* - * This control is disabled for CIF type 1 and VGA type 0 cameras. - * It does not quite act linearly for the Argus QuickClix camera, - * but it does control brightness. The values are 0 - 15 only, and - * the table above makes them act consecutively. - */ - if (has_brightness) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, -254, 255, 1, - MR97310A_BRIGHTNESS_DEFAULT); - else if (has_argus_brightness) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 15, 1, - MR97310A_BRIGHTNESS_DEFAULT); - if (has_contrast) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, MR97310A_CONTRAST_MIN, - MR97310A_CONTRAST_MAX, 1, MR97310A_CONTRAST_DEFAULT); - if (has_gain) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, MR97310A_GAIN_MIN, MR97310A_GAIN_MAX, - 1, MR97310A_GAIN_DEFAULT); - else if (has_cs_gain) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_GAIN, - MR97310A_CS_GAIN_MIN, MR97310A_CS_GAIN_MAX, - 1, MR97310A_CS_GAIN_DEFAULT); - if (has_exposure) - sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, MR97310A_EXPOSURE_MIN, - MR97310A_EXPOSURE_MAX, 1, MR97310A_EXPOSURE_DEFAULT); - if (has_clockdiv) - sd->min_clockdiv = v4l2_ctrl_new_custom(hdl, &clockdiv, NULL); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - if (has_exposure && has_clockdiv) - v4l2_ctrl_cluster(2, &sd->exposure); - return 0; -} - -/* Include pac common sof detection functions */ -#include "pac_common.h" - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - unsigned char *sof; - - sof = pac_find_sof(&sd->sof_read, data, len); - if (sof) { - int n; - - /* finish decoding current frame */ - n = sof - data; - if (n > sizeof pac_sof_marker) - n -= sizeof pac_sof_marker; - else - n = 0; - gspca_frame_add(gspca_dev, LAST_PACKET, - data, n); - /* Start next frame. */ - gspca_frame_add(gspca_dev, FIRST_PACKET, - pac_sof_marker, sizeof pac_sof_marker); - len -= sof - data; - data = sof; - } - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x08ca, 0x0110)}, /* Trust Spyc@m 100 */ - {USB_DEVICE(0x08ca, 0x0111)}, /* Aiptek Pencam VGA+ */ - {USB_DEVICE(0x093a, 0x010f)}, /* All other known MR97310A VGA cams */ - {USB_DEVICE(0x093a, 0x010e)}, /* All known MR97310A CIF cams */ - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/nw80x.c b/drivers/media/video/gspca/nw80x.c deleted file mode 100644 index 44c9964b1b3e..000000000000 --- a/drivers/media/video/gspca/nw80x.c +++ /dev/null @@ -1,2110 +0,0 @@ -/* - * DivIO nw80x subdriver - * - * Copyright (C) 2011 Jean-François Moine (http://moinejf.free.fr) - * Copyright (C) 2003 Sylvain Munaut <tnt@246tNt.com> - * Kjell Claesson <keyson@users.sourceforge.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "nw80x" - -#include "gspca.h" - -MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); -MODULE_DESCRIPTION("NW80x USB Camera Driver"); -MODULE_LICENSE("GPL"); - -static int webcam; - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - u32 ae_res; - s8 ag_cnt; -#define AG_CNT_START 13 - u8 exp_too_low_cnt; - u8 exp_too_high_cnt; - - u8 bridge; - u8 webcam; -}; - -enum bridges { - BRIDGE_NW800, /* and et31x110 */ - BRIDGE_NW801, - BRIDGE_NW802, -}; -enum webcams { - Generic800, - SpaceCam, /* Trust 120 SpaceCam */ - SpaceCam2, /* other Trust 120 SpaceCam */ - Cvideopro, /* Conceptronic Video Pro */ - Dlink350c, - DS3303u, - Kr651us, - Kritter, - Mustek300, - Proscope, - Twinkle, - DvcV6, - P35u, - Generic802, - NWEBCAMS /* number of webcams */ -}; - -static const u8 webcam_chip[NWEBCAMS] = { - [Generic800] = BRIDGE_NW800, /* 06a5:0000 - * Typhoon Webcam 100 USB */ - - [SpaceCam] = BRIDGE_NW800, /* 06a5:d800 - * Trust SpaceCam120 or SpaceCam100 PORTABLE */ - - [SpaceCam2] = BRIDGE_NW800, /* 06a5:d800 - pas106 - * other Trust SpaceCam120 or SpaceCam100 PORTABLE */ - - [Cvideopro] = BRIDGE_NW802, /* 06a5:d001 - * Conceptronic Video Pro 'CVIDEOPRO USB Webcam CCD' */ - - [Dlink350c] = BRIDGE_NW802, /* 06a5:d001 - * D-Link NetQam Pro 250plus */ - - [DS3303u] = BRIDGE_NW801, /* 06a5:d001 - * Plustek Opticam 500U or ProLink DS3303u */ - - [Kr651us] = BRIDGE_NW802, /* 06a5:d001 - * Panasonic GP-KR651US */ - - [Kritter] = BRIDGE_NW802, /* 06a5:d001 - * iRez Kritter cam */ - - [Mustek300] = BRIDGE_NW802, /* 055f:d001 - * Mustek Wcam 300 mini */ - - [Proscope] = BRIDGE_NW802, /* 06a5:d001 - * Scalar USB Microscope (ProScope) */ - - [Twinkle] = BRIDGE_NW800, /* 06a5:d800 - hv7121b? (seems pas106) - * Divio Chicony TwinkleCam - * DSB-C110 */ - - [DvcV6] = BRIDGE_NW802, /* 0502:d001 - * DVC V6 */ - - [P35u] = BRIDGE_NW801, /* 052b:d001, 06a5:d001 and 06be:d001 - * EZCam Pro p35u */ - - [Generic802] = BRIDGE_NW802, -}; -/* - * other webcams: - * - nw801 046d:d001 - * Logitech QuickCam Pro (dark focus ring) - * - nw801 0728:d001 - * AVerMedia Camguard - * - nw??? 06a5:d001 - * D-Link NetQam Pro 250plus - * - nw800 065a:d800 - * Showcam NGS webcam - * - nw??? ????:???? - * Sceptre svc300 - */ - -/* - * registers - * nw800/et31x110 nw801 nw802 - * 0000..009e 0000..00a1 0000..009e - * 0200..0211 id id - * 0300..0302 id id - * 0400..0406 (inex) 0400..0406 - * 0500..0505 0500..0506 (inex) - * 0600..061a 0600..0601 0600..0601 - * 0800..0814 id id - * 1000..109c 1000..10a1 1000..109a - */ - -/* resolutions - * nw800: 320x240, 352x288 - * nw801/802: 320x240, 640x480 - */ -static const struct v4l2_pix_format cif_mode[] = { - {320, 240, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 4 / 8, - .colorspace = V4L2_COLORSPACE_JPEG}, - {352, 288, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 4 / 8, - .colorspace = V4L2_COLORSPACE_JPEG} -}; -static const struct v4l2_pix_format vga_mode[] = { - {320, 240, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 4 / 8, - .colorspace = V4L2_COLORSPACE_JPEG}, - {640, 480, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8, - .colorspace = V4L2_COLORSPACE_JPEG}, -}; - -/* - * The sequences below contain: - * - 1st and 2nd bytes: either - * - register number (BE) - * - I2C0 + i2c address - * - 3rd byte: data length (=0 for end of sequence) - * - n bytes: data - */ -#define I2C0 0xff - -static const u8 nw800_init[] = { - 0x04, 0x05, 0x01, 0x61, - 0x04, 0x04, 0x01, 0x01, - 0x04, 0x06, 0x01, 0x04, - 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, - 0x05, 0x05, 0x01, 0x00, - 0, 0, 0 -}; -static const u8 nw800_start[] = { - 0x04, 0x06, 0x01, 0xc0, - 0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f, - 0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24, - 0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, - 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, - 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, - 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, - 0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08, - 0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04, - 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00, - 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, - 0x40, 0x20, - 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0xc0, - 0x05, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x20, - 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, - 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, - 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, - 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, - 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, - 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, - 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, - 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, - 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, - 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, - 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62, - 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20, - 0x01, 0x60, 0x01, 0x00, 0x00, - - 0x04, 0x04, 0x01, 0xff, - 0x04, 0x06, 0x01, 0xc4, - - 0x04, 0x06, 0x01, 0xc0, - 0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f, - 0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24, - 0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, - 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, - 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, - 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, - 0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08, - 0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04, - 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00, - 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, - 0x40, 0x20, - 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0xc0, - 0x05, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x20, - 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, - 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, - 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, - 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, - 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, - 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, - 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, - 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, - 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, - 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, - 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62, - 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20, - 0x01, 0x60, 0x01, 0x00, 0x00, - - 0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00, - 0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65, - 0x40, - 0x00, 0x80, 0x01, 0xa0, - 0x10, 0x1a, 0x01, 0x00, - 0x00, 0x91, 0x02, 0x6c, 0x01, - 0x00, 0x03, 0x02, 0xc8, 0x01, - 0x10, 0x1a, 0x01, 0x00, - 0x10, 0x00, 0x01, 0x83, - 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, - 0x20, 0x01, 0x60, 0x01, - 0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01, - 0x10, 0x1b, 0x02, 0x69, 0x00, - 0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01, - 0x05, 0x02, 0x01, 0x02, - 0x06, 0x00, 0x02, 0x04, 0xd9, - 0x05, 0x05, 0x01, 0x20, - 0x05, 0x05, 0x01, 0x21, - 0x10, 0x0e, 0x01, 0x08, - 0x10, 0x41, 0x11, 0x00, 0x08, 0x21, 0x3d, 0x52, 0x63, 0x75, 0x83, - 0x91, 0x9e, 0xaa, 0xb6, 0xc1, 0xcc, 0xd6, 0xe0, - 0xea, - 0x10, 0x03, 0x01, 0x00, - 0x10, 0x0f, 0x02, 0x13, 0x13, - 0x10, 0x03, 0x01, 0x14, - 0x10, 0x41, 0x11, 0x00, 0x08, 0x21, 0x3d, 0x52, 0x63, 0x75, 0x83, - 0x91, 0x9e, 0xaa, 0xb6, 0xc1, 0xcc, 0xd6, 0xe0, - 0xea, - 0x10, 0x0b, 0x01, 0x14, - 0x10, 0x0d, 0x01, 0x20, - 0x10, 0x0c, 0x01, 0x34, - 0x04, 0x06, 0x01, 0xc3, - 0x04, 0x04, 0x01, 0x00, - 0x05, 0x02, 0x01, 0x02, - 0x06, 0x00, 0x02, 0x00, 0x48, - 0x05, 0x05, 0x01, 0x20, - 0x05, 0x05, 0x01, 0x21, - 0, 0, 0 -}; - -/* 06a5:d001 - nw801 - Panasonic - * P35u */ -static const u8 nw801_start_1[] = { - 0x05, 0x06, 0x01, 0x04, - 0x00, 0x00, 0x40, 0x0e, 0x00, 0x00, 0xf9, 0x02, 0x11, 0x00, 0x0e, - 0x01, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4, - 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, - 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, - 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, - 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, - 0x00, 0x80, 0x22, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x08, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x69, 0xa8, 0x1f, 0x00, - 0x0d, 0x02, 0x07, 0x00, 0x01, 0x00, 0x19, 0x00, - 0xf2, 0x00, 0x18, 0x06, 0x10, 0x06, 0x10, 0x00, - 0x36, 0x00, - 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, - 0x40, 0x20, - 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x02, 0x09, 0x99, - 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x40, 0x22, 0x02, 0x80, 0x00, 0x1e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x15, 0x08, 0x08, 0x0a, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x35, 0xfd, 0x07, 0x3d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x14, 0x02, - 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x06, - 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, 0xf7, - 0x10, 0x40, 0x40, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, 0x80, - 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, 0xa4, - 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, 0xcf, - 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64, - 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2, - 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, - 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, - 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, - 0x10, 0x80, 0x22, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, - 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x82, 0x02, - 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, 0x01, - 0xf0, 0x00, - 0, 0, 0, -}; -static const u8 nw801_start_qvga[] = { - 0x02, 0x00, 0x10, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00, - 0x00, 0x78, 0x18, 0x0b, 0x06, 0xa2, 0x86, 0x78, - 0x02, 0x0f, 0x01, 0x6b, - 0x10, 0x1a, 0x01, 0x15, - 0x00, 0x00, 0x01, 0x1e, - 0x10, 0x00, 0x01, 0x2f, - 0x10, 0x8c, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, - 0x10, 0x11, 0x08, 0x29, 0x00, 0x18, 0x01, 0x1f, 0x00, 0xd2, 0x00, - /* AE window */ - 0, 0, 0, -}; -static const u8 nw801_start_vga[] = { - 0x02, 0x00, 0x10, 0x78, 0xa0, 0x97, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xf0, - 0x02, 0x0f, 0x01, 0xd5, - 0x10, 0x1a, 0x01, 0x15, - 0x00, 0x00, 0x01, 0x0e, - 0x10, 0x00, 0x01, 0x22, - 0x10, 0x8c, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01, - 0x10, 0x11, 0x08, 0x51, 0x00, 0x30, 0x02, 0x3d, 0x00, 0xa4, 0x01, - 0, 0, 0, -}; -static const u8 nw801_start_2[] = { - 0x10, 0x04, 0x01, 0x1a, - 0x10, 0x19, 0x01, 0x09, /* clock */ - 0x10, 0x24, 0x06, 0xc0, 0x00, 0x3f, 0x02, 0x00, 0x01, - /* .. gain .. */ - 0x00, 0x03, 0x02, 0x92, 0x03, - 0x00, 0x1d, 0x04, 0xf2, 0x00, 0x24, 0x07, - 0x00, 0x7b, 0x01, 0xcf, - 0x10, 0x94, 0x01, 0x07, - 0x05, 0x05, 0x01, 0x01, - 0x05, 0x04, 0x01, 0x01, - 0x10, 0x0e, 0x01, 0x08, - 0x10, 0x48, 0x11, 0x00, 0x37, 0x55, 0x6b, 0x7d, 0x8d, 0x9b, 0xa8, - 0xb4, 0xbf, 0xca, 0xd4, 0xdd, 0xe6, 0xef, 0xf0, - 0xf0, - 0x10, 0x03, 0x01, 0x00, - 0x10, 0x0f, 0x02, 0x0c, 0x0c, - 0x10, 0x03, 0x01, 0x08, - 0x10, 0x48, 0x11, 0x00, 0x37, 0x55, 0x6b, 0x7d, 0x8d, 0x9b, 0xa8, - 0xb4, 0xbf, 0xca, 0xd4, 0xdd, 0xe6, 0xef, 0xf0, - 0xf0, - 0x10, 0x0b, 0x01, 0x0b, - 0x10, 0x0d, 0x01, 0x0b, - 0x10, 0x0c, 0x01, 0x1f, - 0x05, 0x06, 0x01, 0x03, - 0, 0, 0 -}; - -/* nw802 (sharp IR3Y38M?) */ -static const u8 nw802_start[] = { - 0x04, 0x06, 0x01, 0x04, - 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0xf9, 0x02, 0x10, 0x00, 0x4d, - 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4, - 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, - 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, - 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, - 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, - 0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11, - 0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94, - 0x00, 0x10, 0x06, 0x08, 0x00, 0x18, 0x00, - 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, - 0x40, 0x20, - 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00, - 0x06, 0x00, 0x02, 0x09, 0x99, - 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x1d, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x13, 0xff, 0x01, 0xc0, 0x00, 0x14, - 0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, - 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, - 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, - 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, - 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, - 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, - 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, - 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, - 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, - 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, - 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x05, 0x82, - 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, - 0x01, 0xf0, 0x00, - 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00, - 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78, - 0x40, - 0x10, 0x1a, 0x01, 0x00, - 0x10, 0x00, 0x01, 0xad, - 0x00, 0x00, 0x01, 0x08, - 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, - 0x10, 0x1b, 0x02, 0x00, 0x00, - 0x10, 0x11, 0x08, 0x51, 0x00, 0xf0, 0x00, 0x3d, 0x00, 0xb4, 0x00, - 0x10, 0x1d, 0x08, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, - 0x10, 0x0e, 0x01, 0x27, - 0x10, 0x41, 0x11, 0x00, 0x0e, 0x35, 0x4f, 0x62, 0x71, 0x7f, 0x8b, - 0x96, 0xa0, 0xa9, 0xb2, 0xbb, 0xc3, 0xca, 0xd2, - 0xd8, - 0x10, 0x03, 0x01, 0x00, - 0x10, 0x0f, 0x02, 0x14, 0x14, - 0x10, 0x03, 0x01, 0x0c, - 0x10, 0x41, 0x11, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64, 0x74, - 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2, 0xf1, - 0xff, -/* 0x00, 0x0e, 0x35, 0x4f, 0x62, 0x71, 0x7f, 0x8b, - * 0x96, 0xa0, 0xa9, 0xb2, 0xbb, 0xc3, 0xca, 0xd2, - * 0xd8, */ - 0x10, 0x0b, 0x01, 0x10, - 0x10, 0x0d, 0x01, 0x11, - 0x10, 0x0c, 0x01, 0x1c, - 0x04, 0x06, 0x01, 0x03, - 0x04, 0x04, 0x01, 0x00, - 0, 0, 0 -}; -/* et31x110 - Trust 120 SpaceCam */ -static const u8 spacecam_init[] = { - 0x04, 0x05, 0x01, 0x01, - 0x04, 0x04, 0x01, 0x01, - 0x04, 0x06, 0x01, 0x04, - 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, - 0x05, 0x05, 0x01, 0x00, - 0, 0, 0 -}; -static const u8 spacecam_start[] = { - 0x04, 0x06, 0x01, 0x44, - 0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f, - 0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24, - 0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, - 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, - 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, - 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, - 0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08, - 0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04, - 0x00, 0x4b, 0x00, 0x7c, 0x00, 0x80, 0x00, - 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, - 0x40, 0x20, - 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, - 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, - 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, - 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, - 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, - 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, - 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, - 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, - 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, - 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, - 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62, - 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20, - 0x01, 0x60, 0x01, 0x00, 0x00, - 0x04, 0x06, 0x01, 0xc0, - 0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01, - 0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00, - 0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65, - 0x40, - 0x00, 0x80, 0x01, 0xa0, - 0x10, 0x1a, 0x01, 0x00, - 0x00, 0x91, 0x02, 0x32, 0x01, - 0x00, 0x03, 0x02, 0x08, 0x02, - 0x10, 0x00, 0x01, 0x83, - 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, - 0x20, 0x01, 0x60, 0x01, - 0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01, - 0x10, 0x0e, 0x01, 0x08, - 0x10, 0x41, 0x11, 0x00, 0x64, 0x99, 0xc0, 0xe2, 0xf9, 0xf9, 0xf9, - 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, - 0xf9, - 0x10, 0x03, 0x01, 0x00, - 0x10, 0x0f, 0x02, 0x13, 0x13, - 0x10, 0x03, 0x01, 0x06, - 0x10, 0x41, 0x11, 0x00, 0x64, 0x99, 0xc0, 0xe2, 0xf9, 0xf9, 0xf9, - 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, - 0xf9, - 0x10, 0x0b, 0x01, 0x08, - 0x10, 0x0d, 0x01, 0x10, - 0x10, 0x0c, 0x01, 0x1f, - 0x04, 0x06, 0x01, 0xc3, - 0x04, 0x05, 0x01, 0x40, - 0x04, 0x04, 0x01, 0x40, - 0, 0, 0 -}; -/* et31x110 - pas106 - other Trust SpaceCam120 */ -static const u8 spacecam2_start[] = { - 0x04, 0x06, 0x01, 0x44, - 0x04, 0x06, 0x01, 0x00, - 0x00, 0x00, 0x40, 0x14, 0x83, 0x00, 0xba, 0x01, 0x10, 0x00, 0x4f, - 0xef, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x06, 0x00, 0xfc, - 0x01, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, - 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, - 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, - 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, - 0x00, 0x80, 0x1f, 0xb8, 0x48, 0x0f, 0x04, 0x88, 0x14, 0x68, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x03, - 0x00, 0x24, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04, - 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00, - 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, - 0x40, 0x20, - 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00, - 0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x40, 0x80, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, - 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, - 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, - 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, - 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, - 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, - 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, - 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, - 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, - 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, - 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62, - 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20, - 0x01, 0x60, 0x01, 0x00, 0x00, - 0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01, - 0x04, 0x04, 0x01, 0x40, - 0x04, 0x04, 0x01, 0x00, - I2C0, 0x40, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x05, - I2C0, 0x40, 0x02, 0x11, 0x06, - I2C0, 0x40, 0x02, 0x14, 0x00, - I2C0, 0x40, 0x02, 0x13, 0x01, /* i2c end */ - 0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00, - 0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65, - 0x40, - I2C0, 0x40, 0x02, 0x02, 0x0c, /* pixel clock */ - I2C0, 0x40, 0x02, 0x0f, 0x00, - I2C0, 0x40, 0x02, 0x13, 0x01, /* i2c end */ - 0x10, 0x00, 0x01, 0x01, - 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, - 0x20, 0x01, 0x60, 0x01, - I2C0, 0x40, 0x02, 0x05, 0x0f, /* exposure */ - I2C0, 0x40, 0x02, 0x13, 0x01, /* i2c end */ - I2C0, 0x40, 0x07, 0x09, 0x0b, 0x0f, 0x05, 0x05, 0x0f, 0x00, - /* gains */ - I2C0, 0x40, 0x03, 0x12, 0x04, 0x01, - 0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01, - 0x10, 0x0e, 0x01, 0x08, - 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7, - 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7, - 0xf9, - 0x10, 0x03, 0x01, 0x00, - 0x10, 0x0f, 0x02, 0x13, 0x13, - 0x10, 0x03, 0x01, 0x06, - 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7, - 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7, - 0xf9, - 0x10, 0x0b, 0x01, 0x11, - 0x10, 0x0d, 0x01, 0x10, - 0x10, 0x0c, 0x01, 0x14, - 0x04, 0x06, 0x01, 0x03, - 0x04, 0x05, 0x01, 0x61, - 0x04, 0x04, 0x01, 0x00, - 0, 0, 0 -}; - -/* nw802 - Conceptronic Video Pro */ -static const u8 cvideopro_start[] = { - 0x04, 0x06, 0x01, 0x04, - 0x00, 0x00, 0x40, 0x54, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x4c, - 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4, - 0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54, - 0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, - 0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30, - 0x00, 0x80, 0x1f, 0x98, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f, - 0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11, - 0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94, - 0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00, - 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, - 0x40, 0x20, - 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00, - 0x06, 0x00, 0x02, 0x09, 0x99, - 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c, - 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, - 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, - 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, - 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, - 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, - 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, - 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, - 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, - 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, - 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, - 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82, - 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, - 0x01, 0xf0, 0x00, - 0x02, 0x00, 0x11, 0x3c, 0x50, 0x8c, 0x3c, 0x50, 0x00, 0x00, 0x00, - 0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0, - 0x40, - 0x10, 0x1a, 0x01, 0x03, - 0x10, 0x00, 0x01, 0xac, - 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, - 0x10, 0x1b, 0x02, 0x3b, 0x01, - 0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00, - 0x10, 0x1f, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00, - 0x10, 0x1d, 0x02, 0x40, 0x06, - 0x10, 0x0e, 0x01, 0x08, - 0x10, 0x41, 0x11, 0x00, 0x0f, 0x46, 0x62, 0x76, 0x86, 0x94, 0xa0, - 0xab, 0xb6, 0xbf, 0xc8, 0xcf, 0xd7, 0xdc, 0xdc, - 0xdc, - 0x10, 0x03, 0x01, 0x00, - 0x10, 0x0f, 0x02, 0x12, 0x12, - 0x10, 0x03, 0x01, 0x0c, - 0x10, 0x41, 0x11, 0x00, 0x0f, 0x46, 0x62, 0x76, 0x86, 0x94, 0xa0, - 0xab, 0xb6, 0xbf, 0xc8, 0xcf, 0xd7, 0xdc, 0xdc, - 0xdc, - 0x10, 0x0b, 0x01, 0x09, - 0x10, 0x0d, 0x01, 0x10, - 0x10, 0x0c, 0x01, 0x2f, - 0x04, 0x06, 0x01, 0x03, - 0x04, 0x04, 0x01, 0x00, - 0, 0, 0 -}; - -/* nw802 - D-link dru-350c cam */ -static const u8 dlink_start[] = { - 0x04, 0x06, 0x01, 0x04, - 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x92, 0x03, 0x10, 0x00, 0x4d, - 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4, - 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, - 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, - 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, - 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, - 0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11, - 0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94, - 0x00, 0x10, 0x06, 0x10, 0x00, 0x36, 0x00, - 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, - 0x40, 0x20, - 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00, - 0x06, 0x00, 0x02, 0x09, 0x99, - 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x13, 0x00, 0x00, 0xc0, 0x00, 0x14, - 0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, - 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, - 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, - 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, - 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, - 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, - 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, - 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, - 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, - 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, - 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x01, 0x82, - 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, - 0x01, 0xf0, 0x00, - 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00, - 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78, - 0x40, - 0x10, 0x1a, 0x01, 0x00, - 0x10, 0x00, 0x01, 0xad, - 0x00, 0x00, 0x01, 0x08, - 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, - 0x10, 0x1b, 0x02, 0x00, 0x00, - 0x10, 0x11, 0x08, 0x51, 0x00, 0xf0, 0x00, 0x3d, 0x00, 0xb4, 0x00, - 0x10, 0x1d, 0x08, 0x40, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00, - 0x10, 0x0e, 0x01, 0x20, - 0x10, 0x41, 0x11, 0x00, 0x07, 0x1e, 0x38, 0x4d, 0x60, 0x70, 0x7f, - 0x8e, 0x9b, 0xa8, 0xb4, 0xbf, 0xca, 0xd5, 0xdf, - 0xea, - 0x10, 0x03, 0x01, 0x00, - 0x10, 0x0f, 0x02, 0x11, 0x11, - 0x10, 0x03, 0x01, 0x10, - 0x10, 0x41, 0x11, 0x00, 0x07, 0x1e, 0x38, 0x4d, 0x60, 0x70, 0x7f, - 0x8e, 0x9b, 0xa8, 0xb4, 0xbf, 0xca, 0xd5, 0xdf, - 0xea, - 0x10, 0x0b, 0x01, 0x19, - 0x10, 0x0d, 0x01, 0x10, - 0x10, 0x0c, 0x01, 0x1e, - 0x04, 0x06, 0x01, 0x03, - 0x04, 0x04, 0x01, 0x00, - 0, 0, 0 -}; - -/* 06a5:d001 - nw801 - Sony - * Plustek Opticam 500U or ProLink DS3303u (Hitachi HD49322BF) */ -/*fixme: 320x240 only*/ -static const u8 ds3303_start[] = { - 0x05, 0x06, 0x01, 0x04, - 0x00, 0x00, 0x40, 0x16, 0x00, 0x00, 0xf9, 0x02, 0x11, 0x00, 0x0e, - 0x01, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4, - 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, - 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, - 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, - 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, - 0x00, 0x80, 0x22, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x08, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa9, 0xa8, 0x1f, 0x00, - 0x0d, 0x02, 0x07, 0x00, 0x01, 0x00, 0x19, 0x00, - 0xf2, 0x00, 0x18, 0x06, 0x10, 0x06, 0x10, 0x00, - 0x36, 0x00, - 0x02, 0x00, 0x12, 0x03, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0x50, - 0x40, 0x20, - 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, - 0x05, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00, - 0x06, 0x00, 0x02, 0x09, 0x99, - 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x40, 0x2f, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x1f, 0x10, 0x08, 0x0a, - 0x0a, 0x51, 0x00, 0xf1, 0x00, 0x3c, 0x00, 0xb4, - 0x00, 0x01, 0x15, 0xfd, 0x07, 0x3d, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x8c, 0x04, 0x01, 0x20, - 0x02, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, 0xf7, - 0x10, 0x40, 0x40, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, 0x80, - 0x00, 0x2d, 0x46, 0x58, 0x67, 0x74, 0x7f, 0x88, - 0x94, 0x9d, 0xa6, 0xae, 0xb5, 0xbd, 0xc4, 0xcb, - 0xd1, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64, - 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2, - 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, - 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, - 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, - 0x10, 0x80, 0x22, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, - 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x3f, 0x01, - 0x00, 0x00, 0xef, 0x00, 0x02, 0x0a, 0x82, 0x02, - 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, 0x01, - 0xf0, 0x00, - - 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00, - 0x00, 0x78, 0x3f, 0x3f, 0x00, 0xf2, 0x8f, 0x81, - 0x40, - 0x10, 0x1a, 0x01, 0x15, - 0x10, 0x00, 0x01, 0x2f, - 0x10, 0x8c, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, - 0x10, 0x1b, 0x02, 0x00, 0x00, - 0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00, - 0x10, 0x26, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00, - 0x10, 0x24, 0x02, 0x40, 0x06, - 0x10, 0x0e, 0x01, 0x08, - 0x10, 0x48, 0x11, 0x00, 0x15, 0x40, 0x67, 0x84, 0x9d, 0xb2, 0xc6, - 0xd6, 0xe7, 0xf6, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, - 0xf9, - 0x10, 0x03, 0x01, 0x00, - 0x10, 0x0f, 0x02, 0x16, 0x16, - 0x10, 0x03, 0x01, 0x0c, - 0x10, 0x48, 0x11, 0x00, 0x15, 0x40, 0x67, 0x84, 0x9d, 0xb2, 0xc6, - 0xd6, 0xe7, 0xf6, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, - 0xf9, - 0x10, 0x0b, 0x01, 0x26, - 0x10, 0x0d, 0x01, 0x10, - 0x10, 0x0c, 0x01, 0x1c, - 0x05, 0x06, 0x01, 0x03, - 0x05, 0x04, 0x01, 0x00, - 0, 0, 0 -}; - -/* 06a5:d001 - nw802 - Panasonic - * GP-KR651US (Philips TDA8786) */ -static const u8 kr651_start_1[] = { - 0x04, 0x06, 0x01, 0x04, - 0x00, 0x00, 0x40, 0x44, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x48, - 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4, - 0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54, - 0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, - 0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30, - 0x00, 0x80, 0x1f, 0x18, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f, - 0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11, - 0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94, - 0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00, - 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, - 0x40, 0x20, - 0x03, 0x00, 0x03, 0x02, 0x00, 0x00, - 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00, - 0x06, 0x00, 0x02, 0x09, 0x99, - 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c, - 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, - 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, - 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, - 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, - 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, - 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, - 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, - 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, - 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, - 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, - 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82, - 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, - 0x01, 0xf0, 0x00, - 0, 0, 0 -}; -static const u8 kr651_start_qvga[] = { - 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00, - 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78, - 0x40, - 0x10, 0x1a, 0x01, 0x03, - 0x10, 0x00, 0x01, 0xac, - 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, - 0x10, 0x1b, 0x02, 0x00, 0x00, - 0x10, 0x11, 0x08, 0x29, 0x00, 0x18, 0x01, 0x1f, 0x00, 0xd2, 0x00, - 0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00, - 0x10, 0x1d, 0x02, 0x28, 0x01, - 0, 0, 0 -}; -static const u8 kr651_start_vga[] = { - 0x02, 0x00, 0x11, 0x78, 0xa0, 0x8c, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x30, 0x03, 0x01, 0x82, 0x82, 0x98, - 0x80, - 0x10, 0x1a, 0x01, 0x03, - 0x10, 0x00, 0x01, 0xa0, - 0x10, 0x85, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01, - 0x10, 0x1b, 0x02, 0x00, 0x00, - 0x10, 0x11, 0x08, 0x51, 0x00, 0x30, 0x02, 0x3d, 0x00, 0xa4, 0x01, - 0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00, - 0x10, 0x1d, 0x02, 0x68, 0x00, -}; -static const u8 kr651_start_2[] = { - 0x10, 0x0e, 0x01, 0x08, - 0x10, 0x41, 0x11, 0x00, 0x11, 0x3c, 0x5c, 0x74, 0x88, 0x99, 0xa8, - 0xb7, 0xc4, 0xd0, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, - 0xdc, - 0x10, 0x03, 0x01, 0x00, - 0x10, 0x0f, 0x02, 0x0c, 0x0c, - 0x10, 0x03, 0x01, 0x0c, - 0x10, 0x41, 0x11, 0x00, 0x11, 0x3c, 0x5c, 0x74, 0x88, 0x99, 0xa8, - 0xb7, 0xc4, 0xd0, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, - 0xdc, - 0x10, 0x0b, 0x01, 0x10, - 0x10, 0x0d, 0x01, 0x10, - 0x10, 0x0c, 0x01, 0x2d, - 0x04, 0x06, 0x01, 0x03, - 0x04, 0x04, 0x01, 0x00, - 0, 0, 0 -}; - -/* nw802 - iRez Kritter cam */ -static const u8 kritter_start[] = { - 0x04, 0x06, 0x01, 0x06, - 0x00, 0x00, 0x40, 0x44, 0x96, 0x98, 0x94, 0x03, 0x18, 0x00, 0x48, - 0x0f, 0x1e, 0x00, 0x0c, 0x02, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x0b, 0x00, 0x1b, 0x00, 0x0a, 0x01, 0x28, - 0x07, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54, - 0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, - 0x00, 0x5d, 0x00, 0x0e, 0x00, 0x7e, 0x00, 0x30, - 0x00, 0x80, 0x1f, 0x18, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f, - 0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11, - 0x00, 0x0b, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94, - 0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00, - 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, - 0x40, 0x20, - 0x03, 0x00, 0x03, 0x02, 0x00, 0x00, - 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00, - 0x06, 0x00, 0x02, 0x09, 0x99, - 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c, - 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, - 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, - 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, - 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, - 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, - 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, - 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, - 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, - 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, - 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, - 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x82, - 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, - 0x01, 0xf0, 0x00, - 0x02, 0x00, 0x11, 0x3c, 0x50, 0x8c, 0x3c, 0x50, 0x00, 0x00, 0x00, - 0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0, - 0x40, - 0x10, 0x1a, 0x01, 0x03, - 0x10, 0x00, 0x01, 0xaf, - 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, - 0x10, 0x1b, 0x02, 0x3b, 0x01, - 0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00, - 0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00, - 0x10, 0x1d, 0x02, 0x00, 0x00, - 0x10, 0x0e, 0x01, 0x08, - 0x10, 0x41, 0x11, 0x00, 0x0d, 0x36, 0x4e, 0x60, 0x6f, 0x7b, 0x86, - 0x90, 0x98, 0xa1, 0xa9, 0xb1, 0xb7, 0xbe, 0xc4, - 0xcb, - 0x10, 0x03, 0x01, 0x00, - 0x10, 0x0f, 0x02, 0x0d, 0x0d, - 0x10, 0x03, 0x01, 0x02, - 0x10, 0x41, 0x11, 0x00, 0x0d, 0x36, 0x4e, 0x60, 0x6f, 0x7b, 0x86, - 0x90, 0x98, 0xa1, 0xa9, 0xb1, 0xb7, 0xbe, 0xc4, - 0xcb, - 0x10, 0x0b, 0x01, 0x17, - 0x10, 0x0d, 0x01, 0x10, - 0x10, 0x0c, 0x01, 0x1e, - 0x04, 0x06, 0x01, 0x03, - 0x04, 0x04, 0x01, 0x00, - 0, 0, 0 -}; - -/* nw802 - Mustek Wcam 300 mini */ -static const u8 mustek_start[] = { - 0x04, 0x06, 0x01, 0x04, - 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x92, 0x03, 0x10, 0x00, 0x4d, - 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4, - 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, - 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, - 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, - 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, - 0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11, - 0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94, - 0x00, 0x10, 0x06, 0xfc, 0x05, 0x0c, 0x06, - 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, - 0x40, 0x20, - 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00, - 0x06, 0x00, 0x02, 0x09, 0x99, - 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x13, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x13, 0x00, 0x00, 0xc0, 0x00, 0x14, - 0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, - 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, - 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, - 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, - 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, - 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, - 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, - 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, - 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, - 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, - 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x01, 0x82, - 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, - 0x01, 0xf0, 0x00, - 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00, - 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78, - 0x40, - 0x10, 0x1a, 0x01, 0x00, - 0x10, 0x00, 0x01, 0xad, - 0x00, 0x00, 0x01, 0x08, - 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, - 0x10, 0x1b, 0x02, 0x00, 0x00, - 0x10, 0x11, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, - 0x10, 0x1d, 0x08, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, - 0x10, 0x0e, 0x01, 0x0f, - 0x10, 0x41, 0x11, 0x00, 0x0f, 0x29, 0x4a, 0x64, 0x7a, 0x8c, 0x9e, - 0xad, 0xba, 0xc7, 0xd3, 0xde, 0xe8, 0xf1, 0xf9, - 0xff, - 0x10, 0x0f, 0x02, 0x11, 0x11, - 0x10, 0x03, 0x01, 0x0c, - 0x10, 0x41, 0x11, 0x00, 0x0f, 0x29, 0x4a, 0x64, 0x7a, 0x8c, 0x9e, - 0xad, 0xba, 0xc7, 0xd3, 0xde, 0xe8, 0xf1, 0xf9, - 0xff, - 0x10, 0x0b, 0x01, 0x1c, - 0x10, 0x0d, 0x01, 0x1a, - 0x10, 0x0c, 0x01, 0x34, - 0x04, 0x05, 0x01, 0x61, - 0x04, 0x04, 0x01, 0x40, - 0x04, 0x06, 0x01, 0x03, - 0, 0, 0 -}; - -/* nw802 - Scope USB Microscope M2 (ProScope) (Hitachi HD49322BF) */ -static const u8 proscope_init[] = { - 0x04, 0x05, 0x01, 0x21, - 0x04, 0x04, 0x01, 0x01, - 0, 0, 0 -}; -static const u8 proscope_start_1[] = { - 0x04, 0x06, 0x01, 0x04, - 0x00, 0x00, 0x40, 0x10, 0x01, 0x00, 0xf9, 0x02, 0x10, 0x00, 0x04, - 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x08, 0x00, 0x17, 0x00, 0xce, 0x00, 0xf4, - 0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, - 0x00, 0xce, 0x00, 0xf8, 0x03, 0x3e, 0x00, 0x86, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0xb6, - 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xf6, 0x03, 0x34, 0x04, 0xf6, 0x03, 0x34, - 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xe8, - 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, - 0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x1f, 0x0f, 0x08, 0x20, 0xa8, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11, - 0x00, 0x0c, 0x02, 0x01, 0x00, 0x19, 0x00, 0x94, - 0x00, 0x10, 0x06, 0x10, 0x00, 0x36, 0x00, - 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, - 0x40, 0x20, - 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00, - 0x06, 0x00, 0x02, 0x09, 0x99, - 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x40, 0xad, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x1f, 0x10, 0x08, 0x0a, - 0x0a, 0x51, 0x00, 0xf1, 0x00, 0x3c, 0x00, 0xb4, - 0x00, 0x49, 0x13, 0x00, 0x00, 0x8c, 0x04, 0x01, - 0x20, 0x02, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, - 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, - 0x10, 0x40, 0x40, 0x80, 0x00, 0x2d, 0x46, 0x58, 0x67, 0x74, 0x7f, - 0x88, 0x94, 0x9d, 0xa6, 0xae, 0xb5, 0xbd, 0xc4, - 0xcb, 0xd1, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, - 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, - 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, - 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, - 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, - 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, - 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x3f, - 0x01, 0x00, 0x00, 0xef, 0x00, 0x09, 0x05, 0x82, - 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, - 0x01, 0xf0, 0x00, - 0, 0, 0 -}; -static const u8 proscope_start_qvga[] = { - 0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00, - 0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78, - 0x40, - 0x10, 0x1a, 0x01, 0x06, - 0x00, 0x03, 0x02, 0xf9, 0x02, - 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, - 0x10, 0x1b, 0x02, 0x00, 0x00, - 0x10, 0x11, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, - 0x10, 0x1d, 0x08, 0xc0, 0x0d, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00, - 0x10, 0x0e, 0x01, 0x10, - 0, 0, 0 -}; -static const u8 proscope_start_vga[] = { - 0x00, 0x03, 0x02, 0xf9, 0x02, - 0x10, 0x85, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01, - 0x02, 0x00, 0x11, 0x78, 0xa0, 0x8c, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x16, 0x00, 0x00, 0x82, 0x84, 0x00, - 0x80, - 0x10, 0x1a, 0x01, 0x06, - 0x10, 0x00, 0x01, 0xa1, - 0x10, 0x1b, 0x02, 0x00, 0x00, - 0x10, 0x1d, 0x08, 0xc0, 0x0d, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00, - 0x10, 0x11, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01, - 0x10, 0x0e, 0x01, 0x10, - 0x10, 0x41, 0x11, 0x00, 0x10, 0x51, 0x6e, 0x83, 0x93, 0xa1, 0xae, - 0xb9, 0xc3, 0xcc, 0xd4, 0xdd, 0xe4, 0xeb, 0xf2, - 0xf9, - 0x10, 0x03, 0x01, 0x00, - 0, 0, 0 -}; -static const u8 proscope_start_2[] = { - 0x10, 0x0f, 0x02, 0x0c, 0x0c, - 0x10, 0x03, 0x01, 0x0c, - 0x10, 0x41, 0x11, 0x00, 0x10, 0x51, 0x6e, 0x83, 0x93, 0xa1, 0xae, - 0xb9, 0xc3, 0xcc, 0xd4, 0xdd, 0xe4, 0xeb, 0xf2, - 0xf9, - 0x10, 0x0b, 0x01, 0x0b, - 0x10, 0x0d, 0x01, 0x10, - 0x10, 0x0c, 0x01, 0x1b, - 0x04, 0x06, 0x01, 0x03, - 0x04, 0x05, 0x01, 0x21, - 0x04, 0x04, 0x01, 0x00, - 0, 0, 0 -}; - -/* nw800 - hv7121b? (seems pas106) - Divio Chicony TwinkleCam */ -static const u8 twinkle_start[] = { - 0x04, 0x06, 0x01, 0x44, - 0x04, 0x06, 0x01, 0x00, - 0x00, 0x00, 0x40, 0x14, 0x83, 0x00, 0xba, 0x01, 0x10, 0x00, 0x4f, - 0xef, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x06, 0x00, 0xfc, - 0x01, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86, - 0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e, - 0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78, - 0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46, - 0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0, - 0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e, - 0x00, 0x80, 0x1f, 0xb8, 0x48, 0x0f, 0x04, 0x88, 0x14, 0x68, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x03, - 0x00, 0x24, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04, - 0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00, - 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, - 0x40, 0x20, - 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00, - 0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x40, 0x80, 0x02, 0x20, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x08, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, - 0x03, 0x00, 0x00, 0x10, 0x00, 0x20, 0x10, 0x06, - 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x00, 0x80, - 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, - 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, - 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, - 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, - 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, - 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, - 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, - 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, - 0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62, - 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20, - 0x01, 0x60, 0x01, 0x00, 0x00, - - 0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01, - 0x04, 0x04, 0x01, 0x10, - 0x04, 0x04, 0x01, 0x00, - 0x04, 0x05, 0x01, 0x61, - 0x04, 0x04, 0x01, 0x01, - I2C0, 0x40, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0a, - I2C0, 0x40, 0x02, 0x11, 0x06, - I2C0, 0x40, 0x02, 0x14, 0x00, - I2C0, 0x40, 0x02, 0x13, 0x01, /* i2c end */ - I2C0, 0x40, 0x02, 0x07, 0x01, - 0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00, - 0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65, - 0x40, - I2C0, 0x40, 0x02, 0x02, 0x0c, - I2C0, 0x40, 0x02, 0x13, 0x01, - 0x10, 0x00, 0x01, 0x01, - 0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, - 0x20, 0x01, 0x60, 0x01, - I2C0, 0x40, 0x02, 0x05, 0x0f, - I2C0, 0x40, 0x02, 0x13, 0x01, - I2C0, 0x40, 0x08, 0x08, 0x04, 0x0b, 0x01, 0x01, 0x02, 0x00, 0x17, - I2C0, 0x40, 0x03, 0x12, 0x00, 0x01, - 0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01, - I2C0, 0x40, 0x02, 0x12, 0x00, - I2C0, 0x40, 0x02, 0x0e, 0x00, - I2C0, 0x40, 0x02, 0x11, 0x06, - 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7, - 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7, - 0xf9, - 0x10, 0x03, 0x01, 0x00, - 0x10, 0x0f, 0x02, 0x0c, 0x0c, - 0x10, 0x03, 0x01, 0x06, - 0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7, - 0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7, - 0xf9, - 0x10, 0x0b, 0x01, 0x19, - 0x10, 0x0d, 0x01, 0x10, - 0x10, 0x0c, 0x01, 0x0d, - 0x04, 0x06, 0x01, 0x03, - 0x04, 0x05, 0x01, 0x61, - 0x04, 0x04, 0x01, 0x41, - 0, 0, 0 -}; - -/* nw802 dvc-v6 */ -static const u8 dvcv6_start[] = { - 0x04, 0x06, 0x01, 0x06, - 0x00, 0x00, 0x40, 0x54, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x4c, - 0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19, - 0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19, - 0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4, - 0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54, - 0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, - 0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30, - 0x00, 0x80, 0x1f, 0x98, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f, - 0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11, - 0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94, - 0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00, - 0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0, - 0x40, 0x20, - 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00, - 0x06, 0x00, 0x02, 0x09, 0x99, - 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c, - 0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, - 0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, - 0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, - 0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, - 0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, - 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, - 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, - 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, - 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, - 0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, - 0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82, - 0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, - 0x01, 0xf0, 0x00, - 0x00, 0x03, 0x02, 0x94, 0x03, - 0x00, 0x1d, 0x04, 0x0a, 0x01, 0x28, 0x07, - 0x00, 0x7b, 0x02, 0xe0, 0x00, - 0x10, 0x8d, 0x01, 0x00, - 0x00, 0x09, 0x04, 0x1e, 0x00, 0x0c, 0x02, - 0x00, 0x91, 0x02, 0x0b, 0x02, - 0x10, 0x00, 0x01, 0xaf, - 0x02, 0x00, 0x11, 0x3c, 0x50, 0x8f, 0x3c, 0x50, 0x00, 0x00, 0x00, - 0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0, - 0x40, - 0x10, 0x1a, 0x01, 0x02, - 0x10, 0x00, 0x01, 0xaf, - 0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00, - 0x10, 0x1b, 0x02, 0x07, 0x01, - 0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00, - 0x10, 0x1f, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00, - 0x10, 0x1d, 0x02, 0x40, 0x06, - 0x10, 0x0e, 0x01, 0x08, - 0x10, 0x41, 0x11, 0x00, 0x0f, 0x54, 0x6f, 0x82, 0x91, 0x9f, 0xaa, - 0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xdb, 0xdc, 0xdc, - 0xdc, - 0x10, 0x03, 0x01, 0x00, - 0x10, 0x0f, 0x02, 0x12, 0x12, - 0x10, 0x03, 0x01, 0x11, - 0x10, 0x41, 0x11, 0x00, 0x0f, 0x54, 0x6f, 0x82, 0x91, 0x9f, 0xaa, - 0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xdb, 0xdc, 0xdc, - 0xdc, - 0x10, 0x0b, 0x01, 0x16, - 0x10, 0x0d, 0x01, 0x10, - 0x10, 0x0c, 0x01, 0x1a, - 0x04, 0x06, 0x01, 0x03, - 0x04, 0x04, 0x01, 0x00, -}; - -static const u8 *webcam_start[] = { - [Generic800] = nw800_start, - [SpaceCam] = spacecam_start, - [SpaceCam2] = spacecam2_start, - [Cvideopro] = cvideopro_start, - [Dlink350c] = dlink_start, - [DS3303u] = ds3303_start, - [Kr651us] = kr651_start_1, - [Kritter] = kritter_start, - [Mustek300] = mustek_start, - [Proscope] = proscope_start_1, - [Twinkle] = twinkle_start, - [DvcV6] = dvcv6_start, - [P35u] = nw801_start_1, - [Generic802] = nw802_start, -}; - -/* -- write a register -- */ -static void reg_w(struct gspca_dev *gspca_dev, - u16 index, - const u8 *data, - int len) -{ - struct usb_device *dev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return; - if (len == 1) - PDEBUG(D_USBO, "SET 00 0000 %04x %02x", index, *data); - else - PDEBUG(D_USBO, "SET 00 0000 %04x %02x %02x ...", - index, *data, data[1]); - memcpy(gspca_dev->usb_buf, data, len); - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x00, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x00, /* value */ - index, - gspca_dev->usb_buf, - len, - 500); - if (ret < 0) { - pr_err("reg_w err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -/* -- read registers in usb_buf -- */ -static void reg_r(struct gspca_dev *gspca_dev, - u16 index, - int len) -{ - struct usb_device *dev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return; - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - 0x00, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x00, index, - gspca_dev->usb_buf, len, 500); - if (ret < 0) { - pr_err("reg_r err %d\n", ret); - gspca_dev->usb_err = ret; - return; - } - if (len == 1) - PDEBUG(D_USBI, "GET 00 0000 %04x %02x", - index, gspca_dev->usb_buf[0]); - else - PDEBUG(D_USBI, "GET 00 0000 %04x %02x %02x ..", - index, gspca_dev->usb_buf[0], - gspca_dev->usb_buf[1]); -} - -static void i2c_w(struct gspca_dev *gspca_dev, - u8 i2c_addr, - const u8 *data, - int len) -{ - u8 val[2]; - int i; - - reg_w(gspca_dev, 0x0600, data + 1, len - 1); - reg_w(gspca_dev, 0x0600, data, len); - val[0] = len; - val[1] = i2c_addr; - reg_w(gspca_dev, 0x0502, val, 2); - val[0] = 0x01; - reg_w(gspca_dev, 0x0501, val, 1); - for (i = 5; --i >= 0; ) { - msleep(4); - reg_r(gspca_dev, 0x0505, 1); - if (gspca_dev->usb_err < 0) - return; - if (gspca_dev->usb_buf[0] == 0) - return; - } - gspca_dev->usb_err = -ETIME; -} - -static void reg_w_buf(struct gspca_dev *gspca_dev, - const u8 *cmd) -{ - u16 reg; - int len; - - for (;;) { - reg = *cmd++ << 8; - reg += *cmd++; - len = *cmd++; - if (len == 0) - break; - if (cmd[-3] != I2C0) - reg_w(gspca_dev, reg, cmd, len); - else - i2c_w(gspca_dev, reg, cmd, len); - cmd += len; - } -} - -static int swap_bits(int v) -{ - int r, i; - - r = 0; - for (i = 0; i < 8; i++) { - r <<= 1; - if (v & 1) - r++; - v >>= 1; - } - return r; -} - -static void setgain(struct gspca_dev *gspca_dev, u8 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 v[2]; - - switch (sd->webcam) { - case P35u: - reg_w(gspca_dev, 0x1026, &val, 1); - break; - case Kr651us: - /* 0 - 253 */ - val = swap_bits(val); - v[0] = val << 3; - v[1] = val >> 5; - reg_w(gspca_dev, 0x101d, v, 2); /* SIF reg0/1 (AGC) */ - break; - } -} - -static void setexposure(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 v[2]; - - switch (sd->webcam) { - case P35u: - v[0] = ((9 - val) << 3) | 0x01; - reg_w(gspca_dev, 0x1019, v, 1); - break; - case Cvideopro: - case DvcV6: - case Kritter: - case Kr651us: - v[0] = val; - v[1] = val >> 8; - reg_w(gspca_dev, 0x101b, v, 2); - break; - } -} - -static void setautogain(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - int w, h; - - if (!val) { - sd->ag_cnt = -1; - return; - } - sd->ag_cnt = AG_CNT_START; - - reg_r(gspca_dev, 0x1004, 1); - if (gspca_dev->usb_buf[0] & 0x04) { /* if AE_FULL_FRM */ - sd->ae_res = gspca_dev->width * gspca_dev->height; - } else { /* get the AE window size */ - reg_r(gspca_dev, 0x1011, 8); - w = (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0] - - (gspca_dev->usb_buf[3] << 8) - gspca_dev->usb_buf[2]; - h = (gspca_dev->usb_buf[5] << 8) + gspca_dev->usb_buf[4] - - (gspca_dev->usb_buf[7] << 8) - gspca_dev->usb_buf[6]; - sd->ae_res = h * w; - if (sd->ae_res == 0) - sd->ae_res = gspca_dev->width * gspca_dev->height; - } -} - -static int nw802_test_reg(struct gspca_dev *gspca_dev, - u16 index, - u8 value) -{ - /* write the value */ - reg_w(gspca_dev, index, &value, 1); - - /* read it */ - reg_r(gspca_dev, index, 1); - - return gspca_dev->usb_buf[0] == value; -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if ((unsigned) webcam >= NWEBCAMS) - webcam = 0; - sd->webcam = webcam; - gspca_dev->cam.needs_full_bandwidth = 1; - sd->ag_cnt = -1; - - /* - * Autodetect sequence inspired from some log. - * We try to detect what registers exist or not. - * If 0x0500 does not exist => NW802 - * If it does, test 0x109b. If it doesn't exist, - * then it's a NW801. Else, a NW800 - * If a et31x110 (nw800 and 06a5:d800) - * get the sensor ID - */ - if (!nw802_test_reg(gspca_dev, 0x0500, 0x55)) { - sd->bridge = BRIDGE_NW802; - if (sd->webcam == Generic800) - sd->webcam = Generic802; - } else if (!nw802_test_reg(gspca_dev, 0x109b, 0xaa)) { - sd->bridge = BRIDGE_NW801; - if (sd->webcam == Generic800) - sd->webcam = P35u; - } else if (id->idVendor == 0x06a5 && id->idProduct == 0xd800) { - reg_r(gspca_dev, 0x0403, 1); /* GPIO */ - PDEBUG(D_PROBE, "et31x110 sensor type %02x", - gspca_dev->usb_buf[0]); - switch (gspca_dev->usb_buf[0] >> 1) { - case 0x00: /* ?? */ - if (sd->webcam == Generic800) - sd->webcam = SpaceCam; - break; - case 0x01: /* Hynix? */ - if (sd->webcam == Generic800) - sd->webcam = Twinkle; - break; - case 0x0a: /* Pixart */ - if (sd->webcam == Generic800) - sd->webcam = SpaceCam2; - break; - } - } - if (webcam_chip[sd->webcam] != sd->bridge) { - pr_err("Bad webcam type %d for NW80%d\n", - sd->webcam, sd->bridge); - gspca_dev->usb_err = -ENODEV; - return gspca_dev->usb_err; - } - PDEBUG(D_PROBE, "Bridge nw80%d - type: %d", sd->bridge, sd->webcam); - - if (sd->bridge == BRIDGE_NW800) { - switch (sd->webcam) { - case DS3303u: - gspca_dev->cam.cam_mode = cif_mode; /* qvga */ - break; - default: - gspca_dev->cam.cam_mode = &cif_mode[1]; /* cif */ - break; - } - gspca_dev->cam.nmodes = 1; - } else { - gspca_dev->cam.cam_mode = vga_mode; - switch (sd->webcam) { - case Kr651us: - case Proscope: - case P35u: - gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); - break; - default: - gspca_dev->cam.nmodes = 1; /* qvga only */ - break; - } - } - - return gspca_dev->usb_err; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->bridge) { - case BRIDGE_NW800: - switch (sd->webcam) { - case SpaceCam: - reg_w_buf(gspca_dev, spacecam_init); - break; - default: - reg_w_buf(gspca_dev, nw800_init); - break; - } - break; - default: - switch (sd->webcam) { - case Mustek300: - case P35u: - case Proscope: - reg_w_buf(gspca_dev, proscope_init); - break; - } - break; - } - return gspca_dev->usb_err; -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - const u8 *cmd; - - cmd = webcam_start[sd->webcam]; - reg_w_buf(gspca_dev, cmd); - switch (sd->webcam) { - case P35u: - if (gspca_dev->width == 320) - reg_w_buf(gspca_dev, nw801_start_qvga); - else - reg_w_buf(gspca_dev, nw801_start_vga); - reg_w_buf(gspca_dev, nw801_start_2); - break; - case Kr651us: - if (gspca_dev->width == 320) - reg_w_buf(gspca_dev, kr651_start_qvga); - else - reg_w_buf(gspca_dev, kr651_start_vga); - reg_w_buf(gspca_dev, kr651_start_2); - break; - case Proscope: - if (gspca_dev->width == 320) - reg_w_buf(gspca_dev, proscope_start_qvga); - else - reg_w_buf(gspca_dev, proscope_start_vga); - reg_w_buf(gspca_dev, proscope_start_2); - break; - } - - sd->exp_too_high_cnt = 0; - sd->exp_too_low_cnt = 0; - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 value; - - /* 'go' off */ - if (sd->bridge != BRIDGE_NW801) { - value = 0x02; - reg_w(gspca_dev, 0x0406, &value, 1); - } - - /* LED off */ - switch (sd->webcam) { - case Cvideopro: - case Kr651us: - case DvcV6: - case Kritter: - value = 0xff; - break; - case Dlink350c: - value = 0x21; - break; - case SpaceCam: - case SpaceCam2: - case Proscope: - case Twinkle: - value = 0x01; - break; - default: - return; - } - reg_w(gspca_dev, 0x0404, &value, 1); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - /* - * frame header = '00 00 hh ww ss xx ff ff' - * with: - * - 'hh': height / 4 - * - 'ww': width / 4 - * - 'ss': frame sequence number c0..dd - */ - if (data[0] == 0x00 && data[1] == 0x00 - && data[6] == 0xff && data[7] == 0xff) { - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - gspca_frame_add(gspca_dev, FIRST_PACKET, data + 8, len - 8); - } else { - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); - } -} - -static void do_autogain(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int luma; - - if (sd->ag_cnt < 0) - return; - if (--sd->ag_cnt >= 0) - return; - sd->ag_cnt = AG_CNT_START; - - /* get the average luma */ - reg_r(gspca_dev, sd->bridge == BRIDGE_NW801 ? 0x080d : 0x080c, 4); - luma = (gspca_dev->usb_buf[3] << 24) + (gspca_dev->usb_buf[2] << 16) - + (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]; - luma /= sd->ae_res; - - switch (sd->webcam) { - case P35u: - gspca_coarse_grained_expo_autogain(gspca_dev, luma, 100, 5); - break; - default: - gspca_expo_autogain(gspca_dev, luma, 100, 5, 230, 0); - break; - } -} - - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - /* autogain/gain/exposure control cluster */ - case V4L2_CID_AUTOGAIN: - if (ctrl->is_new) - setautogain(gspca_dev, ctrl->val); - if (!ctrl->val) { - if (gspca_dev->gain->is_new) - setgain(gspca_dev, gspca_dev->gain->val); - if (gspca_dev->exposure->is_new) - setexposure(gspca_dev, - gspca_dev->exposure->val); - } - break; - /* Some webcams only have exposure, so handle that separately from the - autogain/gain/exposure cluster in the previous case. */ - case V4L2_CID_EXPOSURE: - setexposure(gspca_dev, gspca_dev->exposure->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 3); - switch (sd->webcam) { - case P35u: - gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - /* For P35u choose coarse expo auto gain function gain minimum, - * to avoid a large settings jump the first auto adjustment */ - gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 127, 1, 127 / 5 * 2); - gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 9, 1, 9); - break; - case Kr651us: - gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 253, 1, 128); - /* fall through */ - case Cvideopro: - case DvcV6: - case Kritter: - gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 315, 1, 150); - break; - default: - break; - } - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - if (gspca_dev->autogain) - v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false); - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, - .dq_callback = do_autogain, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x046d, 0xd001)}, - {USB_DEVICE(0x0502, 0xd001)}, - {USB_DEVICE(0x052b, 0xd001)}, - {USB_DEVICE(0x055f, 0xd001)}, - {USB_DEVICE(0x06a5, 0x0000)}, - {USB_DEVICE(0x06a5, 0xd001)}, - {USB_DEVICE(0x06a5, 0xd800)}, - {USB_DEVICE(0x06be, 0xd001)}, - {USB_DEVICE(0x0728, 0xd001)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); - -module_param(webcam, int, 0644); -MODULE_PARM_DESC(webcam, - "Webcam type\n" - "0: generic\n" - "1: Trust 120 SpaceCam\n" - "2: other Trust 120 SpaceCam\n" - "3: Conceptronic Video Pro\n" - "4: D-link dru-350c\n" - "5: Plustek Opticam 500U\n" - "6: Panasonic GP-KR651US\n" - "7: iRez Kritter\n" - "8: Mustek Wcam 300 mini\n" - "9: Scalar USB Microscope M2 (Proscope)\n" - "10: Divio Chicony TwinkleCam\n" - "11: DVC-V6\n"); diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c deleted file mode 100644 index bfc7cefa59f8..000000000000 --- a/drivers/media/video/gspca/ov519.c +++ /dev/null @@ -1,4991 +0,0 @@ -/** - * OV519 driver - * - * Copyright (C) 2008-2011 Jean-François Moine <moinejf@free.fr> - * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> - * - * This module is adapted from the ov51x-jpeg package, which itself - * was adapted from the ov511 driver. - * - * Original copyright for the ov511 driver is: - * - * Copyright (c) 1999-2006 Mark W. McClelland - * Support for OV519, OV8610 Copyright (c) 2003 Joerg Heckenbach - * Many improvements by Bret Wallach <bwallac1@san.rr.com> - * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000) - * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org> - * Changes by Claudio Matsuoka <claudio@conectiva.com> - * - * ov51x-jpeg original copyright is: - * - * Copyright (c) 2004-2007 Romain Beauxis <toots@rastageeks.org> - * Support for OV7670 sensors was contributed by Sam Skipsey <aoanla@yahoo.com> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "ov519" - -#include <linux/input.h> -#include "gspca.h" - -/* The jpeg_hdr is used by w996Xcf only */ -/* The CONEX_CAM define for jpeg.h needs renaming, now its used here too */ -#define CONEX_CAM -#include "jpeg.h" - -MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); -MODULE_DESCRIPTION("OV519 USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* global parameters */ -static int frame_rate; - -/* Number of times to retry a failed I2C transaction. Increase this if you - * are getting "Failed to read sensor ID..." */ -static int i2c_detect_tries = 10; - -/* ov519 device descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - struct v4l2_ctrl *jpegqual; - struct v4l2_ctrl *freq; - struct { /* h/vflip control cluster */ - struct v4l2_ctrl *hflip; - struct v4l2_ctrl *vflip; - }; - struct { /* autobrightness/brightness control cluster */ - struct v4l2_ctrl *autobright; - struct v4l2_ctrl *brightness; - }; - - u8 packet_nr; - - char bridge; -#define BRIDGE_OV511 0 -#define BRIDGE_OV511PLUS 1 -#define BRIDGE_OV518 2 -#define BRIDGE_OV518PLUS 3 -#define BRIDGE_OV519 4 /* = ov530 */ -#define BRIDGE_OVFX2 5 -#define BRIDGE_W9968CF 6 -#define BRIDGE_MASK 7 - - char invert_led; -#define BRIDGE_INVERT_LED 8 - - char snapshot_pressed; - char snapshot_needs_reset; - - /* Determined by sensor type */ - u8 sif; - -#define QUALITY_MIN 50 -#define QUALITY_MAX 70 -#define QUALITY_DEF 50 - - u8 stopped; /* Streaming is temporarily paused */ - u8 first_frame; - - u8 frame_rate; /* current Framerate */ - u8 clockdiv; /* clockdiv override */ - - s8 sensor; /* Type of image sensor chip (SEN_*) */ - - u8 sensor_addr; - u16 sensor_width; - u16 sensor_height; - s16 sensor_reg_cache[256]; - - u8 jpeg_hdr[JPEG_HDR_SZ]; -}; -enum sensors { - SEN_OV2610, - SEN_OV2610AE, - SEN_OV3610, - SEN_OV6620, - SEN_OV6630, - SEN_OV66308AF, - SEN_OV7610, - SEN_OV7620, - SEN_OV7620AE, - SEN_OV7640, - SEN_OV7648, - SEN_OV7660, - SEN_OV7670, - SEN_OV76BE, - SEN_OV8610, - SEN_OV9600, -}; - -/* Note this is a bit of a hack, but the w9968cf driver needs the code for all - the ov sensors which is already present here. When we have the time we - really should move the sensor drivers to v4l2 sub drivers. */ -#include "w996Xcf.c" - -/* table of the disabled controls */ -struct ctrl_valid { - int has_brightness:1; - int has_contrast:1; - int has_exposure:1; - int has_autogain:1; - int has_sat:1; - int has_hvflip:1; - int has_autobright:1; - int has_freq:1; -}; - -static const struct ctrl_valid valid_controls[] = { - [SEN_OV2610] = { - .has_exposure = 1, - .has_autogain = 1, - }, - [SEN_OV2610AE] = { - .has_exposure = 1, - .has_autogain = 1, - }, - [SEN_OV3610] = { - /* No controls */ - }, - [SEN_OV6620] = { - .has_brightness = 1, - .has_contrast = 1, - .has_sat = 1, - .has_autobright = 1, - .has_freq = 1, - }, - [SEN_OV6630] = { - .has_brightness = 1, - .has_contrast = 1, - .has_sat = 1, - .has_autobright = 1, - .has_freq = 1, - }, - [SEN_OV66308AF] = { - .has_brightness = 1, - .has_contrast = 1, - .has_sat = 1, - .has_autobright = 1, - .has_freq = 1, - }, - [SEN_OV7610] = { - .has_brightness = 1, - .has_contrast = 1, - .has_sat = 1, - .has_autobright = 1, - .has_freq = 1, - }, - [SEN_OV7620] = { - .has_brightness = 1, - .has_contrast = 1, - .has_sat = 1, - .has_autobright = 1, - .has_freq = 1, - }, - [SEN_OV7620AE] = { - .has_brightness = 1, - .has_contrast = 1, - .has_sat = 1, - .has_autobright = 1, - .has_freq = 1, - }, - [SEN_OV7640] = { - .has_brightness = 1, - .has_sat = 1, - .has_freq = 1, - }, - [SEN_OV7648] = { - .has_brightness = 1, - .has_sat = 1, - .has_freq = 1, - }, - [SEN_OV7660] = { - .has_brightness = 1, - .has_contrast = 1, - .has_sat = 1, - .has_hvflip = 1, - .has_freq = 1, - }, - [SEN_OV7670] = { - .has_brightness = 1, - .has_contrast = 1, - .has_hvflip = 1, - .has_freq = 1, - }, - [SEN_OV76BE] = { - .has_brightness = 1, - .has_contrast = 1, - .has_sat = 1, - .has_autobright = 1, - .has_freq = 1, - }, - [SEN_OV8610] = { - .has_brightness = 1, - .has_contrast = 1, - .has_sat = 1, - .has_autobright = 1, - }, - [SEN_OV9600] = { - .has_exposure = 1, - .has_autogain = 1, - }, -}; - -static const struct v4l2_pix_format ov519_vga_mode[] = { - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; -static const struct v4l2_pix_format ov519_sif_mode[] = { - {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 3}, - {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2}, - {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; - -/* Note some of the sizeimage values for the ov511 / ov518 may seem - larger then necessary, however they need to be this big as the ov511 / - ov518 always fills the entire isoc frame, using 0 padding bytes when - it doesn't have any data. So with low framerates the amount of data - transferred can become quite large (libv4l will remove all the 0 padding - in userspace). */ -static const struct v4l2_pix_format ov518_vga_mode[] = { - {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 2, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; -static const struct v4l2_pix_format ov518_sif_mode[] = { - {160, 120, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 70000, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 3}, - {176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 70000, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, - {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2}, - {352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 3, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; - -static const struct v4l2_pix_format ov511_vga_mode[] = { - {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 2, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; -static const struct v4l2_pix_format ov511_sif_mode[] = { - {160, 120, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 70000, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 3}, - {176, 144, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 70000, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, - {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2}, - {352, 288, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 3, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; - -static const struct v4l2_pix_format ovfx2_vga_mode[] = { - {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; -static const struct v4l2_pix_format ovfx2_cif_mode[] = { - {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 3}, - {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, - {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; -static const struct v4l2_pix_format ovfx2_ov2610_mode[] = { - {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 800, - .sizeimage = 800 * 600, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 1600, - .sizeimage = 1600 * 1200, - .colorspace = V4L2_COLORSPACE_SRGB}, -}; -static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { - {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 800, - .sizeimage = 800 * 600, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 1024, - .sizeimage = 1024 * 768, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 1600, - .sizeimage = 1600 * 1200, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, - {2048, 1536, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 2048, - .sizeimage = 2048 * 1536, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; -static const struct v4l2_pix_format ovfx2_ov9600_mode[] = { - {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 1280, - .sizeimage = 1280 * 1024, - .colorspace = V4L2_COLORSPACE_SRGB}, -}; - -/* Registers common to OV511 / OV518 */ -#define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */ -#define R51x_SYS_RESET 0x50 - /* Reset type flags */ - #define OV511_RESET_OMNICE 0x08 -#define R51x_SYS_INIT 0x53 -#define R51x_SYS_SNAP 0x52 -#define R51x_SYS_CUST_ID 0x5f -#define R51x_COMP_LUT_BEGIN 0x80 - -/* OV511 Camera interface register numbers */ -#define R511_CAM_DELAY 0x10 -#define R511_CAM_EDGE 0x11 -#define R511_CAM_PXCNT 0x12 -#define R511_CAM_LNCNT 0x13 -#define R511_CAM_PXDIV 0x14 -#define R511_CAM_LNDIV 0x15 -#define R511_CAM_UV_EN 0x16 -#define R511_CAM_LINE_MODE 0x17 -#define R511_CAM_OPTS 0x18 - -#define R511_SNAP_FRAME 0x19 -#define R511_SNAP_PXCNT 0x1a -#define R511_SNAP_LNCNT 0x1b -#define R511_SNAP_PXDIV 0x1c -#define R511_SNAP_LNDIV 0x1d -#define R511_SNAP_UV_EN 0x1e -#define R511_SNAP_OPTS 0x1f - -#define R511_DRAM_FLOW_CTL 0x20 -#define R511_FIFO_OPTS 0x31 -#define R511_I2C_CTL 0x40 -#define R511_SYS_LED_CTL 0x55 /* OV511+ only */ -#define R511_COMP_EN 0x78 -#define R511_COMP_LUT_EN 0x79 - -/* OV518 Camera interface register numbers */ -#define R518_GPIO_OUT 0x56 /* OV518(+) only */ -#define R518_GPIO_CTL 0x57 /* OV518(+) only */ - -/* OV519 Camera interface register numbers */ -#define OV519_R10_H_SIZE 0x10 -#define OV519_R11_V_SIZE 0x11 -#define OV519_R12_X_OFFSETL 0x12 -#define OV519_R13_X_OFFSETH 0x13 -#define OV519_R14_Y_OFFSETL 0x14 -#define OV519_R15_Y_OFFSETH 0x15 -#define OV519_R16_DIVIDER 0x16 -#define OV519_R20_DFR 0x20 -#define OV519_R25_FORMAT 0x25 - -/* OV519 System Controller register numbers */ -#define OV519_R51_RESET1 0x51 -#define OV519_R54_EN_CLK1 0x54 -#define OV519_R57_SNAPSHOT 0x57 - -#define OV519_GPIO_DATA_OUT0 0x71 -#define OV519_GPIO_IO_CTRL0 0x72 - -/*#define OV511_ENDPOINT_ADDRESS 1 * Isoc endpoint number */ - -/* - * The FX2 chip does not give us a zero length read at end of frame. - * It does, however, give a short read at the end of a frame, if - * necessary, rather than run two frames together. - * - * By choosing the right bulk transfer size, we are guaranteed to always - * get a short read for the last read of each frame. Frame sizes are - * always a composite number (width * height, or a multiple) so if we - * choose a prime number, we are guaranteed that the last read of a - * frame will be short. - * - * But it isn't that easy: the 2.6 kernel requires a multiple of 4KB, - * otherwise EOVERFLOW "babbling" errors occur. I have not been able - * to figure out why. [PMiller] - * - * The constant (13 * 4096) is the largest "prime enough" number less than 64KB. - * - * It isn't enough to know the number of bytes per frame, in case we - * have data dropouts or buffer overruns (even though the FX2 double - * buffers, there are some pretty strict real time constraints for - * isochronous transfer for larger frame sizes). - */ -/*jfm: this value does not work for 800x600 - see isoc_init */ -#define OVFX2_BULK_SIZE (13 * 4096) - -/* I2C registers */ -#define R51x_I2C_W_SID 0x41 -#define R51x_I2C_SADDR_3 0x42 -#define R51x_I2C_SADDR_2 0x43 -#define R51x_I2C_R_SID 0x44 -#define R51x_I2C_DATA 0x45 -#define R518_I2C_CTL 0x47 /* OV518(+) only */ -#define OVFX2_I2C_ADDR 0x00 - -/* I2C ADDRESSES */ -#define OV7xx0_SID 0x42 -#define OV_HIRES_SID 0x60 /* OV9xxx / OV2xxx / OV3xxx */ -#define OV8xx0_SID 0xa0 -#define OV6xx0_SID 0xc0 - -/* OV7610 registers */ -#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */ -#define OV7610_REG_BLUE 0x01 /* blue channel balance */ -#define OV7610_REG_RED 0x02 /* red channel balance */ -#define OV7610_REG_SAT 0x03 /* saturation */ -#define OV8610_REG_HUE 0x04 /* 04 reserved */ -#define OV7610_REG_CNT 0x05 /* Y contrast */ -#define OV7610_REG_BRT 0x06 /* Y brightness */ -#define OV7610_REG_COM_C 0x14 /* misc common regs */ -#define OV7610_REG_ID_HIGH 0x1c /* manufacturer ID MSB */ -#define OV7610_REG_ID_LOW 0x1d /* manufacturer ID LSB */ -#define OV7610_REG_COM_I 0x29 /* misc settings */ - -/* OV7660 and OV7670 registers */ -#define OV7670_R00_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ -#define OV7670_R01_BLUE 0x01 /* blue gain */ -#define OV7670_R02_RED 0x02 /* red gain */ -#define OV7670_R03_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */ -#define OV7670_R04_COM1 0x04 /* Control 1 */ -/*#define OV7670_R07_AECHH 0x07 * AEC MS 5 bits */ -#define OV7670_R0C_COM3 0x0c /* Control 3 */ -#define OV7670_R0D_COM4 0x0d /* Control 4 */ -#define OV7670_R0E_COM5 0x0e /* All "reserved" */ -#define OV7670_R0F_COM6 0x0f /* Control 6 */ -#define OV7670_R10_AECH 0x10 /* More bits of AEC value */ -#define OV7670_R11_CLKRC 0x11 /* Clock control */ -#define OV7670_R12_COM7 0x12 /* Control 7 */ -#define OV7670_COM7_FMT_VGA 0x00 -/*#define OV7670_COM7_YUV 0x00 * YUV */ -#define OV7670_COM7_FMT_QVGA 0x10 /* QVGA format */ -#define OV7670_COM7_FMT_MASK 0x38 -#define OV7670_COM7_RESET 0x80 /* Register reset */ -#define OV7670_R13_COM8 0x13 /* Control 8 */ -#define OV7670_COM8_AEC 0x01 /* Auto exposure enable */ -#define OV7670_COM8_AWB 0x02 /* White balance enable */ -#define OV7670_COM8_AGC 0x04 /* Auto gain enable */ -#define OV7670_COM8_BFILT 0x20 /* Band filter enable */ -#define OV7670_COM8_AECSTEP 0x40 /* Unlimited AEC step size */ -#define OV7670_COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */ -#define OV7670_R14_COM9 0x14 /* Control 9 - gain ceiling */ -#define OV7670_R15_COM10 0x15 /* Control 10 */ -#define OV7670_R17_HSTART 0x17 /* Horiz start high bits */ -#define OV7670_R18_HSTOP 0x18 /* Horiz stop high bits */ -#define OV7670_R19_VSTART 0x19 /* Vert start high bits */ -#define OV7670_R1A_VSTOP 0x1a /* Vert stop high bits */ -#define OV7670_R1E_MVFP 0x1e /* Mirror / vflip */ -#define OV7670_MVFP_VFLIP 0x10 /* vertical flip */ -#define OV7670_MVFP_MIRROR 0x20 /* Mirror image */ -#define OV7670_R24_AEW 0x24 /* AGC upper limit */ -#define OV7670_R25_AEB 0x25 /* AGC lower limit */ -#define OV7670_R26_VPT 0x26 /* AGC/AEC fast mode op region */ -#define OV7670_R32_HREF 0x32 /* HREF pieces */ -#define OV7670_R3A_TSLB 0x3a /* lots of stuff */ -#define OV7670_R3B_COM11 0x3b /* Control 11 */ -#define OV7670_COM11_EXP 0x02 -#define OV7670_COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ -#define OV7670_R3C_COM12 0x3c /* Control 12 */ -#define OV7670_R3D_COM13 0x3d /* Control 13 */ -#define OV7670_COM13_GAMMA 0x80 /* Gamma enable */ -#define OV7670_COM13_UVSAT 0x40 /* UV saturation auto adjustment */ -#define OV7670_R3E_COM14 0x3e /* Control 14 */ -#define OV7670_R3F_EDGE 0x3f /* Edge enhancement factor */ -#define OV7670_R40_COM15 0x40 /* Control 15 */ -/*#define OV7670_COM15_R00FF 0xc0 * 00 to FF */ -#define OV7670_R41_COM16 0x41 /* Control 16 */ -#define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */ -/* end of ov7660 common registers */ -#define OV7670_R55_BRIGHT 0x55 /* Brightness */ -#define OV7670_R56_CONTRAS 0x56 /* Contrast control */ -#define OV7670_R69_GFIX 0x69 /* Fix gain control */ -/*#define OV7670_R8C_RGB444 0x8c * RGB 444 control */ -#define OV7670_R9F_HAECC1 0x9f /* Hist AEC/AGC control 1 */ -#define OV7670_RA0_HAECC2 0xa0 /* Hist AEC/AGC control 2 */ -#define OV7670_RA5_BD50MAX 0xa5 /* 50hz banding step limit */ -#define OV7670_RA6_HAECC3 0xa6 /* Hist AEC/AGC control 3 */ -#define OV7670_RA7_HAECC4 0xa7 /* Hist AEC/AGC control 4 */ -#define OV7670_RA8_HAECC5 0xa8 /* Hist AEC/AGC control 5 */ -#define OV7670_RA9_HAECC6 0xa9 /* Hist AEC/AGC control 6 */ -#define OV7670_RAA_HAECC7 0xaa /* Hist AEC/AGC control 7 */ -#define OV7670_RAB_BD60MAX 0xab /* 60hz banding step limit */ - -struct ov_regvals { - u8 reg; - u8 val; -}; -struct ov_i2c_regvals { - u8 reg; - u8 val; -}; - -/* Settings for OV2610 camera chip */ -static const struct ov_i2c_regvals norm_2610[] = { - { 0x12, 0x80 }, /* reset */ -}; - -static const struct ov_i2c_regvals norm_2610ae[] = { - {0x12, 0x80}, /* reset */ - {0x13, 0xcd}, - {0x09, 0x01}, - {0x0d, 0x00}, - {0x11, 0x80}, - {0x12, 0x20}, /* 1600x1200 */ - {0x33, 0x0c}, - {0x35, 0x90}, - {0x36, 0x37}, -/* ms-win traces */ - {0x11, 0x83}, /* clock / 3 ? */ - {0x2d, 0x00}, /* 60 Hz filter */ - {0x24, 0xb0}, /* normal colors */ - {0x25, 0x90}, - {0x10, 0x43}, -}; - -static const struct ov_i2c_regvals norm_3620b[] = { - /* - * From the datasheet: "Note that after writing to register COMH - * (0x12) to change the sensor mode, registers related to the - * sensor’s cropping window will be reset back to their default - * values." - * - * "wait 4096 external clock ... to make sure the sensor is - * stable and ready to access registers" i.e. 160us at 24MHz - */ - { 0x12, 0x80 }, /* COMH reset */ - { 0x12, 0x00 }, /* QXGA, master */ - - /* - * 11 CLKRC "Clock Rate Control" - * [7] internal frequency doublers: on - * [6] video port mode: master - * [5:0] clock divider: 1 - */ - { 0x11, 0x80 }, - - /* - * 13 COMI "Common Control I" - * = 192 (0xC0) 11000000 - * COMI[7] "AEC speed selection" - * = 1 (0x01) 1....... "Faster AEC correction" - * COMI[6] "AEC speed step selection" - * = 1 (0x01) .1...... "Big steps, fast" - * COMI[5] "Banding filter on off" - * = 0 (0x00) ..0..... "Off" - * COMI[4] "Banding filter option" - * = 0 (0x00) ...0.... "Main clock is 48 MHz and - * the PLL is ON" - * COMI[3] "Reserved" - * = 0 (0x00) ....0... - * COMI[2] "AGC auto manual control selection" - * = 0 (0x00) .....0.. "Manual" - * COMI[1] "AWB auto manual control selection" - * = 0 (0x00) ......0. "Manual" - * COMI[0] "Exposure control" - * = 0 (0x00) .......0 "Manual" - */ - { 0x13, 0xc0 }, - - /* - * 09 COMC "Common Control C" - * = 8 (0x08) 00001000 - * COMC[7:5] "Reserved" - * = 0 (0x00) 000..... - * COMC[4] "Sleep Mode Enable" - * = 0 (0x00) ...0.... "Normal mode" - * COMC[3:2] "Sensor sampling reset timing selection" - * = 2 (0x02) ....10.. "Longer reset time" - * COMC[1:0] "Output drive current select" - * = 0 (0x00) ......00 "Weakest" - */ - { 0x09, 0x08 }, - - /* - * 0C COMD "Common Control D" - * = 8 (0x08) 00001000 - * COMD[7] "Reserved" - * = 0 (0x00) 0....... - * COMD[6] "Swap MSB and LSB at the output port" - * = 0 (0x00) .0...... "False" - * COMD[5:3] "Reserved" - * = 1 (0x01) ..001... - * COMD[2] "Output Average On Off" - * = 0 (0x00) .....0.. "Output Normal" - * COMD[1] "Sensor precharge voltage selection" - * = 0 (0x00) ......0. "Selects internal - * reference precharge - * voltage" - * COMD[0] "Snapshot option" - * = 0 (0x00) .......0 "Enable live video output - * after snapshot sequence" - */ - { 0x0c, 0x08 }, - - /* - * 0D COME "Common Control E" - * = 161 (0xA1) 10100001 - * COME[7] "Output average option" - * = 1 (0x01) 1....... "Output average of 4 pixels" - * COME[6] "Anti-blooming control" - * = 0 (0x00) .0...... "Off" - * COME[5:3] "Reserved" - * = 4 (0x04) ..100... - * COME[2] "Clock output power down pin status" - * = 0 (0x00) .....0.. "Tri-state data output pin - * on power down" - * COME[1] "Data output pin status selection at power down" - * = 0 (0x00) ......0. "Tri-state VSYNC, PCLK, - * HREF, and CHSYNC pins on - * power down" - * COME[0] "Auto zero circuit select" - * = 1 (0x01) .......1 "On" - */ - { 0x0d, 0xa1 }, - - /* - * 0E COMF "Common Control F" - * = 112 (0x70) 01110000 - * COMF[7] "System clock selection" - * = 0 (0x00) 0....... "Use 24 MHz system clock" - * COMF[6:4] "Reserved" - * = 7 (0x07) .111.... - * COMF[3] "Manual auto negative offset canceling selection" - * = 0 (0x00) ....0... "Auto detect negative - * offset and cancel it" - * COMF[2:0] "Reserved" - * = 0 (0x00) .....000 - */ - { 0x0e, 0x70 }, - - /* - * 0F COMG "Common Control G" - * = 66 (0x42) 01000010 - * COMG[7] "Optical black output selection" - * = 0 (0x00) 0....... "Disable" - * COMG[6] "Black level calibrate selection" - * = 1 (0x01) .1...... "Use optical black pixels - * to calibrate" - * COMG[5:4] "Reserved" - * = 0 (0x00) ..00.... - * COMG[3] "Channel offset adjustment" - * = 0 (0x00) ....0... "Disable offset adjustment" - * COMG[2] "ADC black level calibration option" - * = 0 (0x00) .....0.. "Use B/G line and G/R - * line to calibrate each - * channel's black level" - * COMG[1] "Reserved" - * = 1 (0x01) ......1. - * COMG[0] "ADC black level calibration enable" - * = 0 (0x00) .......0 "Disable" - */ - { 0x0f, 0x42 }, - - /* - * 14 COMJ "Common Control J" - * = 198 (0xC6) 11000110 - * COMJ[7:6] "AGC gain ceiling" - * = 3 (0x03) 11...... "8x" - * COMJ[5:4] "Reserved" - * = 0 (0x00) ..00.... - * COMJ[3] "Auto banding filter" - * = 0 (0x00) ....0... "Banding filter is always - * on off depending on - * COMI[5] setting" - * COMJ[2] "VSYNC drop option" - * = 1 (0x01) .....1.. "SYNC is dropped if frame - * data is dropped" - * COMJ[1] "Frame data drop" - * = 1 (0x01) ......1. "Drop frame data if - * exposure is not within - * tolerance. In AEC mode, - * data is normally dropped - * when data is out of - * range." - * COMJ[0] "Reserved" - * = 0 (0x00) .......0 - */ - { 0x14, 0xc6 }, - - /* - * 15 COMK "Common Control K" - * = 2 (0x02) 00000010 - * COMK[7] "CHSYNC pin output swap" - * = 0 (0x00) 0....... "CHSYNC" - * COMK[6] "HREF pin output swap" - * = 0 (0x00) .0...... "HREF" - * COMK[5] "PCLK output selection" - * = 0 (0x00) ..0..... "PCLK always output" - * COMK[4] "PCLK edge selection" - * = 0 (0x00) ...0.... "Data valid on falling edge" - * COMK[3] "HREF output polarity" - * = 0 (0x00) ....0... "positive" - * COMK[2] "Reserved" - * = 0 (0x00) .....0.. - * COMK[1] "VSYNC polarity" - * = 1 (0x01) ......1. "negative" - * COMK[0] "HSYNC polarity" - * = 0 (0x00) .......0 "positive" - */ - { 0x15, 0x02 }, - - /* - * 33 CHLF "Current Control" - * = 9 (0x09) 00001001 - * CHLF[7:6] "Sensor current control" - * = 0 (0x00) 00...... - * CHLF[5] "Sensor current range control" - * = 0 (0x00) ..0..... "normal range" - * CHLF[4] "Sensor current" - * = 0 (0x00) ...0.... "normal current" - * CHLF[3] "Sensor buffer current control" - * = 1 (0x01) ....1... "half current" - * CHLF[2] "Column buffer current control" - * = 0 (0x00) .....0.. "normal current" - * CHLF[1] "Analog DSP current control" - * = 0 (0x00) ......0. "normal current" - * CHLF[1] "ADC current control" - * = 0 (0x00) ......0. "normal current" - */ - { 0x33, 0x09 }, - - /* - * 34 VBLM "Blooming Control" - * = 80 (0x50) 01010000 - * VBLM[7] "Hard soft reset switch" - * = 0 (0x00) 0....... "Hard reset" - * VBLM[6:4] "Blooming voltage selection" - * = 5 (0x05) .101.... - * VBLM[3:0] "Sensor current control" - * = 0 (0x00) ....0000 - */ - { 0x34, 0x50 }, - - /* - * 36 VCHG "Sensor Precharge Voltage Control" - * = 0 (0x00) 00000000 - * VCHG[7] "Reserved" - * = 0 (0x00) 0....... - * VCHG[6:4] "Sensor precharge voltage control" - * = 0 (0x00) .000.... - * VCHG[3:0] "Sensor array common reference" - * = 0 (0x00) ....0000 - */ - { 0x36, 0x00 }, - - /* - * 37 ADC "ADC Reference Control" - * = 4 (0x04) 00000100 - * ADC[7:4] "Reserved" - * = 0 (0x00) 0000.... - * ADC[3] "ADC input signal range" - * = 0 (0x00) ....0... "Input signal 1.0x" - * ADC[2:0] "ADC range control" - * = 4 (0x04) .....100 - */ - { 0x37, 0x04 }, - - /* - * 38 ACOM "Analog Common Ground" - * = 82 (0x52) 01010010 - * ACOM[7] "Analog gain control" - * = 0 (0x00) 0....... "Gain 1x" - * ACOM[6] "Analog black level calibration" - * = 1 (0x01) .1...... "On" - * ACOM[5:0] "Reserved" - * = 18 (0x12) ..010010 - */ - { 0x38, 0x52 }, - - /* - * 3A FREFA "Internal Reference Adjustment" - * = 0 (0x00) 00000000 - * FREFA[7:0] "Range" - * = 0 (0x00) 00000000 - */ - { 0x3a, 0x00 }, - - /* - * 3C FVOPT "Internal Reference Adjustment" - * = 31 (0x1F) 00011111 - * FVOPT[7:0] "Range" - * = 31 (0x1F) 00011111 - */ - { 0x3c, 0x1f }, - - /* - * 44 Undocumented = 0 (0x00) 00000000 - * 44[7:0] "It's a secret" - * = 0 (0x00) 00000000 - */ - { 0x44, 0x00 }, - - /* - * 40 Undocumented = 0 (0x00) 00000000 - * 40[7:0] "It's a secret" - * = 0 (0x00) 00000000 - */ - { 0x40, 0x00 }, - - /* - * 41 Undocumented = 0 (0x00) 00000000 - * 41[7:0] "It's a secret" - * = 0 (0x00) 00000000 - */ - { 0x41, 0x00 }, - - /* - * 42 Undocumented = 0 (0x00) 00000000 - * 42[7:0] "It's a secret" - * = 0 (0x00) 00000000 - */ - { 0x42, 0x00 }, - - /* - * 43 Undocumented = 0 (0x00) 00000000 - * 43[7:0] "It's a secret" - * = 0 (0x00) 00000000 - */ - { 0x43, 0x00 }, - - /* - * 45 Undocumented = 128 (0x80) 10000000 - * 45[7:0] "It's a secret" - * = 128 (0x80) 10000000 - */ - { 0x45, 0x80 }, - - /* - * 48 Undocumented = 192 (0xC0) 11000000 - * 48[7:0] "It's a secret" - * = 192 (0xC0) 11000000 - */ - { 0x48, 0xc0 }, - - /* - * 49 Undocumented = 25 (0x19) 00011001 - * 49[7:0] "It's a secret" - * = 25 (0x19) 00011001 - */ - { 0x49, 0x19 }, - - /* - * 4B Undocumented = 128 (0x80) 10000000 - * 4B[7:0] "It's a secret" - * = 128 (0x80) 10000000 - */ - { 0x4b, 0x80 }, - - /* - * 4D Undocumented = 196 (0xC4) 11000100 - * 4D[7:0] "It's a secret" - * = 196 (0xC4) 11000100 - */ - { 0x4d, 0xc4 }, - - /* - * 35 VREF "Reference Voltage Control" - * = 76 (0x4c) 01001100 - * VREF[7:5] "Column high reference control" - * = 2 (0x02) 010..... "higher voltage" - * VREF[4:2] "Column low reference control" - * = 3 (0x03) ...011.. "Highest voltage" - * VREF[1:0] "Reserved" - * = 0 (0x00) ......00 - */ - { 0x35, 0x4c }, - - /* - * 3D Undocumented = 0 (0x00) 00000000 - * 3D[7:0] "It's a secret" - * = 0 (0x00) 00000000 - */ - { 0x3d, 0x00 }, - - /* - * 3E Undocumented = 0 (0x00) 00000000 - * 3E[7:0] "It's a secret" - * = 0 (0x00) 00000000 - */ - { 0x3e, 0x00 }, - - /* - * 3B FREFB "Internal Reference Adjustment" - * = 24 (0x18) 00011000 - * FREFB[7:0] "Range" - * = 24 (0x18) 00011000 - */ - { 0x3b, 0x18 }, - - /* - * 33 CHLF "Current Control" - * = 25 (0x19) 00011001 - * CHLF[7:6] "Sensor current control" - * = 0 (0x00) 00...... - * CHLF[5] "Sensor current range control" - * = 0 (0x00) ..0..... "normal range" - * CHLF[4] "Sensor current" - * = 1 (0x01) ...1.... "double current" - * CHLF[3] "Sensor buffer current control" - * = 1 (0x01) ....1... "half current" - * CHLF[2] "Column buffer current control" - * = 0 (0x00) .....0.. "normal current" - * CHLF[1] "Analog DSP current control" - * = 0 (0x00) ......0. "normal current" - * CHLF[1] "ADC current control" - * = 0 (0x00) ......0. "normal current" - */ - { 0x33, 0x19 }, - - /* - * 34 VBLM "Blooming Control" - * = 90 (0x5A) 01011010 - * VBLM[7] "Hard soft reset switch" - * = 0 (0x00) 0....... "Hard reset" - * VBLM[6:4] "Blooming voltage selection" - * = 5 (0x05) .101.... - * VBLM[3:0] "Sensor current control" - * = 10 (0x0A) ....1010 - */ - { 0x34, 0x5a }, - - /* - * 3B FREFB "Internal Reference Adjustment" - * = 0 (0x00) 00000000 - * FREFB[7:0] "Range" - * = 0 (0x00) 00000000 - */ - { 0x3b, 0x00 }, - - /* - * 33 CHLF "Current Control" - * = 9 (0x09) 00001001 - * CHLF[7:6] "Sensor current control" - * = 0 (0x00) 00...... - * CHLF[5] "Sensor current range control" - * = 0 (0x00) ..0..... "normal range" - * CHLF[4] "Sensor current" - * = 0 (0x00) ...0.... "normal current" - * CHLF[3] "Sensor buffer current control" - * = 1 (0x01) ....1... "half current" - * CHLF[2] "Column buffer current control" - * = 0 (0x00) .....0.. "normal current" - * CHLF[1] "Analog DSP current control" - * = 0 (0x00) ......0. "normal current" - * CHLF[1] "ADC current control" - * = 0 (0x00) ......0. "normal current" - */ - { 0x33, 0x09 }, - - /* - * 34 VBLM "Blooming Control" - * = 80 (0x50) 01010000 - * VBLM[7] "Hard soft reset switch" - * = 0 (0x00) 0....... "Hard reset" - * VBLM[6:4] "Blooming voltage selection" - * = 5 (0x05) .101.... - * VBLM[3:0] "Sensor current control" - * = 0 (0x00) ....0000 - */ - { 0x34, 0x50 }, - - /* - * 12 COMH "Common Control H" - * = 64 (0x40) 01000000 - * COMH[7] "SRST" - * = 0 (0x00) 0....... "No-op" - * COMH[6:4] "Resolution selection" - * = 4 (0x04) .100.... "XGA" - * COMH[3] "Master slave selection" - * = 0 (0x00) ....0... "Master mode" - * COMH[2] "Internal B/R channel option" - * = 0 (0x00) .....0.. "B/R use same channel" - * COMH[1] "Color bar test pattern" - * = 0 (0x00) ......0. "Off" - * COMH[0] "Reserved" - * = 0 (0x00) .......0 - */ - { 0x12, 0x40 }, - - /* - * 17 HREFST "Horizontal window start" - * = 31 (0x1F) 00011111 - * HREFST[7:0] "Horizontal window start, 8 MSBs" - * = 31 (0x1F) 00011111 - */ - { 0x17, 0x1f }, - - /* - * 18 HREFEND "Horizontal window end" - * = 95 (0x5F) 01011111 - * HREFEND[7:0] "Horizontal Window End, 8 MSBs" - * = 95 (0x5F) 01011111 - */ - { 0x18, 0x5f }, - - /* - * 19 VSTRT "Vertical window start" - * = 0 (0x00) 00000000 - * VSTRT[7:0] "Vertical Window Start, 8 MSBs" - * = 0 (0x00) 00000000 - */ - { 0x19, 0x00 }, - - /* - * 1A VEND "Vertical window end" - * = 96 (0x60) 01100000 - * VEND[7:0] "Vertical Window End, 8 MSBs" - * = 96 (0x60) 01100000 - */ - { 0x1a, 0x60 }, - - /* - * 32 COMM "Common Control M" - * = 18 (0x12) 00010010 - * COMM[7:6] "Pixel clock divide option" - * = 0 (0x00) 00...... "/1" - * COMM[5:3] "Horizontal window end position, 3 LSBs" - * = 2 (0x02) ..010... - * COMM[2:0] "Horizontal window start position, 3 LSBs" - * = 2 (0x02) .....010 - */ - { 0x32, 0x12 }, - - /* - * 03 COMA "Common Control A" - * = 74 (0x4A) 01001010 - * COMA[7:4] "AWB Update Threshold" - * = 4 (0x04) 0100.... - * COMA[3:2] "Vertical window end line control 2 LSBs" - * = 2 (0x02) ....10.. - * COMA[1:0] "Vertical window start line control 2 LSBs" - * = 2 (0x02) ......10 - */ - { 0x03, 0x4a }, - - /* - * 11 CLKRC "Clock Rate Control" - * = 128 (0x80) 10000000 - * CLKRC[7] "Internal frequency doublers on off seclection" - * = 1 (0x01) 1....... "On" - * CLKRC[6] "Digital video master slave selection" - * = 0 (0x00) .0...... "Master mode, sensor - * provides PCLK" - * CLKRC[5:0] "Clock divider { CLK = PCLK/(1+CLKRC[5:0]) }" - * = 0 (0x00) ..000000 - */ - { 0x11, 0x80 }, - - /* - * 12 COMH "Common Control H" - * = 0 (0x00) 00000000 - * COMH[7] "SRST" - * = 0 (0x00) 0....... "No-op" - * COMH[6:4] "Resolution selection" - * = 0 (0x00) .000.... "QXGA" - * COMH[3] "Master slave selection" - * = 0 (0x00) ....0... "Master mode" - * COMH[2] "Internal B/R channel option" - * = 0 (0x00) .....0.. "B/R use same channel" - * COMH[1] "Color bar test pattern" - * = 0 (0x00) ......0. "Off" - * COMH[0] "Reserved" - * = 0 (0x00) .......0 - */ - { 0x12, 0x00 }, - - /* - * 12 COMH "Common Control H" - * = 64 (0x40) 01000000 - * COMH[7] "SRST" - * = 0 (0x00) 0....... "No-op" - * COMH[6:4] "Resolution selection" - * = 4 (0x04) .100.... "XGA" - * COMH[3] "Master slave selection" - * = 0 (0x00) ....0... "Master mode" - * COMH[2] "Internal B/R channel option" - * = 0 (0x00) .....0.. "B/R use same channel" - * COMH[1] "Color bar test pattern" - * = 0 (0x00) ......0. "Off" - * COMH[0] "Reserved" - * = 0 (0x00) .......0 - */ - { 0x12, 0x40 }, - - /* - * 17 HREFST "Horizontal window start" - * = 31 (0x1F) 00011111 - * HREFST[7:0] "Horizontal window start, 8 MSBs" - * = 31 (0x1F) 00011111 - */ - { 0x17, 0x1f }, - - /* - * 18 HREFEND "Horizontal window end" - * = 95 (0x5F) 01011111 - * HREFEND[7:0] "Horizontal Window End, 8 MSBs" - * = 95 (0x5F) 01011111 - */ - { 0x18, 0x5f }, - - /* - * 19 VSTRT "Vertical window start" - * = 0 (0x00) 00000000 - * VSTRT[7:0] "Vertical Window Start, 8 MSBs" - * = 0 (0x00) 00000000 - */ - { 0x19, 0x00 }, - - /* - * 1A VEND "Vertical window end" - * = 96 (0x60) 01100000 - * VEND[7:0] "Vertical Window End, 8 MSBs" - * = 96 (0x60) 01100000 - */ - { 0x1a, 0x60 }, - - /* - * 32 COMM "Common Control M" - * = 18 (0x12) 00010010 - * COMM[7:6] "Pixel clock divide option" - * = 0 (0x00) 00...... "/1" - * COMM[5:3] "Horizontal window end position, 3 LSBs" - * = 2 (0x02) ..010... - * COMM[2:0] "Horizontal window start position, 3 LSBs" - * = 2 (0x02) .....010 - */ - { 0x32, 0x12 }, - - /* - * 03 COMA "Common Control A" - * = 74 (0x4A) 01001010 - * COMA[7:4] "AWB Update Threshold" - * = 4 (0x04) 0100.... - * COMA[3:2] "Vertical window end line control 2 LSBs" - * = 2 (0x02) ....10.. - * COMA[1:0] "Vertical window start line control 2 LSBs" - * = 2 (0x02) ......10 - */ - { 0x03, 0x4a }, - - /* - * 02 RED "Red Gain Control" - * = 175 (0xAF) 10101111 - * RED[7] "Action" - * = 1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))" - * RED[6:0] "Value" - * = 47 (0x2F) .0101111 - */ - { 0x02, 0xaf }, - - /* - * 2D ADDVSL "VSYNC Pulse Width" - * = 210 (0xD2) 11010010 - * ADDVSL[7:0] "VSYNC pulse width, LSB" - * = 210 (0xD2) 11010010 - */ - { 0x2d, 0xd2 }, - - /* - * 00 GAIN = 24 (0x18) 00011000 - * GAIN[7:6] "Reserved" - * = 0 (0x00) 00...... - * GAIN[5] "Double" - * = 0 (0x00) ..0..... "False" - * GAIN[4] "Double" - * = 1 (0x01) ...1.... "True" - * GAIN[3:0] "Range" - * = 8 (0x08) ....1000 - */ - { 0x00, 0x18 }, - - /* - * 01 BLUE "Blue Gain Control" - * = 240 (0xF0) 11110000 - * BLUE[7] "Action" - * = 1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))" - * BLUE[6:0] "Value" - * = 112 (0x70) .1110000 - */ - { 0x01, 0xf0 }, - - /* - * 10 AEC "Automatic Exposure Control" - * = 10 (0x0A) 00001010 - * AEC[7:0] "Automatic Exposure Control, 8 MSBs" - * = 10 (0x0A) 00001010 - */ - { 0x10, 0x0a }, - - { 0xe1, 0x67 }, - { 0xe3, 0x03 }, - { 0xe4, 0x26 }, - { 0xe5, 0x3e }, - { 0xf8, 0x01 }, - { 0xff, 0x01 }, -}; - -static const struct ov_i2c_regvals norm_6x20[] = { - { 0x12, 0x80 }, /* reset */ - { 0x11, 0x01 }, - { 0x03, 0x60 }, - { 0x05, 0x7f }, /* For when autoadjust is off */ - { 0x07, 0xa8 }, - /* The ratio of 0x0c and 0x0d controls the white point */ - { 0x0c, 0x24 }, - { 0x0d, 0x24 }, - { 0x0f, 0x15 }, /* COMS */ - { 0x10, 0x75 }, /* AEC Exposure time */ - { 0x12, 0x24 }, /* Enable AGC */ - { 0x14, 0x04 }, - /* 0x16: 0x06 helps frame stability with moving objects */ - { 0x16, 0x06 }, -/* { 0x20, 0x30 }, * Aperture correction enable */ - { 0x26, 0xb2 }, /* BLC enable */ - /* 0x28: 0x05 Selects RGB format if RGB on */ - { 0x28, 0x05 }, - { 0x2a, 0x04 }, /* Disable framerate adjust */ -/* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */ - { 0x2d, 0x85 }, - { 0x33, 0xa0 }, /* Color Processing Parameter */ - { 0x34, 0xd2 }, /* Max A/D range */ - { 0x38, 0x8b }, - { 0x39, 0x40 }, - - { 0x3c, 0x39 }, /* Enable AEC mode changing */ - { 0x3c, 0x3c }, /* Change AEC mode */ - { 0x3c, 0x24 }, /* Disable AEC mode changing */ - - { 0x3d, 0x80 }, - /* These next two registers (0x4a, 0x4b) are undocumented. - * They control the color balance */ - { 0x4a, 0x80 }, - { 0x4b, 0x80 }, - { 0x4d, 0xd2 }, /* This reduces noise a bit */ - { 0x4e, 0xc1 }, - { 0x4f, 0x04 }, -/* Do 50-53 have any effect? */ -/* Toggle 0x12[2] off and on here? */ -}; - -static const struct ov_i2c_regvals norm_6x30[] = { - { 0x12, 0x80 }, /* Reset */ - { 0x00, 0x1f }, /* Gain */ - { 0x01, 0x99 }, /* Blue gain */ - { 0x02, 0x7c }, /* Red gain */ - { 0x03, 0xc0 }, /* Saturation */ - { 0x05, 0x0a }, /* Contrast */ - { 0x06, 0x95 }, /* Brightness */ - { 0x07, 0x2d }, /* Sharpness */ - { 0x0c, 0x20 }, - { 0x0d, 0x20 }, - { 0x0e, 0xa0 }, /* Was 0x20, bit7 enables a 2x gain which we need */ - { 0x0f, 0x05 }, - { 0x10, 0x9a }, - { 0x11, 0x00 }, /* Pixel clock = fastest */ - { 0x12, 0x24 }, /* Enable AGC and AWB */ - { 0x13, 0x21 }, - { 0x14, 0x80 }, - { 0x15, 0x01 }, - { 0x16, 0x03 }, - { 0x17, 0x38 }, - { 0x18, 0xea }, - { 0x19, 0x04 }, - { 0x1a, 0x93 }, - { 0x1b, 0x00 }, - { 0x1e, 0xc4 }, - { 0x1f, 0x04 }, - { 0x20, 0x20 }, - { 0x21, 0x10 }, - { 0x22, 0x88 }, - { 0x23, 0xc0 }, /* Crystal circuit power level */ - { 0x25, 0x9a }, /* Increase AEC black ratio */ - { 0x26, 0xb2 }, /* BLC enable */ - { 0x27, 0xa2 }, - { 0x28, 0x00 }, - { 0x29, 0x00 }, - { 0x2a, 0x84 }, /* 60 Hz power */ - { 0x2b, 0xa8 }, /* 60 Hz power */ - { 0x2c, 0xa0 }, - { 0x2d, 0x95 }, /* Enable auto-brightness */ - { 0x2e, 0x88 }, - { 0x33, 0x26 }, - { 0x34, 0x03 }, - { 0x36, 0x8f }, - { 0x37, 0x80 }, - { 0x38, 0x83 }, - { 0x39, 0x80 }, - { 0x3a, 0x0f }, - { 0x3b, 0x3c }, - { 0x3c, 0x1a }, - { 0x3d, 0x80 }, - { 0x3e, 0x80 }, - { 0x3f, 0x0e }, - { 0x40, 0x00 }, /* White bal */ - { 0x41, 0x00 }, /* White bal */ - { 0x42, 0x80 }, - { 0x43, 0x3f }, /* White bal */ - { 0x44, 0x80 }, - { 0x45, 0x20 }, - { 0x46, 0x20 }, - { 0x47, 0x80 }, - { 0x48, 0x7f }, - { 0x49, 0x00 }, - { 0x4a, 0x00 }, - { 0x4b, 0x80 }, - { 0x4c, 0xd0 }, - { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */ - { 0x4e, 0x40 }, - { 0x4f, 0x07 }, /* UV avg., col. killer: max */ - { 0x50, 0xff }, - { 0x54, 0x23 }, /* Max AGC gain: 18dB */ - { 0x55, 0xff }, - { 0x56, 0x12 }, - { 0x57, 0x81 }, - { 0x58, 0x75 }, - { 0x59, 0x01 }, /* AGC dark current comp.: +1 */ - { 0x5a, 0x2c }, - { 0x5b, 0x0f }, /* AWB chrominance levels */ - { 0x5c, 0x10 }, - { 0x3d, 0x80 }, - { 0x27, 0xa6 }, - { 0x12, 0x20 }, /* Toggle AWB */ - { 0x12, 0x24 }, -}; - -/* Lawrence Glaister <lg@jfm.bc.ca> reports: - * - * Register 0x0f in the 7610 has the following effects: - * - * 0x85 (AEC method 1): Best overall, good contrast range - * 0x45 (AEC method 2): Very overexposed - * 0xa5 (spec sheet default): Ok, but the black level is - * shifted resulting in loss of contrast - * 0x05 (old driver setting): very overexposed, too much - * contrast - */ -static const struct ov_i2c_regvals norm_7610[] = { - { 0x10, 0xff }, - { 0x16, 0x06 }, - { 0x28, 0x24 }, - { 0x2b, 0xac }, - { 0x12, 0x00 }, - { 0x38, 0x81 }, - { 0x28, 0x24 }, /* 0c */ - { 0x0f, 0x85 }, /* lg's setting */ - { 0x15, 0x01 }, - { 0x20, 0x1c }, - { 0x23, 0x2a }, - { 0x24, 0x10 }, - { 0x25, 0x8a }, - { 0x26, 0xa2 }, - { 0x27, 0xc2 }, - { 0x2a, 0x04 }, - { 0x2c, 0xfe }, - { 0x2d, 0x93 }, - { 0x30, 0x71 }, - { 0x31, 0x60 }, - { 0x32, 0x26 }, - { 0x33, 0x20 }, - { 0x34, 0x48 }, - { 0x12, 0x24 }, - { 0x11, 0x01 }, - { 0x0c, 0x24 }, - { 0x0d, 0x24 }, -}; - -static const struct ov_i2c_regvals norm_7620[] = { - { 0x12, 0x80 }, /* reset */ - { 0x00, 0x00 }, /* gain */ - { 0x01, 0x80 }, /* blue gain */ - { 0x02, 0x80 }, /* red gain */ - { 0x03, 0xc0 }, /* OV7670_R03_VREF */ - { 0x06, 0x60 }, - { 0x07, 0x00 }, - { 0x0c, 0x24 }, - { 0x0c, 0x24 }, - { 0x0d, 0x24 }, - { 0x11, 0x01 }, - { 0x12, 0x24 }, - { 0x13, 0x01 }, - { 0x14, 0x84 }, - { 0x15, 0x01 }, - { 0x16, 0x03 }, - { 0x17, 0x2f }, - { 0x18, 0xcf }, - { 0x19, 0x06 }, - { 0x1a, 0xf5 }, - { 0x1b, 0x00 }, - { 0x20, 0x18 }, - { 0x21, 0x80 }, - { 0x22, 0x80 }, - { 0x23, 0x00 }, - { 0x26, 0xa2 }, - { 0x27, 0xea }, - { 0x28, 0x22 }, /* Was 0x20, bit1 enables a 2x gain which we need */ - { 0x29, 0x00 }, - { 0x2a, 0x10 }, - { 0x2b, 0x00 }, - { 0x2c, 0x88 }, - { 0x2d, 0x91 }, - { 0x2e, 0x80 }, - { 0x2f, 0x44 }, - { 0x60, 0x27 }, - { 0x61, 0x02 }, - { 0x62, 0x5f }, - { 0x63, 0xd5 }, - { 0x64, 0x57 }, - { 0x65, 0x83 }, - { 0x66, 0x55 }, - { 0x67, 0x92 }, - { 0x68, 0xcf }, - { 0x69, 0x76 }, - { 0x6a, 0x22 }, - { 0x6b, 0x00 }, - { 0x6c, 0x02 }, - { 0x6d, 0x44 }, - { 0x6e, 0x80 }, - { 0x6f, 0x1d }, - { 0x70, 0x8b }, - { 0x71, 0x00 }, - { 0x72, 0x14 }, - { 0x73, 0x54 }, - { 0x74, 0x00 }, - { 0x75, 0x8e }, - { 0x76, 0x00 }, - { 0x77, 0xff }, - { 0x78, 0x80 }, - { 0x79, 0x80 }, - { 0x7a, 0x80 }, - { 0x7b, 0xe2 }, - { 0x7c, 0x00 }, -}; - -/* 7640 and 7648. The defaults should be OK for most registers. */ -static const struct ov_i2c_regvals norm_7640[] = { - { 0x12, 0x80 }, - { 0x12, 0x14 }, -}; - -static const struct ov_regvals init_519_ov7660[] = { - { 0x5d, 0x03 }, /* Turn off suspend mode */ - { 0x53, 0x9b }, /* 0x9f enables the (unused) microcontroller */ - { 0x54, 0x0f }, /* bit2 (jpeg enable) */ - { 0xa2, 0x20 }, /* a2-a5 are undocumented */ - { 0xa3, 0x18 }, - { 0xa4, 0x04 }, - { 0xa5, 0x28 }, - { 0x37, 0x00 }, /* SetUsbInit */ - { 0x55, 0x02 }, /* 4.096 Mhz audio clock */ - /* Enable both fields, YUV Input, disable defect comp (why?) */ - { 0x20, 0x0c }, /* 0x0d does U <-> V swap */ - { 0x21, 0x38 }, - { 0x22, 0x1d }, - { 0x17, 0x50 }, /* undocumented */ - { 0x37, 0x00 }, /* undocumented */ - { 0x40, 0xff }, /* I2C timeout counter */ - { 0x46, 0x00 }, /* I2C clock prescaler */ -}; -static const struct ov_i2c_regvals norm_7660[] = { - {OV7670_R12_COM7, OV7670_COM7_RESET}, - {OV7670_R11_CLKRC, 0x81}, - {0x92, 0x00}, /* DM_LNL */ - {0x93, 0x00}, /* DM_LNH */ - {0x9d, 0x4c}, /* BD50ST */ - {0x9e, 0x3f}, /* BD60ST */ - {OV7670_R3B_COM11, 0x02}, - {OV7670_R13_COM8, 0xf5}, - {OV7670_R10_AECH, 0x00}, - {OV7670_R00_GAIN, 0x00}, - {OV7670_R01_BLUE, 0x7c}, - {OV7670_R02_RED, 0x9d}, - {OV7670_R12_COM7, 0x00}, - {OV7670_R04_COM1, 00}, - {OV7670_R18_HSTOP, 0x01}, - {OV7670_R17_HSTART, 0x13}, - {OV7670_R32_HREF, 0x92}, - {OV7670_R19_VSTART, 0x02}, - {OV7670_R1A_VSTOP, 0x7a}, - {OV7670_R03_VREF, 0x00}, - {OV7670_R0E_COM5, 0x04}, - {OV7670_R0F_COM6, 0x62}, - {OV7670_R15_COM10, 0x00}, - {0x16, 0x02}, /* RSVD */ - {0x1b, 0x00}, /* PSHFT */ - {OV7670_R1E_MVFP, 0x01}, - {0x29, 0x3c}, /* RSVD */ - {0x33, 0x00}, /* CHLF */ - {0x34, 0x07}, /* ARBLM */ - {0x35, 0x84}, /* RSVD */ - {0x36, 0x00}, /* RSVD */ - {0x37, 0x04}, /* ADC */ - {0x39, 0x43}, /* OFON */ - {OV7670_R3A_TSLB, 0x00}, - {OV7670_R3C_COM12, 0x6c}, - {OV7670_R3D_COM13, 0x98}, - {OV7670_R3F_EDGE, 0x23}, - {OV7670_R40_COM15, 0xc1}, - {OV7670_R41_COM16, 0x22}, - {0x6b, 0x0a}, /* DBLV */ - {0xa1, 0x08}, /* RSVD */ - {0x69, 0x80}, /* HV */ - {0x43, 0xf0}, /* RSVD.. */ - {0x44, 0x10}, - {0x45, 0x78}, - {0x46, 0xa8}, - {0x47, 0x60}, - {0x48, 0x80}, - {0x59, 0xba}, - {0x5a, 0x9a}, - {0x5b, 0x22}, - {0x5c, 0xb9}, - {0x5d, 0x9b}, - {0x5e, 0x10}, - {0x5f, 0xe0}, - {0x60, 0x85}, - {0x61, 0x60}, - {0x9f, 0x9d}, /* RSVD */ - {0xa0, 0xa0}, /* DSPC2 */ - {0x4f, 0x60}, /* matrix */ - {0x50, 0x64}, - {0x51, 0x04}, - {0x52, 0x18}, - {0x53, 0x3c}, - {0x54, 0x54}, - {0x55, 0x40}, - {0x56, 0x40}, - {0x57, 0x40}, - {0x58, 0x0d}, /* matrix sign */ - {0x8b, 0xcc}, /* RSVD */ - {0x8c, 0xcc}, - {0x8d, 0xcf}, - {0x6c, 0x40}, /* gamma curve */ - {0x6d, 0xe0}, - {0x6e, 0xa0}, - {0x6f, 0x80}, - {0x70, 0x70}, - {0x71, 0x80}, - {0x72, 0x60}, - {0x73, 0x60}, - {0x74, 0x50}, - {0x75, 0x40}, - {0x76, 0x38}, - {0x77, 0x3c}, - {0x78, 0x32}, - {0x79, 0x1a}, - {0x7a, 0x28}, - {0x7b, 0x24}, - {0x7c, 0x04}, /* gamma curve */ - {0x7d, 0x12}, - {0x7e, 0x26}, - {0x7f, 0x46}, - {0x80, 0x54}, - {0x81, 0x64}, - {0x82, 0x70}, - {0x83, 0x7c}, - {0x84, 0x86}, - {0x85, 0x8e}, - {0x86, 0x9c}, - {0x87, 0xab}, - {0x88, 0xc4}, - {0x89, 0xd1}, - {0x8a, 0xe5}, - {OV7670_R14_COM9, 0x1e}, - {OV7670_R24_AEW, 0x80}, - {OV7670_R25_AEB, 0x72}, - {OV7670_R26_VPT, 0xb3}, - {0x62, 0x80}, /* LCC1 */ - {0x63, 0x80}, /* LCC2 */ - {0x64, 0x06}, /* LCC3 */ - {0x65, 0x00}, /* LCC4 */ - {0x66, 0x01}, /* LCC5 */ - {0x94, 0x0e}, /* RSVD.. */ - {0x95, 0x14}, - {OV7670_R13_COM8, OV7670_COM8_FASTAEC - | OV7670_COM8_AECSTEP - | OV7670_COM8_BFILT - | 0x10 - | OV7670_COM8_AGC - | OV7670_COM8_AWB - | OV7670_COM8_AEC}, - {0xa1, 0xc8} -}; -static const struct ov_i2c_regvals norm_9600[] = { - {0x12, 0x80}, - {0x0c, 0x28}, - {0x11, 0x80}, - {0x13, 0xb5}, - {0x14, 0x3e}, - {0x1b, 0x04}, - {0x24, 0xb0}, - {0x25, 0x90}, - {0x26, 0x94}, - {0x35, 0x90}, - {0x37, 0x07}, - {0x38, 0x08}, - {0x01, 0x8e}, - {0x02, 0x85} -}; - -/* 7670. Defaults taken from OmniVision provided data, -* as provided by Jonathan Corbet of OLPC */ -static const struct ov_i2c_regvals norm_7670[] = { - { OV7670_R12_COM7, OV7670_COM7_RESET }, - { OV7670_R3A_TSLB, 0x04 }, /* OV */ - { OV7670_R12_COM7, OV7670_COM7_FMT_VGA }, /* VGA */ - { OV7670_R11_CLKRC, 0x01 }, -/* - * Set the hardware window. These values from OV don't entirely - * make sense - hstop is less than hstart. But they work... - */ - { OV7670_R17_HSTART, 0x13 }, - { OV7670_R18_HSTOP, 0x01 }, - { OV7670_R32_HREF, 0xb6 }, - { OV7670_R19_VSTART, 0x02 }, - { OV7670_R1A_VSTOP, 0x7a }, - { OV7670_R03_VREF, 0x0a }, - - { OV7670_R0C_COM3, 0x00 }, - { OV7670_R3E_COM14, 0x00 }, -/* Mystery scaling numbers */ - { 0x70, 0x3a }, - { 0x71, 0x35 }, - { 0x72, 0x11 }, - { 0x73, 0xf0 }, - { 0xa2, 0x02 }, -/* { OV7670_R15_COM10, 0x0 }, */ - -/* Gamma curve values */ - { 0x7a, 0x20 }, - { 0x7b, 0x10 }, - { 0x7c, 0x1e }, - { 0x7d, 0x35 }, - { 0x7e, 0x5a }, - { 0x7f, 0x69 }, - { 0x80, 0x76 }, - { 0x81, 0x80 }, - { 0x82, 0x88 }, - { 0x83, 0x8f }, - { 0x84, 0x96 }, - { 0x85, 0xa3 }, - { 0x86, 0xaf }, - { 0x87, 0xc4 }, - { 0x88, 0xd7 }, - { 0x89, 0xe8 }, - -/* AGC and AEC parameters. Note we start by disabling those features, - then turn them only after tweaking the values. */ - { OV7670_R13_COM8, OV7670_COM8_FASTAEC - | OV7670_COM8_AECSTEP - | OV7670_COM8_BFILT }, - { OV7670_R00_GAIN, 0x00 }, - { OV7670_R10_AECH, 0x00 }, - { OV7670_R0D_COM4, 0x40 }, /* magic reserved bit */ - { OV7670_R14_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ - { OV7670_RA5_BD50MAX, 0x05 }, - { OV7670_RAB_BD60MAX, 0x07 }, - { OV7670_R24_AEW, 0x95 }, - { OV7670_R25_AEB, 0x33 }, - { OV7670_R26_VPT, 0xe3 }, - { OV7670_R9F_HAECC1, 0x78 }, - { OV7670_RA0_HAECC2, 0x68 }, - { 0xa1, 0x03 }, /* magic */ - { OV7670_RA6_HAECC3, 0xd8 }, - { OV7670_RA7_HAECC4, 0xd8 }, - { OV7670_RA8_HAECC5, 0xf0 }, - { OV7670_RA9_HAECC6, 0x90 }, - { OV7670_RAA_HAECC7, 0x94 }, - { OV7670_R13_COM8, OV7670_COM8_FASTAEC - | OV7670_COM8_AECSTEP - | OV7670_COM8_BFILT - | OV7670_COM8_AGC - | OV7670_COM8_AEC }, - -/* Almost all of these are magic "reserved" values. */ - { OV7670_R0E_COM5, 0x61 }, - { OV7670_R0F_COM6, 0x4b }, - { 0x16, 0x02 }, - { OV7670_R1E_MVFP, 0x07 }, - { 0x21, 0x02 }, - { 0x22, 0x91 }, - { 0x29, 0x07 }, - { 0x33, 0x0b }, - { 0x35, 0x0b }, - { 0x37, 0x1d }, - { 0x38, 0x71 }, - { 0x39, 0x2a }, - { OV7670_R3C_COM12, 0x78 }, - { 0x4d, 0x40 }, - { 0x4e, 0x20 }, - { OV7670_R69_GFIX, 0x00 }, - { 0x6b, 0x4a }, - { 0x74, 0x10 }, - { 0x8d, 0x4f }, - { 0x8e, 0x00 }, - { 0x8f, 0x00 }, - { 0x90, 0x00 }, - { 0x91, 0x00 }, - { 0x96, 0x00 }, - { 0x9a, 0x00 }, - { 0xb0, 0x84 }, - { 0xb1, 0x0c }, - { 0xb2, 0x0e }, - { 0xb3, 0x82 }, - { 0xb8, 0x0a }, - -/* More reserved magic, some of which tweaks white balance */ - { 0x43, 0x0a }, - { 0x44, 0xf0 }, - { 0x45, 0x34 }, - { 0x46, 0x58 }, - { 0x47, 0x28 }, - { 0x48, 0x3a }, - { 0x59, 0x88 }, - { 0x5a, 0x88 }, - { 0x5b, 0x44 }, - { 0x5c, 0x67 }, - { 0x5d, 0x49 }, - { 0x5e, 0x0e }, - { 0x6c, 0x0a }, - { 0x6d, 0x55 }, - { 0x6e, 0x11 }, - { 0x6f, 0x9f }, /* "9e for advance AWB" */ - { 0x6a, 0x40 }, - { OV7670_R01_BLUE, 0x40 }, - { OV7670_R02_RED, 0x60 }, - { OV7670_R13_COM8, OV7670_COM8_FASTAEC - | OV7670_COM8_AECSTEP - | OV7670_COM8_BFILT - | OV7670_COM8_AGC - | OV7670_COM8_AEC - | OV7670_COM8_AWB }, - -/* Matrix coefficients */ - { 0x4f, 0x80 }, - { 0x50, 0x80 }, - { 0x51, 0x00 }, - { 0x52, 0x22 }, - { 0x53, 0x5e }, - { 0x54, 0x80 }, - { 0x58, 0x9e }, - - { OV7670_R41_COM16, OV7670_COM16_AWBGAIN }, - { OV7670_R3F_EDGE, 0x00 }, - { 0x75, 0x05 }, - { 0x76, 0xe1 }, - { 0x4c, 0x00 }, - { 0x77, 0x01 }, - { OV7670_R3D_COM13, OV7670_COM13_GAMMA - | OV7670_COM13_UVSAT - | 2}, /* was 3 */ - { 0x4b, 0x09 }, - { 0xc9, 0x60 }, - { OV7670_R41_COM16, 0x38 }, - { 0x56, 0x40 }, - - { 0x34, 0x11 }, - { OV7670_R3B_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO }, - { 0xa4, 0x88 }, - { 0x96, 0x00 }, - { 0x97, 0x30 }, - { 0x98, 0x20 }, - { 0x99, 0x30 }, - { 0x9a, 0x84 }, - { 0x9b, 0x29 }, - { 0x9c, 0x03 }, - { 0x9d, 0x4c }, - { 0x9e, 0x3f }, - { 0x78, 0x04 }, - -/* Extra-weird stuff. Some sort of multiplexor register */ - { 0x79, 0x01 }, - { 0xc8, 0xf0 }, - { 0x79, 0x0f }, - { 0xc8, 0x00 }, - { 0x79, 0x10 }, - { 0xc8, 0x7e }, - { 0x79, 0x0a }, - { 0xc8, 0x80 }, - { 0x79, 0x0b }, - { 0xc8, 0x01 }, - { 0x79, 0x0c }, - { 0xc8, 0x0f }, - { 0x79, 0x0d }, - { 0xc8, 0x20 }, - { 0x79, 0x09 }, - { 0xc8, 0x80 }, - { 0x79, 0x02 }, - { 0xc8, 0xc0 }, - { 0x79, 0x03 }, - { 0xc8, 0x40 }, - { 0x79, 0x05 }, - { 0xc8, 0x30 }, - { 0x79, 0x26 }, -}; - -static const struct ov_i2c_regvals norm_8610[] = { - { 0x12, 0x80 }, - { 0x00, 0x00 }, - { 0x01, 0x80 }, - { 0x02, 0x80 }, - { 0x03, 0xc0 }, - { 0x04, 0x30 }, - { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */ - { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */ - { 0x0a, 0x86 }, - { 0x0b, 0xb0 }, - { 0x0c, 0x20 }, - { 0x0d, 0x20 }, - { 0x11, 0x01 }, - { 0x12, 0x25 }, - { 0x13, 0x01 }, - { 0x14, 0x04 }, - { 0x15, 0x01 }, /* Lin and Win think different about UV order */ - { 0x16, 0x03 }, - { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */ - { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */ - { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */ - { 0x1a, 0xf5 }, - { 0x1b, 0x00 }, - { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */ - { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */ - { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */ - { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */ - { 0x26, 0xa2 }, - { 0x27, 0xea }, - { 0x28, 0x00 }, - { 0x29, 0x00 }, - { 0x2a, 0x80 }, - { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */ - { 0x2c, 0xac }, - { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */ - { 0x2e, 0x80 }, - { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */ - { 0x4c, 0x00 }, - { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */ - { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */ - { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */ - { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */ - { 0x63, 0xff }, - { 0x64, 0x53 }, /* new windrv 090403 says 0x57, - * maybe thats wrong */ - { 0x65, 0x00 }, - { 0x66, 0x55 }, - { 0x67, 0xb0 }, - { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */ - { 0x69, 0x02 }, - { 0x6a, 0x22 }, - { 0x6b, 0x00 }, - { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but - * deleting bit7 colors the first images red */ - { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */ - { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */ - { 0x6f, 0x01 }, - { 0x70, 0x8b }, - { 0x71, 0x00 }, - { 0x72, 0x14 }, - { 0x73, 0x54 }, - { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */ - { 0x75, 0x0e }, - { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */ - { 0x77, 0xff }, - { 0x78, 0x80 }, - { 0x79, 0x80 }, - { 0x7a, 0x80 }, - { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */ - { 0x7c, 0x00 }, - { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */ - { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */ - { 0x7f, 0xfb }, - { 0x80, 0x28 }, - { 0x81, 0x00 }, - { 0x82, 0x23 }, - { 0x83, 0x0b }, - { 0x84, 0x00 }, - { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */ - { 0x86, 0xc9 }, - { 0x87, 0x00 }, - { 0x88, 0x00 }, - { 0x89, 0x01 }, - { 0x12, 0x20 }, - { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */ -}; - -static unsigned char ov7670_abs_to_sm(unsigned char v) -{ - if (v > 127) - return v & 0x7f; - return (128 - v) | 0x80; -} - -/* Write a OV519 register */ -static void reg_w(struct sd *sd, u16 index, u16 value) -{ - int ret, req = 0; - - if (sd->gspca_dev.usb_err < 0) - return; - - switch (sd->bridge) { - case BRIDGE_OV511: - case BRIDGE_OV511PLUS: - req = 2; - break; - case BRIDGE_OVFX2: - req = 0x0a; - /* fall through */ - case BRIDGE_W9968CF: - PDEBUG(D_USBO, "SET %02x %04x %04x", - req, value, index); - ret = usb_control_msg(sd->gspca_dev.dev, - usb_sndctrlpipe(sd->gspca_dev.dev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, NULL, 0, 500); - goto leave; - default: - req = 1; - } - - PDEBUG(D_USBO, "SET %02x 0000 %04x %02x", - req, index, value); - sd->gspca_dev.usb_buf[0] = value; - ret = usb_control_msg(sd->gspca_dev.dev, - usb_sndctrlpipe(sd->gspca_dev.dev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, index, - sd->gspca_dev.usb_buf, 1, 500); -leave: - if (ret < 0) { - pr_err("reg_w %02x failed %d\n", index, ret); - sd->gspca_dev.usb_err = ret; - return; - } -} - -/* Read from a OV519 register, note not valid for the w9968cf!! */ -/* returns: negative is error, pos or zero is data */ -static int reg_r(struct sd *sd, u16 index) -{ - int ret; - int req; - - if (sd->gspca_dev.usb_err < 0) - return -1; - - switch (sd->bridge) { - case BRIDGE_OV511: - case BRIDGE_OV511PLUS: - req = 3; - break; - case BRIDGE_OVFX2: - req = 0x0b; - break; - default: - req = 1; - } - - ret = usb_control_msg(sd->gspca_dev.dev, - usb_rcvctrlpipe(sd->gspca_dev.dev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, index, sd->gspca_dev.usb_buf, 1, 500); - - if (ret >= 0) { - ret = sd->gspca_dev.usb_buf[0]; - PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", - req, index, ret); - } else { - pr_err("reg_r %02x failed %d\n", index, ret); - sd->gspca_dev.usb_err = ret; - } - - return ret; -} - -/* Read 8 values from a OV519 register */ -static int reg_r8(struct sd *sd, - u16 index) -{ - int ret; - - if (sd->gspca_dev.usb_err < 0) - return -1; - - ret = usb_control_msg(sd->gspca_dev.dev, - usb_rcvctrlpipe(sd->gspca_dev.dev, 0), - 1, /* REQ_IO */ - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, index, sd->gspca_dev.usb_buf, 8, 500); - - if (ret >= 0) { - ret = sd->gspca_dev.usb_buf[0]; - } else { - pr_err("reg_r8 %02x failed %d\n", index, ret); - sd->gspca_dev.usb_err = ret; - } - - return ret; -} - -/* - * Writes bits at positions specified by mask to an OV51x reg. Bits that are in - * the same position as 1's in "mask" are cleared and set to "value". Bits - * that are in the same position as 0's in "mask" are preserved, regardless - * of their respective state in "value". - */ -static void reg_w_mask(struct sd *sd, - u16 index, - u8 value, - u8 mask) -{ - int ret; - u8 oldval; - - if (mask != 0xff) { - value &= mask; /* Enforce mask on value */ - ret = reg_r(sd, index); - if (ret < 0) - return; - - oldval = ret & ~mask; /* Clear the masked bits */ - value |= oldval; /* Set the desired bits */ - } - reg_w(sd, index, value); -} - -/* - * Writes multiple (n) byte value to a single register. Only valid with certain - * registers (0x30 and 0xc4 - 0xce). - */ -static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n) -{ - int ret; - - if (sd->gspca_dev.usb_err < 0) - return; - - *((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value); - - ret = usb_control_msg(sd->gspca_dev.dev, - usb_sndctrlpipe(sd->gspca_dev.dev, 0), - 1 /* REG_IO */, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, index, - sd->gspca_dev.usb_buf, n, 500); - if (ret < 0) { - pr_err("reg_w32 %02x failed %d\n", index, ret); - sd->gspca_dev.usb_err = ret; - } -} - -static void ov511_i2c_w(struct sd *sd, u8 reg, u8 value) -{ - int rc, retries; - - PDEBUG(D_USBO, "ov511_i2c_w %02x %02x", reg, value); - - /* Three byte write cycle */ - for (retries = 6; ; ) { - /* Select camera register */ - reg_w(sd, R51x_I2C_SADDR_3, reg); - - /* Write "value" to I2C data port of OV511 */ - reg_w(sd, R51x_I2C_DATA, value); - - /* Initiate 3-byte write cycle */ - reg_w(sd, R511_I2C_CTL, 0x01); - - do { - rc = reg_r(sd, R511_I2C_CTL); - } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ - - if (rc < 0) - return; - - if ((rc & 2) == 0) /* Ack? */ - break; - if (--retries < 0) { - PDEBUG(D_USBO, "i2c write retries exhausted"); - return; - } - } -} - -static int ov511_i2c_r(struct sd *sd, u8 reg) -{ - int rc, value, retries; - - /* Two byte write cycle */ - for (retries = 6; ; ) { - /* Select camera register */ - reg_w(sd, R51x_I2C_SADDR_2, reg); - - /* Initiate 2-byte write cycle */ - reg_w(sd, R511_I2C_CTL, 0x03); - - do { - rc = reg_r(sd, R511_I2C_CTL); - } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ - - if (rc < 0) - return rc; - - if ((rc & 2) == 0) /* Ack? */ - break; - - /* I2C abort */ - reg_w(sd, R511_I2C_CTL, 0x10); - - if (--retries < 0) { - PDEBUG(D_USBI, "i2c write retries exhausted"); - return -1; - } - } - - /* Two byte read cycle */ - for (retries = 6; ; ) { - /* Initiate 2-byte read cycle */ - reg_w(sd, R511_I2C_CTL, 0x05); - - do { - rc = reg_r(sd, R511_I2C_CTL); - } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ - - if (rc < 0) - return rc; - - if ((rc & 2) == 0) /* Ack? */ - break; - - /* I2C abort */ - reg_w(sd, R511_I2C_CTL, 0x10); - - if (--retries < 0) { - PDEBUG(D_USBI, "i2c read retries exhausted"); - return -1; - } - } - - value = reg_r(sd, R51x_I2C_DATA); - - PDEBUG(D_USBI, "ov511_i2c_r %02x %02x", reg, value); - - /* This is needed to make i2c_w() work */ - reg_w(sd, R511_I2C_CTL, 0x05); - - return value; -} - -/* - * The OV518 I2C I/O procedure is different, hence, this function. - * This is normally only called from i2c_w(). Note that this function - * always succeeds regardless of whether the sensor is present and working. - */ -static void ov518_i2c_w(struct sd *sd, - u8 reg, - u8 value) -{ - PDEBUG(D_USBO, "ov518_i2c_w %02x %02x", reg, value); - - /* Select camera register */ - reg_w(sd, R51x_I2C_SADDR_3, reg); - - /* Write "value" to I2C data port of OV511 */ - reg_w(sd, R51x_I2C_DATA, value); - - /* Initiate 3-byte write cycle */ - reg_w(sd, R518_I2C_CTL, 0x01); - - /* wait for write complete */ - msleep(4); - reg_r8(sd, R518_I2C_CTL); -} - -/* - * returns: negative is error, pos or zero is data - * - * The OV518 I2C I/O procedure is different, hence, this function. - * This is normally only called from i2c_r(). Note that this function - * always succeeds regardless of whether the sensor is present and working. - */ -static int ov518_i2c_r(struct sd *sd, u8 reg) -{ - int value; - - /* Select camera register */ - reg_w(sd, R51x_I2C_SADDR_2, reg); - - /* Initiate 2-byte write cycle */ - reg_w(sd, R518_I2C_CTL, 0x03); - reg_r8(sd, R518_I2C_CTL); - - /* Initiate 2-byte read cycle */ - reg_w(sd, R518_I2C_CTL, 0x05); - reg_r8(sd, R518_I2C_CTL); - - value = reg_r(sd, R51x_I2C_DATA); - PDEBUG(D_USBI, "ov518_i2c_r %02x %02x", reg, value); - return value; -} - -static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value) -{ - int ret; - - if (sd->gspca_dev.usb_err < 0) - return; - - ret = usb_control_msg(sd->gspca_dev.dev, - usb_sndctrlpipe(sd->gspca_dev.dev, 0), - 0x02, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - (u16) value, (u16) reg, NULL, 0, 500); - - if (ret < 0) { - pr_err("ovfx2_i2c_w %02x failed %d\n", reg, ret); - sd->gspca_dev.usb_err = ret; - } - - PDEBUG(D_USBO, "ovfx2_i2c_w %02x %02x", reg, value); -} - -static int ovfx2_i2c_r(struct sd *sd, u8 reg) -{ - int ret; - - if (sd->gspca_dev.usb_err < 0) - return -1; - - ret = usb_control_msg(sd->gspca_dev.dev, - usb_rcvctrlpipe(sd->gspca_dev.dev, 0), - 0x03, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, (u16) reg, sd->gspca_dev.usb_buf, 1, 500); - - if (ret >= 0) { - ret = sd->gspca_dev.usb_buf[0]; - PDEBUG(D_USBI, "ovfx2_i2c_r %02x %02x", reg, ret); - } else { - pr_err("ovfx2_i2c_r %02x failed %d\n", reg, ret); - sd->gspca_dev.usb_err = ret; - } - - return ret; -} - -static void i2c_w(struct sd *sd, u8 reg, u8 value) -{ - if (sd->sensor_reg_cache[reg] == value) - return; - - switch (sd->bridge) { - case BRIDGE_OV511: - case BRIDGE_OV511PLUS: - ov511_i2c_w(sd, reg, value); - break; - case BRIDGE_OV518: - case BRIDGE_OV518PLUS: - case BRIDGE_OV519: - ov518_i2c_w(sd, reg, value); - break; - case BRIDGE_OVFX2: - ovfx2_i2c_w(sd, reg, value); - break; - case BRIDGE_W9968CF: - w9968cf_i2c_w(sd, reg, value); - break; - } - - if (sd->gspca_dev.usb_err >= 0) { - /* Up on sensor reset empty the register cache */ - if (reg == 0x12 && (value & 0x80)) - memset(sd->sensor_reg_cache, -1, - sizeof(sd->sensor_reg_cache)); - else - sd->sensor_reg_cache[reg] = value; - } -} - -static int i2c_r(struct sd *sd, u8 reg) -{ - int ret = -1; - - if (sd->sensor_reg_cache[reg] != -1) - return sd->sensor_reg_cache[reg]; - - switch (sd->bridge) { - case BRIDGE_OV511: - case BRIDGE_OV511PLUS: - ret = ov511_i2c_r(sd, reg); - break; - case BRIDGE_OV518: - case BRIDGE_OV518PLUS: - case BRIDGE_OV519: - ret = ov518_i2c_r(sd, reg); - break; - case BRIDGE_OVFX2: - ret = ovfx2_i2c_r(sd, reg); - break; - case BRIDGE_W9968CF: - ret = w9968cf_i2c_r(sd, reg); - break; - } - - if (ret >= 0) - sd->sensor_reg_cache[reg] = ret; - - return ret; -} - -/* Writes bits at positions specified by mask to an I2C reg. Bits that are in - * the same position as 1's in "mask" are cleared and set to "value". Bits - * that are in the same position as 0's in "mask" are preserved, regardless - * of their respective state in "value". - */ -static void i2c_w_mask(struct sd *sd, - u8 reg, - u8 value, - u8 mask) -{ - int rc; - u8 oldval; - - value &= mask; /* Enforce mask on value */ - rc = i2c_r(sd, reg); - if (rc < 0) - return; - oldval = rc & ~mask; /* Clear the masked bits */ - value |= oldval; /* Set the desired bits */ - i2c_w(sd, reg, value); -} - -/* Temporarily stops OV511 from functioning. Must do this before changing - * registers while the camera is streaming */ -static inline void ov51x_stop(struct sd *sd) -{ - PDEBUG(D_STREAM, "stopping"); - sd->stopped = 1; - switch (sd->bridge) { - case BRIDGE_OV511: - case BRIDGE_OV511PLUS: - reg_w(sd, R51x_SYS_RESET, 0x3d); - break; - case BRIDGE_OV518: - case BRIDGE_OV518PLUS: - reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a); - break; - case BRIDGE_OV519: - reg_w(sd, OV519_R51_RESET1, 0x0f); - reg_w(sd, OV519_R51_RESET1, 0x00); - reg_w(sd, 0x22, 0x00); /* FRAR */ - break; - case BRIDGE_OVFX2: - reg_w_mask(sd, 0x0f, 0x00, 0x02); - break; - case BRIDGE_W9968CF: - reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */ - break; - } -} - -/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not - * actually stopped (for performance). */ -static inline void ov51x_restart(struct sd *sd) -{ - PDEBUG(D_STREAM, "restarting"); - if (!sd->stopped) - return; - sd->stopped = 0; - - /* Reinitialize the stream */ - switch (sd->bridge) { - case BRIDGE_OV511: - case BRIDGE_OV511PLUS: - reg_w(sd, R51x_SYS_RESET, 0x00); - break; - case BRIDGE_OV518: - case BRIDGE_OV518PLUS: - reg_w(sd, 0x2f, 0x80); - reg_w(sd, R51x_SYS_RESET, 0x00); - break; - case BRIDGE_OV519: - reg_w(sd, OV519_R51_RESET1, 0x0f); - reg_w(sd, OV519_R51_RESET1, 0x00); - reg_w(sd, 0x22, 0x1d); /* FRAR */ - break; - case BRIDGE_OVFX2: - reg_w_mask(sd, 0x0f, 0x02, 0x02); - break; - case BRIDGE_W9968CF: - reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */ - break; - } -} - -static void ov51x_set_slave_ids(struct sd *sd, u8 slave); - -/* This does an initial reset of an OmniVision sensor and ensures that I2C - * is synchronized. Returns <0 on failure. - */ -static int init_ov_sensor(struct sd *sd, u8 slave) -{ - int i; - - ov51x_set_slave_ids(sd, slave); - - /* Reset the sensor */ - i2c_w(sd, 0x12, 0x80); - - /* Wait for it to initialize */ - msleep(150); - - for (i = 0; i < i2c_detect_tries; i++) { - if (i2c_r(sd, OV7610_REG_ID_HIGH) == 0x7f && - i2c_r(sd, OV7610_REG_ID_LOW) == 0xa2) { - PDEBUG(D_PROBE, "I2C synced in %d attempt(s)", i); - return 0; - } - - /* Reset the sensor */ - i2c_w(sd, 0x12, 0x80); - - /* Wait for it to initialize */ - msleep(150); - - /* Dummy read to sync I2C */ - if (i2c_r(sd, 0x00) < 0) - return -1; - } - return -1; -} - -/* Set the read and write slave IDs. The "slave" argument is the write slave, - * and the read slave will be set to (slave + 1). - * This should not be called from outside the i2c I/O functions. - * Sets I2C read and write slave IDs. Returns <0 for error - */ -static void ov51x_set_slave_ids(struct sd *sd, - u8 slave) -{ - switch (sd->bridge) { - case BRIDGE_OVFX2: - reg_w(sd, OVFX2_I2C_ADDR, slave); - return; - case BRIDGE_W9968CF: - sd->sensor_addr = slave; - return; - } - - reg_w(sd, R51x_I2C_W_SID, slave); - reg_w(sd, R51x_I2C_R_SID, slave + 1); -} - -static void write_regvals(struct sd *sd, - const struct ov_regvals *regvals, - int n) -{ - while (--n >= 0) { - reg_w(sd, regvals->reg, regvals->val); - regvals++; - } -} - -static void write_i2c_regvals(struct sd *sd, - const struct ov_i2c_regvals *regvals, - int n) -{ - while (--n >= 0) { - i2c_w(sd, regvals->reg, regvals->val); - regvals++; - } -} - -/**************************************************************************** - * - * OV511 and sensor configuration - * - ***************************************************************************/ - -/* This initializes the OV2x10 / OV3610 / OV3620 / OV9600 */ -static void ov_hires_configure(struct sd *sd) -{ - int high, low; - - if (sd->bridge != BRIDGE_OVFX2) { - pr_err("error hires sensors only supported with ovfx2\n"); - return; - } - - PDEBUG(D_PROBE, "starting ov hires configuration"); - - /* Detect sensor (sub)type */ - high = i2c_r(sd, 0x0a); - low = i2c_r(sd, 0x0b); - /* info("%x, %x", high, low); */ - switch (high) { - case 0x96: - switch (low) { - case 0x40: - PDEBUG(D_PROBE, "Sensor is a OV2610"); - sd->sensor = SEN_OV2610; - return; - case 0x41: - PDEBUG(D_PROBE, "Sensor is a OV2610AE"); - sd->sensor = SEN_OV2610AE; - return; - case 0xb1: - PDEBUG(D_PROBE, "Sensor is a OV9600"); - sd->sensor = SEN_OV9600; - return; - } - break; - case 0x36: - if ((low & 0x0f) == 0x00) { - PDEBUG(D_PROBE, "Sensor is a OV3610"); - sd->sensor = SEN_OV3610; - return; - } - break; - } - pr_err("Error unknown sensor type: %02x%02x\n", high, low); -} - -/* This initializes the OV8110, OV8610 sensor. The OV8110 uses - * the same register settings as the OV8610, since they are very similar. - */ -static void ov8xx0_configure(struct sd *sd) -{ - int rc; - - PDEBUG(D_PROBE, "starting ov8xx0 configuration"); - - /* Detect sensor (sub)type */ - rc = i2c_r(sd, OV7610_REG_COM_I); - if (rc < 0) { - PDEBUG(D_ERR, "Error detecting sensor type"); - return; - } - if ((rc & 3) == 1) - sd->sensor = SEN_OV8610; - else - pr_err("Unknown image sensor version: %d\n", rc & 3); -} - -/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses - * the same register settings as the OV7610, since they are very similar. - */ -static void ov7xx0_configure(struct sd *sd) -{ - int rc, high, low; - - PDEBUG(D_PROBE, "starting OV7xx0 configuration"); - - /* Detect sensor (sub)type */ - rc = i2c_r(sd, OV7610_REG_COM_I); - - /* add OV7670 here - * it appears to be wrongly detected as a 7610 by default */ - if (rc < 0) { - pr_err("Error detecting sensor type\n"); - return; - } - if ((rc & 3) == 3) { - /* quick hack to make OV7670s work */ - high = i2c_r(sd, 0x0a); - low = i2c_r(sd, 0x0b); - /* info("%x, %x", high, low); */ - if (high == 0x76 && (low & 0xf0) == 0x70) { - PDEBUG(D_PROBE, "Sensor is an OV76%02x", low); - sd->sensor = SEN_OV7670; - } else { - PDEBUG(D_PROBE, "Sensor is an OV7610"); - sd->sensor = SEN_OV7610; - } - } else if ((rc & 3) == 1) { - /* I don't know what's different about the 76BE yet. */ - if (i2c_r(sd, 0x15) & 1) { - PDEBUG(D_PROBE, "Sensor is an OV7620AE"); - sd->sensor = SEN_OV7620AE; - } else { - PDEBUG(D_PROBE, "Sensor is an OV76BE"); - sd->sensor = SEN_OV76BE; - } - } else if ((rc & 3) == 0) { - /* try to read product id registers */ - high = i2c_r(sd, 0x0a); - if (high < 0) { - pr_err("Error detecting camera chip PID\n"); - return; - } - low = i2c_r(sd, 0x0b); - if (low < 0) { - pr_err("Error detecting camera chip VER\n"); - return; - } - if (high == 0x76) { - switch (low) { - case 0x30: - pr_err("Sensor is an OV7630/OV7635\n"); - pr_err("7630 is not supported by this driver\n"); - return; - case 0x40: - PDEBUG(D_PROBE, "Sensor is an OV7645"); - sd->sensor = SEN_OV7640; /* FIXME */ - break; - case 0x45: - PDEBUG(D_PROBE, "Sensor is an OV7645B"); - sd->sensor = SEN_OV7640; /* FIXME */ - break; - case 0x48: - PDEBUG(D_PROBE, "Sensor is an OV7648"); - sd->sensor = SEN_OV7648; - break; - case 0x60: - PDEBUG(D_PROBE, "Sensor is a OV7660"); - sd->sensor = SEN_OV7660; - break; - default: - pr_err("Unknown sensor: 0x76%02x\n", low); - return; - } - } else { - PDEBUG(D_PROBE, "Sensor is an OV7620"); - sd->sensor = SEN_OV7620; - } - } else { - pr_err("Unknown image sensor version: %d\n", rc & 3); - } -} - -/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */ -static void ov6xx0_configure(struct sd *sd) -{ - int rc; - PDEBUG(D_PROBE, "starting OV6xx0 configuration"); - - /* Detect sensor (sub)type */ - rc = i2c_r(sd, OV7610_REG_COM_I); - if (rc < 0) { - pr_err("Error detecting sensor type\n"); - return; - } - - /* Ugh. The first two bits are the version bits, but - * the entire register value must be used. I guess OVT - * underestimated how many variants they would make. */ - switch (rc) { - case 0x00: - sd->sensor = SEN_OV6630; - pr_warn("WARNING: Sensor is an OV66308. Your camera may have been misdetected in previous driver versions.\n"); - break; - case 0x01: - sd->sensor = SEN_OV6620; - PDEBUG(D_PROBE, "Sensor is an OV6620"); - break; - case 0x02: - sd->sensor = SEN_OV6630; - PDEBUG(D_PROBE, "Sensor is an OV66308AE"); - break; - case 0x03: - sd->sensor = SEN_OV66308AF; - PDEBUG(D_PROBE, "Sensor is an OV66308AF"); - break; - case 0x90: - sd->sensor = SEN_OV6630; - pr_warn("WARNING: Sensor is an OV66307. Your camera may have been misdetected in previous driver versions.\n"); - break; - default: - pr_err("FATAL: Unknown sensor version: 0x%02x\n", rc); - return; - } - - /* Set sensor-specific vars */ - sd->sif = 1; -} - -/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ -static void ov51x_led_control(struct sd *sd, int on) -{ - if (sd->invert_led) - on = !on; - - switch (sd->bridge) { - /* OV511 has no LED control */ - case BRIDGE_OV511PLUS: - reg_w(sd, R511_SYS_LED_CTL, on); - break; - case BRIDGE_OV518: - case BRIDGE_OV518PLUS: - reg_w_mask(sd, R518_GPIO_OUT, 0x02 * on, 0x02); - break; - case BRIDGE_OV519: - reg_w_mask(sd, OV519_GPIO_DATA_OUT0, on, 1); - break; - } -} - -static void sd_reset_snapshot(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (!sd->snapshot_needs_reset) - return; - - /* Note it is important that we clear sd->snapshot_needs_reset, - before actually clearing the snapshot state in the bridge - otherwise we might race with the pkt_scan interrupt handler */ - sd->snapshot_needs_reset = 0; - - switch (sd->bridge) { - case BRIDGE_OV511: - case BRIDGE_OV511PLUS: - reg_w(sd, R51x_SYS_SNAP, 0x02); - reg_w(sd, R51x_SYS_SNAP, 0x00); - break; - case BRIDGE_OV518: - case BRIDGE_OV518PLUS: - reg_w(sd, R51x_SYS_SNAP, 0x02); /* Reset */ - reg_w(sd, R51x_SYS_SNAP, 0x01); /* Enable */ - break; - case BRIDGE_OV519: - reg_w(sd, R51x_SYS_RESET, 0x40); - reg_w(sd, R51x_SYS_RESET, 0x00); - break; - } -} - -static void ov51x_upload_quan_tables(struct sd *sd) -{ - const unsigned char yQuanTable511[] = { - 0, 1, 1, 2, 2, 3, 3, 4, - 1, 1, 1, 2, 2, 3, 4, 4, - 1, 1, 2, 2, 3, 4, 4, 4, - 2, 2, 2, 3, 4, 4, 4, 4, - 2, 2, 3, 4, 4, 5, 5, 5, - 3, 3, 4, 4, 5, 5, 5, 5, - 3, 4, 4, 4, 5, 5, 5, 5, - 4, 4, 4, 4, 5, 5, 5, 5 - }; - - const unsigned char uvQuanTable511[] = { - 0, 2, 2, 3, 4, 4, 4, 4, - 2, 2, 2, 4, 4, 4, 4, 4, - 2, 2, 3, 4, 4, 4, 4, 4, - 3, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4 - }; - - /* OV518 quantization tables are 8x4 (instead of 8x8) */ - const unsigned char yQuanTable518[] = { - 5, 4, 5, 6, 6, 7, 7, 7, - 5, 5, 5, 5, 6, 7, 7, 7, - 6, 6, 6, 6, 7, 7, 7, 8, - 7, 7, 6, 7, 7, 7, 8, 8 - }; - const unsigned char uvQuanTable518[] = { - 6, 6, 6, 7, 7, 7, 7, 7, - 6, 6, 6, 7, 7, 7, 7, 7, - 6, 6, 6, 7, 7, 7, 7, 8, - 7, 7, 7, 7, 7, 7, 8, 8 - }; - - const unsigned char *pYTable, *pUVTable; - unsigned char val0, val1; - int i, size, reg = R51x_COMP_LUT_BEGIN; - - PDEBUG(D_PROBE, "Uploading quantization tables"); - - if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) { - pYTable = yQuanTable511; - pUVTable = uvQuanTable511; - size = 32; - } else { - pYTable = yQuanTable518; - pUVTable = uvQuanTable518; - size = 16; - } - - for (i = 0; i < size; i++) { - val0 = *pYTable++; - val1 = *pYTable++; - val0 &= 0x0f; - val1 &= 0x0f; - val0 |= val1 << 4; - reg_w(sd, reg, val0); - - val0 = *pUVTable++; - val1 = *pUVTable++; - val0 &= 0x0f; - val1 &= 0x0f; - val0 |= val1 << 4; - reg_w(sd, reg + size, val0); - - reg++; - } -} - -/* This initializes the OV511/OV511+ and the sensor */ -static void ov511_configure(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* For 511 and 511+ */ - const struct ov_regvals init_511[] = { - { R51x_SYS_RESET, 0x7f }, - { R51x_SYS_INIT, 0x01 }, - { R51x_SYS_RESET, 0x7f }, - { R51x_SYS_INIT, 0x01 }, - { R51x_SYS_RESET, 0x3f }, - { R51x_SYS_INIT, 0x01 }, - { R51x_SYS_RESET, 0x3d }, - }; - - const struct ov_regvals norm_511[] = { - { R511_DRAM_FLOW_CTL, 0x01 }, - { R51x_SYS_SNAP, 0x00 }, - { R51x_SYS_SNAP, 0x02 }, - { R51x_SYS_SNAP, 0x00 }, - { R511_FIFO_OPTS, 0x1f }, - { R511_COMP_EN, 0x00 }, - { R511_COMP_LUT_EN, 0x03 }, - }; - - const struct ov_regvals norm_511_p[] = { - { R511_DRAM_FLOW_CTL, 0xff }, - { R51x_SYS_SNAP, 0x00 }, - { R51x_SYS_SNAP, 0x02 }, - { R51x_SYS_SNAP, 0x00 }, - { R511_FIFO_OPTS, 0xff }, - { R511_COMP_EN, 0x00 }, - { R511_COMP_LUT_EN, 0x03 }, - }; - - const struct ov_regvals compress_511[] = { - { 0x70, 0x1f }, - { 0x71, 0x05 }, - { 0x72, 0x06 }, - { 0x73, 0x06 }, - { 0x74, 0x14 }, - { 0x75, 0x03 }, - { 0x76, 0x04 }, - { 0x77, 0x04 }, - }; - - PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID)); - - write_regvals(sd, init_511, ARRAY_SIZE(init_511)); - - switch (sd->bridge) { - case BRIDGE_OV511: - write_regvals(sd, norm_511, ARRAY_SIZE(norm_511)); - break; - case BRIDGE_OV511PLUS: - write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p)); - break; - } - - /* Init compression */ - write_regvals(sd, compress_511, ARRAY_SIZE(compress_511)); - - ov51x_upload_quan_tables(sd); -} - -/* This initializes the OV518/OV518+ and the sensor */ -static void ov518_configure(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* For 518 and 518+ */ - const struct ov_regvals init_518[] = { - { R51x_SYS_RESET, 0x40 }, - { R51x_SYS_INIT, 0xe1 }, - { R51x_SYS_RESET, 0x3e }, - { R51x_SYS_INIT, 0xe1 }, - { R51x_SYS_RESET, 0x00 }, - { R51x_SYS_INIT, 0xe1 }, - { 0x46, 0x00 }, - { 0x5d, 0x03 }, - }; - - const struct ov_regvals norm_518[] = { - { R51x_SYS_SNAP, 0x02 }, /* Reset */ - { R51x_SYS_SNAP, 0x01 }, /* Enable */ - { 0x31, 0x0f }, - { 0x5d, 0x03 }, - { 0x24, 0x9f }, - { 0x25, 0x90 }, - { 0x20, 0x00 }, - { 0x51, 0x04 }, - { 0x71, 0x19 }, - { 0x2f, 0x80 }, - }; - - const struct ov_regvals norm_518_p[] = { - { R51x_SYS_SNAP, 0x02 }, /* Reset */ - { R51x_SYS_SNAP, 0x01 }, /* Enable */ - { 0x31, 0x0f }, - { 0x5d, 0x03 }, - { 0x24, 0x9f }, - { 0x25, 0x90 }, - { 0x20, 0x60 }, - { 0x51, 0x02 }, - { 0x71, 0x19 }, - { 0x40, 0xff }, - { 0x41, 0x42 }, - { 0x46, 0x00 }, - { 0x33, 0x04 }, - { 0x21, 0x19 }, - { 0x3f, 0x10 }, - { 0x2f, 0x80 }, - }; - - /* First 5 bits of custom ID reg are a revision ID on OV518 */ - PDEBUG(D_PROBE, "Device revision %d", - 0x1f & reg_r(sd, R51x_SYS_CUST_ID)); - - write_regvals(sd, init_518, ARRAY_SIZE(init_518)); - - /* Set LED GPIO pin to output mode */ - reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02); - - switch (sd->bridge) { - case BRIDGE_OV518: - write_regvals(sd, norm_518, ARRAY_SIZE(norm_518)); - break; - case BRIDGE_OV518PLUS: - write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p)); - break; - } - - ov51x_upload_quan_tables(sd); - - reg_w(sd, 0x2f, 0x80); -} - -static void ov519_configure(struct sd *sd) -{ - static const struct ov_regvals init_519[] = { - { 0x5a, 0x6d }, /* EnableSystem */ - { 0x53, 0x9b }, /* don't enable the microcontroller */ - { OV519_R54_EN_CLK1, 0xff }, /* set bit2 to enable jpeg */ - { 0x5d, 0x03 }, - { 0x49, 0x01 }, - { 0x48, 0x00 }, - /* Set LED pin to output mode. Bit 4 must be cleared or sensor - * detection will fail. This deserves further investigation. */ - { OV519_GPIO_IO_CTRL0, 0xee }, - { OV519_R51_RESET1, 0x0f }, - { OV519_R51_RESET1, 0x00 }, - { 0x22, 0x00 }, - /* windows reads 0x55 at this point*/ - }; - - write_regvals(sd, init_519, ARRAY_SIZE(init_519)); -} - -static void ovfx2_configure(struct sd *sd) -{ - static const struct ov_regvals init_fx2[] = { - { 0x00, 0x60 }, - { 0x02, 0x01 }, - { 0x0f, 0x1d }, - { 0xe9, 0x82 }, - { 0xea, 0xc7 }, - { 0xeb, 0x10 }, - { 0xec, 0xf6 }, - }; - - sd->stopped = 1; - - write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2)); -} - -/* set the mode */ -/* This function works for ov7660 only */ -static void ov519_set_mode(struct sd *sd) -{ - static const struct ov_regvals bridge_ov7660[2][10] = { - {{0x10, 0x14}, {0x11, 0x1e}, {0x12, 0x00}, {0x13, 0x00}, - {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c}, - {0x25, 0x01}, {0x26, 0x00}}, - {{0x10, 0x28}, {0x11, 0x3c}, {0x12, 0x00}, {0x13, 0x00}, - {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c}, - {0x25, 0x03}, {0x26, 0x00}} - }; - static const struct ov_i2c_regvals sensor_ov7660[2][3] = { - {{0x12, 0x00}, {0x24, 0x00}, {0x0c, 0x0c}}, - {{0x12, 0x00}, {0x04, 0x00}, {0x0c, 0x00}} - }; - static const struct ov_i2c_regvals sensor_ov7660_2[] = { - {OV7670_R17_HSTART, 0x13}, - {OV7670_R18_HSTOP, 0x01}, - {OV7670_R32_HREF, 0x92}, - {OV7670_R19_VSTART, 0x02}, - {OV7670_R1A_VSTOP, 0x7a}, - {OV7670_R03_VREF, 0x00}, -/* {0x33, 0x00}, */ -/* {0x34, 0x07}, */ -/* {0x36, 0x00}, */ -/* {0x6b, 0x0a}, */ - }; - - write_regvals(sd, bridge_ov7660[sd->gspca_dev.curr_mode], - ARRAY_SIZE(bridge_ov7660[0])); - write_i2c_regvals(sd, sensor_ov7660[sd->gspca_dev.curr_mode], - ARRAY_SIZE(sensor_ov7660[0])); - write_i2c_regvals(sd, sensor_ov7660_2, - ARRAY_SIZE(sensor_ov7660_2)); -} - -/* set the frame rate */ -/* This function works for sensors ov7640, ov7648 ov7660 and ov7670 only */ -static void ov519_set_fr(struct sd *sd) -{ - int fr; - u8 clock; - /* frame rate table with indices: - * - mode = 0: 320x240, 1: 640x480 - * - fr rate = 0: 30, 1: 25, 2: 20, 3: 15, 4: 10, 5: 5 - * - reg = 0: bridge a4, 1: bridge 23, 2: sensor 11 (clock) - */ - static const u8 fr_tb[2][6][3] = { - {{0x04, 0xff, 0x00}, - {0x04, 0x1f, 0x00}, - {0x04, 0x1b, 0x00}, - {0x04, 0x15, 0x00}, - {0x04, 0x09, 0x00}, - {0x04, 0x01, 0x00}}, - {{0x0c, 0xff, 0x00}, - {0x0c, 0x1f, 0x00}, - {0x0c, 0x1b, 0x00}, - {0x04, 0xff, 0x01}, - {0x04, 0x1f, 0x01}, - {0x04, 0x1b, 0x01}}, - }; - - if (frame_rate > 0) - sd->frame_rate = frame_rate; - if (sd->frame_rate >= 30) - fr = 0; - else if (sd->frame_rate >= 25) - fr = 1; - else if (sd->frame_rate >= 20) - fr = 2; - else if (sd->frame_rate >= 15) - fr = 3; - else if (sd->frame_rate >= 10) - fr = 4; - else - fr = 5; - reg_w(sd, 0xa4, fr_tb[sd->gspca_dev.curr_mode][fr][0]); - reg_w(sd, 0x23, fr_tb[sd->gspca_dev.curr_mode][fr][1]); - clock = fr_tb[sd->gspca_dev.curr_mode][fr][2]; - if (sd->sensor == SEN_OV7660) - clock |= 0x80; /* enable double clock */ - ov518_i2c_w(sd, OV7670_R11_CLKRC, clock); -} - -static void setautogain(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - i2c_w_mask(sd, 0x13, val ? 0x05 : 0x00, 0x05); -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam = &gspca_dev->cam; - - sd->bridge = id->driver_info & BRIDGE_MASK; - sd->invert_led = (id->driver_info & BRIDGE_INVERT_LED) != 0; - - switch (sd->bridge) { - case BRIDGE_OV511: - case BRIDGE_OV511PLUS: - cam->cam_mode = ov511_vga_mode; - cam->nmodes = ARRAY_SIZE(ov511_vga_mode); - break; - case BRIDGE_OV518: - case BRIDGE_OV518PLUS: - cam->cam_mode = ov518_vga_mode; - cam->nmodes = ARRAY_SIZE(ov518_vga_mode); - break; - case BRIDGE_OV519: - cam->cam_mode = ov519_vga_mode; - cam->nmodes = ARRAY_SIZE(ov519_vga_mode); - break; - case BRIDGE_OVFX2: - cam->cam_mode = ov519_vga_mode; - cam->nmodes = ARRAY_SIZE(ov519_vga_mode); - cam->bulk_size = OVFX2_BULK_SIZE; - cam->bulk_nurbs = MAX_NURBS; - cam->bulk = 1; - break; - case BRIDGE_W9968CF: - cam->cam_mode = w9968cf_vga_mode; - cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode); - break; - } - - sd->frame_rate = 15; - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam = &gspca_dev->cam; - - switch (sd->bridge) { - case BRIDGE_OV511: - case BRIDGE_OV511PLUS: - ov511_configure(gspca_dev); - break; - case BRIDGE_OV518: - case BRIDGE_OV518PLUS: - ov518_configure(gspca_dev); - break; - case BRIDGE_OV519: - ov519_configure(sd); - break; - case BRIDGE_OVFX2: - ovfx2_configure(sd); - break; - case BRIDGE_W9968CF: - w9968cf_configure(sd); - break; - } - - /* The OV519 must be more aggressive about sensor detection since - * I2C write will never fail if the sensor is not present. We have - * to try to initialize the sensor to detect its presence */ - sd->sensor = -1; - - /* Test for 76xx */ - if (init_ov_sensor(sd, OV7xx0_SID) >= 0) { - ov7xx0_configure(sd); - - /* Test for 6xx0 */ - } else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) { - ov6xx0_configure(sd); - - /* Test for 8xx0 */ - } else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) { - ov8xx0_configure(sd); - - /* Test for 3xxx / 2xxx */ - } else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) { - ov_hires_configure(sd); - } else { - pr_err("Can't determine sensor slave IDs\n"); - goto error; - } - - if (sd->sensor < 0) - goto error; - - ov51x_led_control(sd, 0); /* turn LED off */ - - switch (sd->bridge) { - case BRIDGE_OV511: - case BRIDGE_OV511PLUS: - if (sd->sif) { - cam->cam_mode = ov511_sif_mode; - cam->nmodes = ARRAY_SIZE(ov511_sif_mode); - } - break; - case BRIDGE_OV518: - case BRIDGE_OV518PLUS: - if (sd->sif) { - cam->cam_mode = ov518_sif_mode; - cam->nmodes = ARRAY_SIZE(ov518_sif_mode); - } - break; - case BRIDGE_OV519: - if (sd->sif) { - cam->cam_mode = ov519_sif_mode; - cam->nmodes = ARRAY_SIZE(ov519_sif_mode); - } - break; - case BRIDGE_OVFX2: - switch (sd->sensor) { - case SEN_OV2610: - case SEN_OV2610AE: - cam->cam_mode = ovfx2_ov2610_mode; - cam->nmodes = ARRAY_SIZE(ovfx2_ov2610_mode); - break; - case SEN_OV3610: - cam->cam_mode = ovfx2_ov3610_mode; - cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode); - break; - case SEN_OV9600: - cam->cam_mode = ovfx2_ov9600_mode; - cam->nmodes = ARRAY_SIZE(ovfx2_ov9600_mode); - break; - default: - if (sd->sif) { - cam->cam_mode = ov519_sif_mode; - cam->nmodes = ARRAY_SIZE(ov519_sif_mode); - } - break; - } - break; - case BRIDGE_W9968CF: - if (sd->sif) - cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode) - 1; - - /* w9968cf needs initialisation once the sensor is known */ - w9968cf_init(sd); - break; - } - - /* initialize the sensor */ - switch (sd->sensor) { - case SEN_OV2610: - write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610)); - - /* Enable autogain, autoexpo, awb, bandfilter */ - i2c_w_mask(sd, 0x13, 0x27, 0x27); - break; - case SEN_OV2610AE: - write_i2c_regvals(sd, norm_2610ae, ARRAY_SIZE(norm_2610ae)); - - /* enable autoexpo */ - i2c_w_mask(sd, 0x13, 0x05, 0x05); - break; - case SEN_OV3610: - write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b)); - - /* Enable autogain, autoexpo, awb, bandfilter */ - i2c_w_mask(sd, 0x13, 0x27, 0x27); - break; - case SEN_OV6620: - write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)); - break; - case SEN_OV6630: - case SEN_OV66308AF: - write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)); - break; - default: -/* case SEN_OV7610: */ -/* case SEN_OV76BE: */ - write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)); - i2c_w_mask(sd, 0x0e, 0x00, 0x40); - break; - case SEN_OV7620: - case SEN_OV7620AE: - write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)); - break; - case SEN_OV7640: - case SEN_OV7648: - write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)); - break; - case SEN_OV7660: - i2c_w(sd, OV7670_R12_COM7, OV7670_COM7_RESET); - msleep(14); - reg_w(sd, OV519_R57_SNAPSHOT, 0x23); - write_regvals(sd, init_519_ov7660, - ARRAY_SIZE(init_519_ov7660)); - write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660)); - sd->gspca_dev.curr_mode = 1; /* 640x480 */ - ov519_set_mode(sd); - ov519_set_fr(sd); - sd_reset_snapshot(gspca_dev); - ov51x_restart(sd); - ov51x_stop(sd); /* not in win traces */ - ov51x_led_control(sd, 0); - break; - case SEN_OV7670: - write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)); - break; - case SEN_OV8610: - write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)); - break; - case SEN_OV9600: - write_i2c_regvals(sd, norm_9600, ARRAY_SIZE(norm_9600)); - - /* enable autoexpo */ -/* i2c_w_mask(sd, 0x13, 0x05, 0x05); */ - break; - } - return gspca_dev->usb_err; -error: - PDEBUG(D_ERR, "OV519 Config failed"); - return -EINVAL; -} - -/* function called at start time before URB creation */ -static int sd_isoc_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->bridge) { - case BRIDGE_OVFX2: - if (gspca_dev->width != 800) - gspca_dev->cam.bulk_size = OVFX2_BULK_SIZE; - else - gspca_dev->cam.bulk_size = 7 * 4096; - break; - } - return 0; -} - -/* Set up the OV511/OV511+ with the given image parameters. - * - * Do not put any sensor-specific code in here (including I2C I/O functions) - */ -static void ov511_mode_init_regs(struct sd *sd) -{ - int hsegs, vsegs, packet_size, fps, needed; - int interlaced = 0; - struct usb_host_interface *alt; - struct usb_interface *intf; - - intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); - alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); - if (!alt) { - pr_err("Couldn't get altsetting\n"); - sd->gspca_dev.usb_err = -EIO; - return; - } - - packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); - reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5); - - reg_w(sd, R511_CAM_UV_EN, 0x01); - reg_w(sd, R511_SNAP_UV_EN, 0x01); - reg_w(sd, R511_SNAP_OPTS, 0x03); - - /* Here I'm assuming that snapshot size == image size. - * I hope that's always true. --claudio - */ - hsegs = (sd->gspca_dev.width >> 3) - 1; - vsegs = (sd->gspca_dev.height >> 3) - 1; - - reg_w(sd, R511_CAM_PXCNT, hsegs); - reg_w(sd, R511_CAM_LNCNT, vsegs); - reg_w(sd, R511_CAM_PXDIV, 0x00); - reg_w(sd, R511_CAM_LNDIV, 0x00); - - /* YUV420, low pass filter on */ - reg_w(sd, R511_CAM_OPTS, 0x03); - - /* Snapshot additions */ - reg_w(sd, R511_SNAP_PXCNT, hsegs); - reg_w(sd, R511_SNAP_LNCNT, vsegs); - reg_w(sd, R511_SNAP_PXDIV, 0x00); - reg_w(sd, R511_SNAP_LNDIV, 0x00); - - /******** Set the framerate ********/ - if (frame_rate > 0) - sd->frame_rate = frame_rate; - - switch (sd->sensor) { - case SEN_OV6620: - /* No framerate control, doesn't like higher rates yet */ - sd->clockdiv = 3; - break; - - /* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed - for more sensors we need to do this for them too */ - case SEN_OV7620: - case SEN_OV7620AE: - case SEN_OV7640: - case SEN_OV7648: - case SEN_OV76BE: - if (sd->gspca_dev.width == 320) - interlaced = 1; - /* Fall through */ - case SEN_OV6630: - case SEN_OV7610: - case SEN_OV7670: - switch (sd->frame_rate) { - case 30: - case 25: - /* Not enough bandwidth to do 640x480 @ 30 fps */ - if (sd->gspca_dev.width != 640) { - sd->clockdiv = 0; - break; - } - /* Fall through for 640x480 case */ - default: -/* case 20: */ -/* case 15: */ - sd->clockdiv = 1; - break; - case 10: - sd->clockdiv = 2; - break; - case 5: - sd->clockdiv = 5; - break; - } - if (interlaced) { - sd->clockdiv = (sd->clockdiv + 1) * 2 - 1; - /* Higher then 10 does not work */ - if (sd->clockdiv > 10) - sd->clockdiv = 10; - } - break; - - case SEN_OV8610: - /* No framerate control ?? */ - sd->clockdiv = 0; - break; - } - - /* Check if we have enough bandwidth to disable compression */ - fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1; - needed = fps * sd->gspca_dev.width * sd->gspca_dev.height * 3 / 2; - /* 1000 isoc packets/sec */ - if (needed > 1000 * packet_size) { - /* Enable Y and UV quantization and compression */ - reg_w(sd, R511_COMP_EN, 0x07); - reg_w(sd, R511_COMP_LUT_EN, 0x03); - } else { - reg_w(sd, R511_COMP_EN, 0x06); - reg_w(sd, R511_COMP_LUT_EN, 0x00); - } - - reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE); - reg_w(sd, R51x_SYS_RESET, 0); -} - -/* Sets up the OV518/OV518+ with the given image parameters - * - * OV518 needs a completely different approach, until we can figure out what - * the individual registers do. Also, only 15 FPS is supported now. - * - * Do not put any sensor-specific code in here (including I2C I/O functions) - */ -static void ov518_mode_init_regs(struct sd *sd) -{ - int hsegs, vsegs, packet_size; - struct usb_host_interface *alt; - struct usb_interface *intf; - - intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); - alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); - if (!alt) { - pr_err("Couldn't get altsetting\n"); - sd->gspca_dev.usb_err = -EIO; - return; - } - - packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); - ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2); - - /******** Set the mode ********/ - reg_w(sd, 0x2b, 0); - reg_w(sd, 0x2c, 0); - reg_w(sd, 0x2d, 0); - reg_w(sd, 0x2e, 0); - reg_w(sd, 0x3b, 0); - reg_w(sd, 0x3c, 0); - reg_w(sd, 0x3d, 0); - reg_w(sd, 0x3e, 0); - - if (sd->bridge == BRIDGE_OV518) { - /* Set 8-bit (YVYU) input format */ - reg_w_mask(sd, 0x20, 0x08, 0x08); - - /* Set 12-bit (4:2:0) output format */ - reg_w_mask(sd, 0x28, 0x80, 0xf0); - reg_w_mask(sd, 0x38, 0x80, 0xf0); - } else { - reg_w(sd, 0x28, 0x80); - reg_w(sd, 0x38, 0x80); - } - - hsegs = sd->gspca_dev.width / 16; - vsegs = sd->gspca_dev.height / 4; - - reg_w(sd, 0x29, hsegs); - reg_w(sd, 0x2a, vsegs); - - reg_w(sd, 0x39, hsegs); - reg_w(sd, 0x3a, vsegs); - - /* Windows driver does this here; who knows why */ - reg_w(sd, 0x2f, 0x80); - - /******** Set the framerate ********/ - sd->clockdiv = 1; - - /* Mode independent, but framerate dependent, regs */ - /* 0x51: Clock divider; Only works on some cams which use 2 crystals */ - reg_w(sd, 0x51, 0x04); - reg_w(sd, 0x22, 0x18); - reg_w(sd, 0x23, 0xff); - - if (sd->bridge == BRIDGE_OV518PLUS) { - switch (sd->sensor) { - case SEN_OV7620AE: - if (sd->gspca_dev.width == 320) { - reg_w(sd, 0x20, 0x00); - reg_w(sd, 0x21, 0x19); - } else { - reg_w(sd, 0x20, 0x60); - reg_w(sd, 0x21, 0x1f); - } - break; - case SEN_OV7620: - reg_w(sd, 0x20, 0x00); - reg_w(sd, 0x21, 0x19); - break; - default: - reg_w(sd, 0x21, 0x19); - } - } else - reg_w(sd, 0x71, 0x17); /* Compression-related? */ - - /* FIXME: Sensor-specific */ - /* Bit 5 is what matters here. Of course, it is "reserved" */ - i2c_w(sd, 0x54, 0x23); - - reg_w(sd, 0x2f, 0x80); - - if (sd->bridge == BRIDGE_OV518PLUS) { - reg_w(sd, 0x24, 0x94); - reg_w(sd, 0x25, 0x90); - ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */ - ov518_reg_w32(sd, 0xc6, 540, 2); /* 21ch */ - ov518_reg_w32(sd, 0xc7, 540, 2); /* 21ch */ - ov518_reg_w32(sd, 0xc8, 108, 2); /* 6ch */ - ov518_reg_w32(sd, 0xca, 131098, 3); /* 2001ah */ - ov518_reg_w32(sd, 0xcb, 532, 2); /* 214h */ - ov518_reg_w32(sd, 0xcc, 2400, 2); /* 960h */ - ov518_reg_w32(sd, 0xcd, 32, 2); /* 20h */ - ov518_reg_w32(sd, 0xce, 608, 2); /* 260h */ - } else { - reg_w(sd, 0x24, 0x9f); - reg_w(sd, 0x25, 0x90); - ov518_reg_w32(sd, 0xc4, 400, 2); /* 190h */ - ov518_reg_w32(sd, 0xc6, 381, 2); /* 17dh */ - ov518_reg_w32(sd, 0xc7, 381, 2); /* 17dh */ - ov518_reg_w32(sd, 0xc8, 128, 2); /* 80h */ - ov518_reg_w32(sd, 0xca, 183331, 3); /* 2cc23h */ - ov518_reg_w32(sd, 0xcb, 746, 2); /* 2eah */ - ov518_reg_w32(sd, 0xcc, 1750, 2); /* 6d6h */ - ov518_reg_w32(sd, 0xcd, 45, 2); /* 2dh */ - ov518_reg_w32(sd, 0xce, 851, 2); /* 353h */ - } - - reg_w(sd, 0x2f, 0x80); -} - -/* Sets up the OV519 with the given image parameters - * - * OV519 needs a completely different approach, until we can figure out what - * the individual registers do. - * - * Do not put any sensor-specific code in here (including I2C I/O functions) - */ -static void ov519_mode_init_regs(struct sd *sd) -{ - static const struct ov_regvals mode_init_519_ov7670[] = { - { 0x5d, 0x03 }, /* Turn off suspend mode */ - { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */ - { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */ - { 0xa2, 0x20 }, /* a2-a5 are undocumented */ - { 0xa3, 0x18 }, - { 0xa4, 0x04 }, - { 0xa5, 0x28 }, - { 0x37, 0x00 }, /* SetUsbInit */ - { 0x55, 0x02 }, /* 4.096 Mhz audio clock */ - /* Enable both fields, YUV Input, disable defect comp (why?) */ - { 0x20, 0x0c }, - { 0x21, 0x38 }, - { 0x22, 0x1d }, - { 0x17, 0x50 }, /* undocumented */ - { 0x37, 0x00 }, /* undocumented */ - { 0x40, 0xff }, /* I2C timeout counter */ - { 0x46, 0x00 }, /* I2C clock prescaler */ - { 0x59, 0x04 }, /* new from windrv 090403 */ - { 0xff, 0x00 }, /* undocumented */ - /* windows reads 0x55 at this point, why? */ - }; - - static const struct ov_regvals mode_init_519[] = { - { 0x5d, 0x03 }, /* Turn off suspend mode */ - { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */ - { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */ - { 0xa2, 0x20 }, /* a2-a5 are undocumented */ - { 0xa3, 0x18 }, - { 0xa4, 0x04 }, - { 0xa5, 0x28 }, - { 0x37, 0x00 }, /* SetUsbInit */ - { 0x55, 0x02 }, /* 4.096 Mhz audio clock */ - /* Enable both fields, YUV Input, disable defect comp (why?) */ - { 0x22, 0x1d }, - { 0x17, 0x50 }, /* undocumented */ - { 0x37, 0x00 }, /* undocumented */ - { 0x40, 0xff }, /* I2C timeout counter */ - { 0x46, 0x00 }, /* I2C clock prescaler */ - { 0x59, 0x04 }, /* new from windrv 090403 */ - { 0xff, 0x00 }, /* undocumented */ - /* windows reads 0x55 at this point, why? */ - }; - - /******** Set the mode ********/ - switch (sd->sensor) { - default: - write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519)); - if (sd->sensor == SEN_OV7640 || - sd->sensor == SEN_OV7648) { - /* Select 8-bit input mode */ - reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10); - } - break; - case SEN_OV7660: - return; /* done by ov519_set_mode/fr() */ - case SEN_OV7670: - write_regvals(sd, mode_init_519_ov7670, - ARRAY_SIZE(mode_init_519_ov7670)); - break; - } - - reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4); - reg_w(sd, OV519_R11_V_SIZE, sd->gspca_dev.height >> 3); - if (sd->sensor == SEN_OV7670 && - sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv) - reg_w(sd, OV519_R12_X_OFFSETL, 0x04); - else if (sd->sensor == SEN_OV7648 && - sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv) - reg_w(sd, OV519_R12_X_OFFSETL, 0x01); - else - reg_w(sd, OV519_R12_X_OFFSETL, 0x00); - reg_w(sd, OV519_R13_X_OFFSETH, 0x00); - reg_w(sd, OV519_R14_Y_OFFSETL, 0x00); - reg_w(sd, OV519_R15_Y_OFFSETH, 0x00); - reg_w(sd, OV519_R16_DIVIDER, 0x00); - reg_w(sd, OV519_R25_FORMAT, 0x03); /* YUV422 */ - reg_w(sd, 0x26, 0x00); /* Undocumented */ - - /******** Set the framerate ********/ - if (frame_rate > 0) - sd->frame_rate = frame_rate; - -/* FIXME: These are only valid at the max resolution. */ - sd->clockdiv = 0; - switch (sd->sensor) { - case SEN_OV7640: - case SEN_OV7648: - switch (sd->frame_rate) { - default: -/* case 30: */ - reg_w(sd, 0xa4, 0x0c); - reg_w(sd, 0x23, 0xff); - break; - case 25: - reg_w(sd, 0xa4, 0x0c); - reg_w(sd, 0x23, 0x1f); - break; - case 20: - reg_w(sd, 0xa4, 0x0c); - reg_w(sd, 0x23, 0x1b); - break; - case 15: - reg_w(sd, 0xa4, 0x04); - reg_w(sd, 0x23, 0xff); - sd->clockdiv = 1; - break; - case 10: - reg_w(sd, 0xa4, 0x04); - reg_w(sd, 0x23, 0x1f); - sd->clockdiv = 1; - break; - case 5: - reg_w(sd, 0xa4, 0x04); - reg_w(sd, 0x23, 0x1b); - sd->clockdiv = 1; - break; - } - break; - case SEN_OV8610: - switch (sd->frame_rate) { - default: /* 15 fps */ -/* case 15: */ - reg_w(sd, 0xa4, 0x06); - reg_w(sd, 0x23, 0xff); - break; - case 10: - reg_w(sd, 0xa4, 0x06); - reg_w(sd, 0x23, 0x1f); - break; - case 5: - reg_w(sd, 0xa4, 0x06); - reg_w(sd, 0x23, 0x1b); - break; - } - break; - case SEN_OV7670: /* guesses, based on 7640 */ - PDEBUG(D_STREAM, "Setting framerate to %d fps", - (sd->frame_rate == 0) ? 15 : sd->frame_rate); - reg_w(sd, 0xa4, 0x10); - switch (sd->frame_rate) { - case 30: - reg_w(sd, 0x23, 0xff); - break; - case 20: - reg_w(sd, 0x23, 0x1b); - break; - default: -/* case 15: */ - reg_w(sd, 0x23, 0xff); - sd->clockdiv = 1; - break; - } - break; - } -} - -static void mode_init_ov_sensor_regs(struct sd *sd) -{ - struct gspca_dev *gspca_dev; - int qvga, xstart, xend, ystart, yend; - u8 v; - - gspca_dev = &sd->gspca_dev; - qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; - - /******** Mode (VGA/QVGA) and sensor specific regs ********/ - switch (sd->sensor) { - case SEN_OV2610: - i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); - i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); - i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); - i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); - i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); - i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); - i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); - return; - case SEN_OV2610AE: { - u8 v; - - /* frame rates: - * 10fps / 5 fps for 1600x1200 - * 40fps / 20fps for 800x600 - */ - v = 80; - if (qvga) { - if (sd->frame_rate < 25) - v = 0x81; - } else { - if (sd->frame_rate < 10) - v = 0x81; - } - i2c_w(sd, 0x11, v); - i2c_w(sd, 0x12, qvga ? 0x60 : 0x20); - return; - } - case SEN_OV3610: - if (qvga) { - xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4); - ystart = (776 - gspca_dev->height) / 2; - } else { - xstart = (2076 - gspca_dev->width) / 2 + (0x10 << 4); - ystart = (1544 - gspca_dev->height) / 2; - } - xend = xstart + gspca_dev->width; - yend = ystart + gspca_dev->height; - /* Writing to the COMH register resets the other windowing regs - to their default values, so we must do this first. */ - i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0xf0); - i2c_w_mask(sd, 0x32, - (((xend >> 1) & 7) << 3) | ((xstart >> 1) & 7), - 0x3f); - i2c_w_mask(sd, 0x03, - (((yend >> 1) & 3) << 2) | ((ystart >> 1) & 3), - 0x0f); - i2c_w(sd, 0x17, xstart >> 4); - i2c_w(sd, 0x18, xend >> 4); - i2c_w(sd, 0x19, ystart >> 3); - i2c_w(sd, 0x1a, yend >> 3); - return; - case SEN_OV8610: - /* For OV8610 qvga means qsvga */ - i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5); - i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ - i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ - i2c_w_mask(sd, 0x2d, 0x00, 0x40); /* from windrv 090403 */ - i2c_w_mask(sd, 0x28, 0x20, 0x20); /* progressive mode on */ - break; - case SEN_OV7610: - i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); - i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e); - i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ - i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ - break; - case SEN_OV7620: - case SEN_OV7620AE: - case SEN_OV76BE: - i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); - i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); - i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); - i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); - i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); - i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0); - i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); - i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ - i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ - if (sd->sensor == SEN_OV76BE) - i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e); - break; - case SEN_OV7640: - case SEN_OV7648: - i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); - i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); - /* Setting this undocumented bit in qvga mode removes a very - annoying vertical shaking of the image */ - i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); - /* Unknown */ - i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); - /* Allow higher automatic gain (to allow higher framerates) */ - i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); - i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */ - break; - case SEN_OV7670: - /* set COM7_FMT_VGA or COM7_FMT_QVGA - * do we need to set anything else? - * HSTART etc are set in set_ov_sensor_window itself */ - i2c_w_mask(sd, OV7670_R12_COM7, - qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA, - OV7670_COM7_FMT_MASK); - i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ - i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_AWB, - OV7670_COM8_AWB); - if (qvga) { /* QVGA from ov7670.c by - * Jonathan Corbet */ - xstart = 164; - xend = 28; - ystart = 14; - yend = 494; - } else { /* VGA */ - xstart = 158; - xend = 14; - ystart = 10; - yend = 490; - } - /* OV7670 hardware window registers are split across - * multiple locations */ - i2c_w(sd, OV7670_R17_HSTART, xstart >> 3); - i2c_w(sd, OV7670_R18_HSTOP, xend >> 3); - v = i2c_r(sd, OV7670_R32_HREF); - v = (v & 0xc0) | ((xend & 0x7) << 3) | (xstart & 0x07); - msleep(10); /* need to sleep between read and write to - * same reg! */ - i2c_w(sd, OV7670_R32_HREF, v); - - i2c_w(sd, OV7670_R19_VSTART, ystart >> 2); - i2c_w(sd, OV7670_R1A_VSTOP, yend >> 2); - v = i2c_r(sd, OV7670_R03_VREF); - v = (v & 0xc0) | ((yend & 0x3) << 2) | (ystart & 0x03); - msleep(10); /* need to sleep between read and write to - * same reg! */ - i2c_w(sd, OV7670_R03_VREF, v); - break; - case SEN_OV6620: - i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); - i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ - i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ - break; - case SEN_OV6630: - case SEN_OV66308AF: - i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); - i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ - break; - case SEN_OV9600: { - const struct ov_i2c_regvals *vals; - static const struct ov_i2c_regvals sxga_15[] = { - {0x11, 0x80}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75} - }; - static const struct ov_i2c_regvals sxga_7_5[] = { - {0x11, 0x81}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75} - }; - static const struct ov_i2c_regvals vga_30[] = { - {0x11, 0x81}, {0x14, 0x7e}, {0x24, 0x70}, {0x25, 0x60} - }; - static const struct ov_i2c_regvals vga_15[] = { - {0x11, 0x83}, {0x14, 0x3e}, {0x24, 0x80}, {0x25, 0x70} - }; - - /* frame rates: - * 15fps / 7.5 fps for 1280x1024 - * 30fps / 15fps for 640x480 - */ - i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0x40); - if (qvga) - vals = sd->frame_rate < 30 ? vga_15 : vga_30; - else - vals = sd->frame_rate < 15 ? sxga_7_5 : sxga_15; - write_i2c_regvals(sd, vals, ARRAY_SIZE(sxga_15)); - return; - } - default: - return; - } - - /******** Clock programming ********/ - i2c_w(sd, 0x11, sd->clockdiv); -} - -/* this function works for bridge ov519 and sensors ov7660 and ov7670 only */ -static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->gspca_dev.streaming) - reg_w(sd, OV519_R51_RESET1, 0x0f); /* block stream */ - i2c_w_mask(sd, OV7670_R1E_MVFP, - OV7670_MVFP_MIRROR * hflip | OV7670_MVFP_VFLIP * vflip, - OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP); - if (sd->gspca_dev.streaming) - reg_w(sd, OV519_R51_RESET1, 0x00); /* restart stream */ -} - -static void set_ov_sensor_window(struct sd *sd) -{ - struct gspca_dev *gspca_dev; - int qvga, crop; - int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; - - /* mode setup is fully handled in mode_init_ov_sensor_regs for these */ - switch (sd->sensor) { - case SEN_OV2610: - case SEN_OV2610AE: - case SEN_OV3610: - case SEN_OV7670: - case SEN_OV9600: - mode_init_ov_sensor_regs(sd); - return; - case SEN_OV7660: - ov519_set_mode(sd); - ov519_set_fr(sd); - return; - } - - gspca_dev = &sd->gspca_dev; - qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; - crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2; - - /* The different sensor ICs handle setting up of window differently. - * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */ - switch (sd->sensor) { - case SEN_OV8610: - hwsbase = 0x1e; - hwebase = 0x1e; - vwsbase = 0x02; - vwebase = 0x02; - break; - case SEN_OV7610: - case SEN_OV76BE: - hwsbase = 0x38; - hwebase = 0x3a; - vwsbase = vwebase = 0x05; - break; - case SEN_OV6620: - case SEN_OV6630: - case SEN_OV66308AF: - hwsbase = 0x38; - hwebase = 0x3a; - vwsbase = 0x05; - vwebase = 0x06; - if (sd->sensor == SEN_OV66308AF && qvga) - /* HDG: this fixes U and V getting swapped */ - hwsbase++; - if (crop) { - hwsbase += 8; - hwebase += 8; - vwsbase += 11; - vwebase += 11; - } - break; - case SEN_OV7620: - case SEN_OV7620AE: - hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */ - hwebase = 0x2f; - vwsbase = vwebase = 0x05; - break; - case SEN_OV7640: - case SEN_OV7648: - hwsbase = 0x1a; - hwebase = 0x1a; - vwsbase = vwebase = 0x03; - break; - default: - return; - } - - switch (sd->sensor) { - case SEN_OV6620: - case SEN_OV6630: - case SEN_OV66308AF: - if (qvga) { /* QCIF */ - hwscale = 0; - vwscale = 0; - } else { /* CIF */ - hwscale = 1; - vwscale = 1; /* The datasheet says 0; - * it's wrong */ - } - break; - case SEN_OV8610: - if (qvga) { /* QSVGA */ - hwscale = 1; - vwscale = 1; - } else { /* SVGA */ - hwscale = 2; - vwscale = 2; - } - break; - default: /* SEN_OV7xx0 */ - if (qvga) { /* QVGA */ - hwscale = 1; - vwscale = 0; - } else { /* VGA */ - hwscale = 2; - vwscale = 1; - } - } - - mode_init_ov_sensor_regs(sd); - - i2c_w(sd, 0x17, hwsbase); - i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale)); - i2c_w(sd, 0x19, vwsbase); - i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale)); -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* Default for most bridges, allow bridge_mode_init_regs to override */ - sd->sensor_width = sd->gspca_dev.width; - sd->sensor_height = sd->gspca_dev.height; - - switch (sd->bridge) { - case BRIDGE_OV511: - case BRIDGE_OV511PLUS: - ov511_mode_init_regs(sd); - break; - case BRIDGE_OV518: - case BRIDGE_OV518PLUS: - ov518_mode_init_regs(sd); - break; - case BRIDGE_OV519: - ov519_mode_init_regs(sd); - break; - /* case BRIDGE_OVFX2: nothing to do */ - case BRIDGE_W9968CF: - w9968cf_mode_init_regs(sd); - break; - } - - set_ov_sensor_window(sd); - - /* Force clear snapshot state in case the snapshot button was - pressed while we weren't streaming */ - sd->snapshot_needs_reset = 1; - sd_reset_snapshot(gspca_dev); - - sd->first_frame = 3; - - ov51x_restart(sd); - ov51x_led_control(sd, 1); - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - ov51x_stop(sd); - ov51x_led_control(sd, 0); -} - -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (!sd->gspca_dev.present) - return; - if (sd->bridge == BRIDGE_W9968CF) - w9968cf_stop0(sd); - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - /* If the last button state is pressed, release it now! */ - if (sd->snapshot_pressed) { - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); - input_sync(gspca_dev->input_dev); - sd->snapshot_pressed = 0; - } -#endif - if (sd->bridge == BRIDGE_OV519) - reg_w(sd, OV519_R57_SNAPSHOT, 0x23); -} - -static void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->snapshot_pressed != state) { -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - input_report_key(gspca_dev->input_dev, KEY_CAMERA, state); - input_sync(gspca_dev->input_dev); -#endif - if (state) - sd->snapshot_needs_reset = 1; - - sd->snapshot_pressed = state; - } else { - /* On the ov511 / ov519 we need to reset the button state - multiple times, as resetting does not work as long as the - button stays pressed */ - switch (sd->bridge) { - case BRIDGE_OV511: - case BRIDGE_OV511PLUS: - case BRIDGE_OV519: - if (state) - sd->snapshot_needs_reset = 1; - break; - } - } -} - -static void ov511_pkt_scan(struct gspca_dev *gspca_dev, - u8 *in, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th - * byte non-zero. The EOF packet has image width/height in the - * 10th and 11th bytes. The 9th byte is given as follows: - * - * bit 7: EOF - * 6: compression enabled - * 5: 422/420/400 modes - * 4: 422/420/400 modes - * 3: 1 - * 2: snapshot button on - * 1: snapshot frame - * 0: even/odd field - */ - if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) && - (in[8] & 0x08)) { - ov51x_handle_button(gspca_dev, (in[8] >> 2) & 1); - if (in[8] & 0x80) { - /* Frame end */ - if ((in[9] + 1) * 8 != gspca_dev->width || - (in[10] + 1) * 8 != gspca_dev->height) { - PDEBUG(D_ERR, "Invalid frame size, got: %dx%d," - " requested: %dx%d\n", - (in[9] + 1) * 8, (in[10] + 1) * 8, - gspca_dev->width, gspca_dev->height); - gspca_dev->last_packet_type = DISCARD_PACKET; - return; - } - /* Add 11 byte footer to frame, might be useful */ - gspca_frame_add(gspca_dev, LAST_PACKET, in, 11); - return; - } else { - /* Frame start */ - gspca_frame_add(gspca_dev, FIRST_PACKET, in, 0); - sd->packet_nr = 0; - } - } - - /* Ignore the packet number */ - len--; - - /* intermediate packet */ - gspca_frame_add(gspca_dev, INTER_PACKET, in, len); -} - -static void ov518_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* A false positive here is likely, until OVT gives me - * the definitive SOF/EOF format */ - if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) { - ov51x_handle_button(gspca_dev, (data[6] >> 1) & 1); - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); - sd->packet_nr = 0; - } - - if (gspca_dev->last_packet_type == DISCARD_PACKET) - return; - - /* Does this device use packet numbers ? */ - if (len & 7) { - len--; - if (sd->packet_nr == data[len]) - sd->packet_nr++; - /* The last few packets of the frame (which are all 0's - except that they may contain part of the footer), are - numbered 0 */ - else if (sd->packet_nr == 0 || data[len]) { - PDEBUG(D_ERR, "Invalid packet nr: %d (expect: %d)", - (int)data[len], (int)sd->packet_nr); - gspca_dev->last_packet_type = DISCARD_PACKET; - return; - } - } - - /* intermediate packet */ - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -static void ov519_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - /* Header of ov519 is 16 bytes: - * Byte Value Description - * 0 0xff magic - * 1 0xff magic - * 2 0xff magic - * 3 0xXX 0x50 = SOF, 0x51 = EOF - * 9 0xXX 0x01 initial frame without data, - * 0x00 standard frame with image - * 14 Lo in EOF: length of image data / 8 - * 15 Hi - */ - - if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) { - switch (data[3]) { - case 0x50: /* start of frame */ - /* Don't check the button state here, as the state - usually (always ?) changes at EOF and checking it - here leads to unnecessary snapshot state resets. */ -#define HDRSZ 16 - data += HDRSZ; - len -= HDRSZ; -#undef HDRSZ - if (data[0] == 0xff || data[1] == 0xd8) - gspca_frame_add(gspca_dev, FIRST_PACKET, - data, len); - else - gspca_dev->last_packet_type = DISCARD_PACKET; - return; - case 0x51: /* end of frame */ - ov51x_handle_button(gspca_dev, data[11] & 1); - if (data[9] != 0) - gspca_dev->last_packet_type = DISCARD_PACKET; - gspca_frame_add(gspca_dev, LAST_PACKET, - NULL, 0); - return; - } - } - - /* intermediate packet */ - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); - - /* A short read signals EOF */ - if (len < gspca_dev->cam.bulk_size) { - /* If the frame is short, and it is one of the first ones - the sensor and bridge are still syncing, so drop it. */ - if (sd->first_frame) { - sd->first_frame--; - if (gspca_dev->image_len < - sd->gspca_dev.width * sd->gspca_dev.height) - gspca_dev->last_packet_type = DISCARD_PACKET; - } - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); - } -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->bridge) { - case BRIDGE_OV511: - case BRIDGE_OV511PLUS: - ov511_pkt_scan(gspca_dev, data, len); - break; - case BRIDGE_OV518: - case BRIDGE_OV518PLUS: - ov518_pkt_scan(gspca_dev, data, len); - break; - case BRIDGE_OV519: - ov519_pkt_scan(gspca_dev, data, len); - break; - case BRIDGE_OVFX2: - ovfx2_pkt_scan(gspca_dev, data, len); - break; - case BRIDGE_W9968CF: - w9968cf_pkt_scan(gspca_dev, data, len); - break; - } -} - -/* -- management routines -- */ - -static void setbrightness(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - static const struct ov_i2c_regvals brit_7660[][7] = { - {{0x0f, 0x6a}, {0x24, 0x40}, {0x25, 0x2b}, {0x26, 0x90}, - {0x27, 0xe0}, {0x28, 0xe0}, {0x2c, 0xe0}}, - {{0x0f, 0x6a}, {0x24, 0x50}, {0x25, 0x40}, {0x26, 0xa1}, - {0x27, 0xc0}, {0x28, 0xc0}, {0x2c, 0xc0}}, - {{0x0f, 0x6a}, {0x24, 0x68}, {0x25, 0x58}, {0x26, 0xc2}, - {0x27, 0xa0}, {0x28, 0xa0}, {0x2c, 0xa0}}, - {{0x0f, 0x6a}, {0x24, 0x70}, {0x25, 0x68}, {0x26, 0xd3}, - {0x27, 0x80}, {0x28, 0x80}, {0x2c, 0x80}}, - {{0x0f, 0x6a}, {0x24, 0x80}, {0x25, 0x70}, {0x26, 0xd3}, - {0x27, 0x20}, {0x28, 0x20}, {0x2c, 0x20}}, - {{0x0f, 0x6a}, {0x24, 0x88}, {0x25, 0x78}, {0x26, 0xd3}, - {0x27, 0x40}, {0x28, 0x40}, {0x2c, 0x40}}, - {{0x0f, 0x6a}, {0x24, 0x90}, {0x25, 0x80}, {0x26, 0xd4}, - {0x27, 0x60}, {0x28, 0x60}, {0x2c, 0x60}} - }; - - switch (sd->sensor) { - case SEN_OV8610: - case SEN_OV7610: - case SEN_OV76BE: - case SEN_OV6620: - case SEN_OV6630: - case SEN_OV66308AF: - case SEN_OV7640: - case SEN_OV7648: - i2c_w(sd, OV7610_REG_BRT, val); - break; - case SEN_OV7620: - case SEN_OV7620AE: - i2c_w(sd, OV7610_REG_BRT, val); - break; - case SEN_OV7660: - write_i2c_regvals(sd, brit_7660[val], - ARRAY_SIZE(brit_7660[0])); - break; - case SEN_OV7670: -/*win trace - * i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_AEC); */ - i2c_w(sd, OV7670_R55_BRIGHT, ov7670_abs_to_sm(val)); - break; - } -} - -static void setcontrast(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - static const struct ov_i2c_regvals contrast_7660[][31] = { - {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0xa0}, - {0x70, 0x58}, {0x71, 0x38}, {0x72, 0x30}, {0x73, 0x30}, - {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x24}, {0x77, 0x24}, - {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x34}, - {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x65}, - {0x80, 0x70}, {0x81, 0x77}, {0x82, 0x7d}, {0x83, 0x83}, - {0x84, 0x88}, {0x85, 0x8d}, {0x86, 0x96}, {0x87, 0x9f}, - {0x88, 0xb0}, {0x89, 0xc4}, {0x8a, 0xd9}}, - {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0x94}, - {0x70, 0x58}, {0x71, 0x40}, {0x72, 0x30}, {0x73, 0x30}, - {0x74, 0x30}, {0x75, 0x30}, {0x76, 0x2c}, {0x77, 0x24}, - {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x31}, - {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x62}, - {0x80, 0x6d}, {0x81, 0x75}, {0x82, 0x7b}, {0x83, 0x81}, - {0x84, 0x87}, {0x85, 0x8d}, {0x86, 0x98}, {0x87, 0xa1}, - {0x88, 0xb2}, {0x89, 0xc6}, {0x8a, 0xdb}}, - {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x84}, - {0x70, 0x58}, {0x71, 0x48}, {0x72, 0x40}, {0x73, 0x40}, - {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x28}, {0x77, 0x24}, - {0x78, 0x26}, {0x79, 0x28}, {0x7a, 0x28}, {0x7b, 0x34}, - {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x5d}, - {0x80, 0x68}, {0x81, 0x71}, {0x82, 0x79}, {0x83, 0x81}, - {0x84, 0x86}, {0x85, 0x8b}, {0x86, 0x95}, {0x87, 0x9e}, - {0x88, 0xb1}, {0x89, 0xc5}, {0x8a, 0xd9}}, - {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x70}, - {0x70, 0x58}, {0x71, 0x58}, {0x72, 0x48}, {0x73, 0x48}, - {0x74, 0x38}, {0x75, 0x40}, {0x76, 0x34}, {0x77, 0x34}, - {0x78, 0x2e}, {0x79, 0x28}, {0x7a, 0x24}, {0x7b, 0x22}, - {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x58}, - {0x80, 0x63}, {0x81, 0x6e}, {0x82, 0x77}, {0x83, 0x80}, - {0x84, 0x87}, {0x85, 0x8f}, {0x86, 0x9c}, {0x87, 0xa9}, - {0x88, 0xc0}, {0x89, 0xd4}, {0x8a, 0xe6}}, - {{0x6c, 0xa0}, {0x6d, 0xf0}, {0x6e, 0x90}, {0x6f, 0x80}, - {0x70, 0x70}, {0x71, 0x80}, {0x72, 0x60}, {0x73, 0x60}, - {0x74, 0x58}, {0x75, 0x60}, {0x76, 0x4c}, {0x77, 0x38}, - {0x78, 0x38}, {0x79, 0x2a}, {0x7a, 0x20}, {0x7b, 0x0e}, - {0x7c, 0x0a}, {0x7d, 0x14}, {0x7e, 0x26}, {0x7f, 0x46}, - {0x80, 0x54}, {0x81, 0x64}, {0x82, 0x70}, {0x83, 0x7c}, - {0x84, 0x87}, {0x85, 0x93}, {0x86, 0xa6}, {0x87, 0xb4}, - {0x88, 0xd0}, {0x89, 0xe5}, {0x8a, 0xf5}}, - {{0x6c, 0x60}, {0x6d, 0x80}, {0x6e, 0x60}, {0x6f, 0x80}, - {0x70, 0x80}, {0x71, 0x80}, {0x72, 0x88}, {0x73, 0x30}, - {0x74, 0x70}, {0x75, 0x68}, {0x76, 0x64}, {0x77, 0x50}, - {0x78, 0x3c}, {0x79, 0x22}, {0x7a, 0x10}, {0x7b, 0x08}, - {0x7c, 0x06}, {0x7d, 0x0e}, {0x7e, 0x1a}, {0x7f, 0x3a}, - {0x80, 0x4a}, {0x81, 0x5a}, {0x82, 0x6b}, {0x83, 0x7b}, - {0x84, 0x89}, {0x85, 0x96}, {0x86, 0xaf}, {0x87, 0xc3}, - {0x88, 0xe1}, {0x89, 0xf2}, {0x8a, 0xfa}}, - {{0x6c, 0x20}, {0x6d, 0x40}, {0x6e, 0x20}, {0x6f, 0x60}, - {0x70, 0x88}, {0x71, 0xc8}, {0x72, 0xc0}, {0x73, 0xb8}, - {0x74, 0xa8}, {0x75, 0xb8}, {0x76, 0x80}, {0x77, 0x5c}, - {0x78, 0x26}, {0x79, 0x10}, {0x7a, 0x08}, {0x7b, 0x04}, - {0x7c, 0x02}, {0x7d, 0x06}, {0x7e, 0x0a}, {0x7f, 0x22}, - {0x80, 0x33}, {0x81, 0x4c}, {0x82, 0x64}, {0x83, 0x7b}, - {0x84, 0x90}, {0x85, 0xa7}, {0x86, 0xc7}, {0x87, 0xde}, - {0x88, 0xf1}, {0x89, 0xf9}, {0x8a, 0xfd}}, - }; - - switch (sd->sensor) { - case SEN_OV7610: - case SEN_OV6620: - i2c_w(sd, OV7610_REG_CNT, val); - break; - case SEN_OV6630: - case SEN_OV66308AF: - i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f); - break; - case SEN_OV8610: { - static const u8 ctab[] = { - 0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f - }; - - /* Use Y gamma control instead. Bit 0 enables it. */ - i2c_w(sd, 0x64, ctab[val >> 5]); - break; - } - case SEN_OV7620: - case SEN_OV7620AE: { - static const u8 ctab[] = { - 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57, - 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff - }; - - /* Use Y gamma control instead. Bit 0 enables it. */ - i2c_w(sd, 0x64, ctab[val >> 4]); - break; - } - case SEN_OV7660: - write_i2c_regvals(sd, contrast_7660[val], - ARRAY_SIZE(contrast_7660[0])); - break; - case SEN_OV7670: - /* check that this isn't just the same as ov7610 */ - i2c_w(sd, OV7670_R56_CONTRAS, val >> 1); - break; - } -} - -static void setexposure(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - i2c_w(sd, 0x10, val); -} - -static void setcolors(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - static const struct ov_i2c_regvals colors_7660[][6] = { - {{0x4f, 0x28}, {0x50, 0x2a}, {0x51, 0x02}, {0x52, 0x0a}, - {0x53, 0x19}, {0x54, 0x23}}, - {{0x4f, 0x47}, {0x50, 0x4a}, {0x51, 0x03}, {0x52, 0x11}, - {0x53, 0x2c}, {0x54, 0x3e}}, - {{0x4f, 0x66}, {0x50, 0x6b}, {0x51, 0x05}, {0x52, 0x19}, - {0x53, 0x40}, {0x54, 0x59}}, - {{0x4f, 0x84}, {0x50, 0x8b}, {0x51, 0x06}, {0x52, 0x20}, - {0x53, 0x53}, {0x54, 0x73}}, - {{0x4f, 0xa3}, {0x50, 0xab}, {0x51, 0x08}, {0x52, 0x28}, - {0x53, 0x66}, {0x54, 0x8e}}, - }; - - switch (sd->sensor) { - case SEN_OV8610: - case SEN_OV7610: - case SEN_OV76BE: - case SEN_OV6620: - case SEN_OV6630: - case SEN_OV66308AF: - i2c_w(sd, OV7610_REG_SAT, val); - break; - case SEN_OV7620: - case SEN_OV7620AE: - /* Use UV gamma control instead. Bits 0 & 7 are reserved. */ -/* rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e); - if (rc < 0) - goto out; */ - i2c_w(sd, OV7610_REG_SAT, val); - break; - case SEN_OV7640: - case SEN_OV7648: - i2c_w(sd, OV7610_REG_SAT, val & 0xf0); - break; - case SEN_OV7660: - write_i2c_regvals(sd, colors_7660[val], - ARRAY_SIZE(colors_7660[0])); - break; - case SEN_OV7670: - /* supported later once I work out how to do it - * transparently fail now! */ - /* set REG_COM13 values for UV sat auto mode */ - break; - } -} - -static void setautobright(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - i2c_w_mask(sd, 0x2d, val ? 0x10 : 0x00, 0x10); -} - -static void setfreq_i(struct sd *sd, s32 val) -{ - if (sd->sensor == SEN_OV7660 - || sd->sensor == SEN_OV7670) { - switch (val) { - case 0: /* Banding filter disabled */ - i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_BFILT); - break; - case 1: /* 50 hz */ - i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, - OV7670_COM8_BFILT); - i2c_w_mask(sd, OV7670_R3B_COM11, 0x08, 0x18); - break; - case 2: /* 60 hz */ - i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, - OV7670_COM8_BFILT); - i2c_w_mask(sd, OV7670_R3B_COM11, 0x00, 0x18); - break; - case 3: /* Auto hz - ov7670 only */ - i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT, - OV7670_COM8_BFILT); - i2c_w_mask(sd, OV7670_R3B_COM11, OV7670_COM11_HZAUTO, - 0x18); - break; - } - } else { - switch (val) { - case 0: /* Banding filter disabled */ - i2c_w_mask(sd, 0x2d, 0x00, 0x04); - i2c_w_mask(sd, 0x2a, 0x00, 0x80); - break; - case 1: /* 50 hz (filter on and framerate adj) */ - i2c_w_mask(sd, 0x2d, 0x04, 0x04); - i2c_w_mask(sd, 0x2a, 0x80, 0x80); - /* 20 fps -> 16.667 fps */ - if (sd->sensor == SEN_OV6620 || - sd->sensor == SEN_OV6630 || - sd->sensor == SEN_OV66308AF) - i2c_w(sd, 0x2b, 0x5e); - else - i2c_w(sd, 0x2b, 0xac); - break; - case 2: /* 60 hz (filter on, ...) */ - i2c_w_mask(sd, 0x2d, 0x04, 0x04); - if (sd->sensor == SEN_OV6620 || - sd->sensor == SEN_OV6630 || - sd->sensor == SEN_OV66308AF) { - /* 20 fps -> 15 fps */ - i2c_w_mask(sd, 0x2a, 0x80, 0x80); - i2c_w(sd, 0x2b, 0xa8); - } else { - /* no framerate adj. */ - i2c_w_mask(sd, 0x2a, 0x00, 0x80); - } - break; - } - } -} - -static void setfreq(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - setfreq_i(sd, val); - - /* Ugly but necessary */ - if (sd->bridge == BRIDGE_W9968CF) - w9968cf_set_crop_window(sd); -} - -static int sd_get_jcomp(struct gspca_dev *gspca_dev, - struct v4l2_jpegcompression *jcomp) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->bridge != BRIDGE_W9968CF) - return -ENOTTY; - - memset(jcomp, 0, sizeof *jcomp); - jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual); - jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT | - V4L2_JPEG_MARKER_DRI; - return 0; -} - -static int sd_set_jcomp(struct gspca_dev *gspca_dev, - struct v4l2_jpegcompression *jcomp) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->bridge != BRIDGE_W9968CF) - return -ENOTTY; - - v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality); - return 0; -} - -static int sd_g_volatile_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - switch (ctrl->id) { - case V4L2_CID_AUTOGAIN: - gspca_dev->exposure->val = i2c_r(sd, 0x10); - break; - } - return 0; -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_CONTRAST: - setcontrast(gspca_dev, ctrl->val); - break; - case V4L2_CID_POWER_LINE_FREQUENCY: - setfreq(gspca_dev, ctrl->val); - break; - case V4L2_CID_AUTOBRIGHTNESS: - if (ctrl->is_new) - setautobright(gspca_dev, ctrl->val); - if (!ctrl->val && sd->brightness->is_new) - setbrightness(gspca_dev, sd->brightness->val); - break; - case V4L2_CID_SATURATION: - setcolors(gspca_dev, ctrl->val); - break; - case V4L2_CID_HFLIP: - sethvflip(gspca_dev, ctrl->val, sd->vflip->val); - break; - case V4L2_CID_AUTOGAIN: - if (ctrl->is_new) - setautogain(gspca_dev, ctrl->val); - if (!ctrl->val && gspca_dev->exposure->is_new) - setexposure(gspca_dev, gspca_dev->exposure->val); - break; - case V4L2_CID_JPEG_COMPRESSION_QUALITY: - return -EBUSY; /* Should never happen, as we grab the ctrl */ - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .g_volatile_ctrl = sd_g_volatile_ctrl, - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 10); - if (valid_controls[sd->sensor].has_brightness) - sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, - sd->sensor == SEN_OV7660 ? 6 : 255, 1, - sd->sensor == SEN_OV7660 ? 3 : 127); - if (valid_controls[sd->sensor].has_contrast) { - if (sd->sensor == SEN_OV7660) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 6, 1, 3); - else - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 255, 1, - (sd->sensor == SEN_OV6630 || - sd->sensor == SEN_OV66308AF) ? 200 : 127); - } - if (valid_controls[sd->sensor].has_sat) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SATURATION, 0, - sd->sensor == SEN_OV7660 ? 4 : 255, 1, - sd->sensor == SEN_OV7660 ? 2 : 127); - if (valid_controls[sd->sensor].has_exposure) - gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 255, 1, 127); - if (valid_controls[sd->sensor].has_hvflip) { - sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_HFLIP, 0, 1, 1, 0); - sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_VFLIP, 0, 1, 1, 0); - } - if (valid_controls[sd->sensor].has_autobright) - sd->autobright = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_AUTOBRIGHTNESS, 0, 1, 1, 1); - if (valid_controls[sd->sensor].has_autogain) - gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - if (valid_controls[sd->sensor].has_freq) { - if (sd->sensor == SEN_OV7670) - sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, - V4L2_CID_POWER_LINE_FREQUENCY, - V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0, - V4L2_CID_POWER_LINE_FREQUENCY_AUTO); - else - sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, - V4L2_CID_POWER_LINE_FREQUENCY, - V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0); - } - if (sd->bridge == BRIDGE_W9968CF) - sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_JPEG_COMPRESSION_QUALITY, - QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - if (gspca_dev->autogain) - v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, true); - if (sd->autobright) - v4l2_ctrl_auto_cluster(2, &sd->autobright, 0, false); - if (sd->hflip) - v4l2_ctrl_cluster(2, &sd->hflip); - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .isoc_init = sd_isoc_init, - .start = sd_start, - .stopN = sd_stopN, - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, - .dq_callback = sd_reset_snapshot, - .get_jcomp = sd_get_jcomp, - .set_jcomp = sd_set_jcomp, -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .other_input = 1, -#endif -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF }, - {USB_DEVICE(0x041e, 0x4052), - .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, - {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 }, - {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, - {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 }, - {USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 }, - {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 }, - {USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 }, - {USB_DEVICE(0x045e, 0x028c), - .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, - {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, - {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 }, - {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 }, - {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, - {USB_DEVICE(0x05a9, 0x0519), - .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, - {USB_DEVICE(0x05a9, 0x0530), - .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, - {USB_DEVICE(0x05a9, 0x2800), .driver_info = BRIDGE_OVFX2 }, - {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 }, - {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 }, - {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS }, - {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS }, - {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS }, - {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 }, - {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 }, - {USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF }, - {USB_DEVICE(0x8020, 0xef04), .driver_info = BRIDGE_OVFX2 }, - {} -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); - -module_param(frame_rate, int, 0644); -MODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)"); diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c deleted file mode 100644 index bb09d7884b89..000000000000 --- a/drivers/media/video/gspca/ov534.c +++ /dev/null @@ -1,1544 +0,0 @@ -/* - * ov534-ov7xxx gspca driver - * - * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it> - * Copyright (C) 2008 Jim Paris <jim@jtan.com> - * Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr - * - * Based on a prototype written by Mark Ferrell <majortrips@gmail.com> - * USB protocol reverse engineered by Jim Paris <jim@jtan.com> - * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/ - * - * PS3 Eye camera enhanced by Richard Kaswy http://kaswy.free.fr - * PS3 Eye camera - brightness, contrast, awb, agc, aec controls - * added by Max Thrun <bear24rw@gmail.com> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "ov534" - -#include "gspca.h" - -#include <linux/fixp-arith.h> -#include <media/v4l2-ctrls.h> - -#define OV534_REG_ADDRESS 0xf1 /* sensor address */ -#define OV534_REG_SUBADDR 0xf2 -#define OV534_REG_WRITE 0xf3 -#define OV534_REG_READ 0xf4 -#define OV534_REG_OPERATION 0xf5 -#define OV534_REG_STATUS 0xf6 - -#define OV534_OP_WRITE_3 0x37 -#define OV534_OP_WRITE_2 0x33 -#define OV534_OP_READ_2 0xf9 - -#define CTRL_TIMEOUT 500 - -MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); -MODULE_DESCRIPTION("GSPCA/OV534 USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - struct v4l2_ctrl_handler ctrl_handler; - struct v4l2_ctrl *hue; - struct v4l2_ctrl *saturation; - struct v4l2_ctrl *brightness; - struct v4l2_ctrl *contrast; - struct { /* gain control cluster */ - struct v4l2_ctrl *autogain; - struct v4l2_ctrl *gain; - }; - struct v4l2_ctrl *autowhitebalance; - struct { /* exposure control cluster */ - struct v4l2_ctrl *autoexposure; - struct v4l2_ctrl *exposure; - }; - struct v4l2_ctrl *sharpness; - struct v4l2_ctrl *hflip; - struct v4l2_ctrl *vflip; - struct v4l2_ctrl *plfreq; - - __u32 last_pts; - u16 last_fid; - u8 frame_rate; - - u8 sensor; -}; -enum sensors { - SENSOR_OV767x, - SENSOR_OV772x, - NSENSORS -}; - -static int sd_start(struct gspca_dev *gspca_dev); -static void sd_stopN(struct gspca_dev *gspca_dev); - - -static const struct v4l2_pix_format ov772x_mode[] = { - {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, - .bytesperline = 320 * 2, - .sizeimage = 320 * 240 * 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, - .bytesperline = 640 * 2, - .sizeimage = 640 * 480 * 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; -static const struct v4l2_pix_format ov767x_mode[] = { - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG}, -}; - -static const u8 qvga_rates[] = {125, 100, 75, 60, 50, 40, 30}; -static const u8 vga_rates[] = {60, 50, 40, 30, 15}; - -static const struct framerates ov772x_framerates[] = { - { /* 320x240 */ - .rates = qvga_rates, - .nrates = ARRAY_SIZE(qvga_rates), - }, - { /* 640x480 */ - .rates = vga_rates, - .nrates = ARRAY_SIZE(vga_rates), - }, -}; - -struct reg_array { - const u8 (*val)[2]; - int len; -}; - -static const u8 bridge_init_767x[][2] = { -/* comments from the ms-win file apollo7670.set */ -/* str1 */ - {0xf1, 0x42}, - {0x88, 0xf8}, - {0x89, 0xff}, - {0x76, 0x03}, - {0x92, 0x03}, - {0x95, 0x10}, - {0xe2, 0x00}, - {0xe7, 0x3e}, - {0x8d, 0x1c}, - {0x8e, 0x00}, - {0x8f, 0x00}, - {0x1f, 0x00}, - {0xc3, 0xf9}, - {0x89, 0xff}, - {0x88, 0xf8}, - {0x76, 0x03}, - {0x92, 0x01}, - {0x93, 0x18}, - {0x1c, 0x00}, - {0x1d, 0x48}, - {0x1d, 0x00}, - {0x1d, 0xff}, - {0x1d, 0x02}, - {0x1d, 0x58}, - {0x1d, 0x00}, - {0x1c, 0x0a}, - {0x1d, 0x0a}, - {0x1d, 0x0e}, - {0xc0, 0x50}, /* HSize 640 */ - {0xc1, 0x3c}, /* VSize 480 */ - {0x34, 0x05}, /* enable Audio Suspend mode */ - {0xc2, 0x0c}, /* Input YUV */ - {0xc3, 0xf9}, /* enable PRE */ - {0x34, 0x05}, /* enable Audio Suspend mode */ - {0xe7, 0x2e}, /* this solves failure of "SuspendResumeTest" */ - {0x31, 0xf9}, /* enable 1.8V Suspend */ - {0x35, 0x02}, /* turn on JPEG */ - {0xd9, 0x10}, - {0x25, 0x42}, /* GPIO[8]:Input */ - {0x94, 0x11}, /* If the default setting is loaded when - * system boots up, this flag is closed here */ -}; -static const u8 sensor_init_767x[][2] = { - {0x12, 0x80}, - {0x11, 0x03}, - {0x3a, 0x04}, - {0x12, 0x00}, - {0x17, 0x13}, - {0x18, 0x01}, - {0x32, 0xb6}, - {0x19, 0x02}, - {0x1a, 0x7a}, - {0x03, 0x0a}, - {0x0c, 0x00}, - {0x3e, 0x00}, - {0x70, 0x3a}, - {0x71, 0x35}, - {0x72, 0x11}, - {0x73, 0xf0}, - {0xa2, 0x02}, - {0x7a, 0x2a}, /* set Gamma=1.6 below */ - {0x7b, 0x12}, - {0x7c, 0x1d}, - {0x7d, 0x2d}, - {0x7e, 0x45}, - {0x7f, 0x50}, - {0x80, 0x59}, - {0x81, 0x62}, - {0x82, 0x6b}, - {0x83, 0x73}, - {0x84, 0x7b}, - {0x85, 0x8a}, - {0x86, 0x98}, - {0x87, 0xb2}, - {0x88, 0xca}, - {0x89, 0xe0}, - {0x13, 0xe0}, - {0x00, 0x00}, - {0x10, 0x00}, - {0x0d, 0x40}, - {0x14, 0x38}, /* gain max 16x */ - {0xa5, 0x05}, - {0xab, 0x07}, - {0x24, 0x95}, - {0x25, 0x33}, - {0x26, 0xe3}, - {0x9f, 0x78}, - {0xa0, 0x68}, - {0xa1, 0x03}, - {0xa6, 0xd8}, - {0xa7, 0xd8}, - {0xa8, 0xf0}, - {0xa9, 0x90}, - {0xaa, 0x94}, - {0x13, 0xe5}, - {0x0e, 0x61}, - {0x0f, 0x4b}, - {0x16, 0x02}, - {0x21, 0x02}, - {0x22, 0x91}, - {0x29, 0x07}, - {0x33, 0x0b}, - {0x35, 0x0b}, - {0x37, 0x1d}, - {0x38, 0x71}, - {0x39, 0x2a}, - {0x3c, 0x78}, - {0x4d, 0x40}, - {0x4e, 0x20}, - {0x69, 0x00}, - {0x6b, 0x4a}, - {0x74, 0x10}, - {0x8d, 0x4f}, - {0x8e, 0x00}, - {0x8f, 0x00}, - {0x90, 0x00}, - {0x91, 0x00}, - {0x96, 0x00}, - {0x9a, 0x80}, - {0xb0, 0x84}, - {0xb1, 0x0c}, - {0xb2, 0x0e}, - {0xb3, 0x82}, - {0xb8, 0x0a}, - {0x43, 0x0a}, - {0x44, 0xf0}, - {0x45, 0x34}, - {0x46, 0x58}, - {0x47, 0x28}, - {0x48, 0x3a}, - {0x59, 0x88}, - {0x5a, 0x88}, - {0x5b, 0x44}, - {0x5c, 0x67}, - {0x5d, 0x49}, - {0x5e, 0x0e}, - {0x6c, 0x0a}, - {0x6d, 0x55}, - {0x6e, 0x11}, - {0x6f, 0x9f}, - {0x6a, 0x40}, - {0x01, 0x40}, - {0x02, 0x40}, - {0x13, 0xe7}, - {0x4f, 0x80}, - {0x50, 0x80}, - {0x51, 0x00}, - {0x52, 0x22}, - {0x53, 0x5e}, - {0x54, 0x80}, - {0x58, 0x9e}, - {0x41, 0x08}, - {0x3f, 0x00}, - {0x75, 0x04}, - {0x76, 0xe1}, - {0x4c, 0x00}, - {0x77, 0x01}, - {0x3d, 0xc2}, - {0x4b, 0x09}, - {0xc9, 0x60}, - {0x41, 0x38}, /* jfm: auto sharpness + auto de-noise */ - {0x56, 0x40}, - {0x34, 0x11}, - {0x3b, 0xc2}, - {0xa4, 0x8a}, /* Night mode trigger point */ - {0x96, 0x00}, - {0x97, 0x30}, - {0x98, 0x20}, - {0x99, 0x20}, - {0x9a, 0x84}, - {0x9b, 0x29}, - {0x9c, 0x03}, - {0x9d, 0x4c}, - {0x9e, 0x3f}, - {0x78, 0x04}, - {0x79, 0x01}, - {0xc8, 0xf0}, - {0x79, 0x0f}, - {0xc8, 0x00}, - {0x79, 0x10}, - {0xc8, 0x7e}, - {0x79, 0x0a}, - {0xc8, 0x80}, - {0x79, 0x0b}, - {0xc8, 0x01}, - {0x79, 0x0c}, - {0xc8, 0x0f}, - {0x79, 0x0d}, - {0xc8, 0x20}, - {0x79, 0x09}, - {0xc8, 0x80}, - {0x79, 0x02}, - {0xc8, 0xc0}, - {0x79, 0x03}, - {0xc8, 0x20}, - {0x79, 0x26}, -}; -static const u8 bridge_start_vga_767x[][2] = { -/* str59 JPG */ - {0x94, 0xaa}, - {0xf1, 0x42}, - {0xe5, 0x04}, - {0xc0, 0x50}, - {0xc1, 0x3c}, - {0xc2, 0x0c}, - {0x35, 0x02}, /* turn on JPEG */ - {0xd9, 0x10}, - {0xda, 0x00}, /* for higher clock rate(30fps) */ - {0x34, 0x05}, /* enable Audio Suspend mode */ - {0xc3, 0xf9}, /* enable PRE */ - {0x8c, 0x00}, /* CIF VSize LSB[2:0] */ - {0x8d, 0x1c}, /* output YUV */ -/* {0x34, 0x05}, * enable Audio Suspend mode (?) */ - {0x50, 0x00}, /* H/V divider=0 */ - {0x51, 0xa0}, /* input H=640/4 */ - {0x52, 0x3c}, /* input V=480/4 */ - {0x53, 0x00}, /* offset X=0 */ - {0x54, 0x00}, /* offset Y=0 */ - {0x55, 0x00}, /* H/V size[8]=0 */ - {0x57, 0x00}, /* H-size[9]=0 */ - {0x5c, 0x00}, /* output size[9:8]=0 */ - {0x5a, 0xa0}, /* output H=640/4 */ - {0x5b, 0x78}, /* output V=480/4 */ - {0x1c, 0x0a}, - {0x1d, 0x0a}, - {0x94, 0x11}, -}; -static const u8 sensor_start_vga_767x[][2] = { - {0x11, 0x01}, - {0x1e, 0x04}, - {0x19, 0x02}, - {0x1a, 0x7a}, -}; -static const u8 bridge_start_qvga_767x[][2] = { -/* str86 JPG */ - {0x94, 0xaa}, - {0xf1, 0x42}, - {0xe5, 0x04}, - {0xc0, 0x80}, - {0xc1, 0x60}, - {0xc2, 0x0c}, - {0x35, 0x02}, /* turn on JPEG */ - {0xd9, 0x10}, - {0xc0, 0x50}, /* CIF HSize 640 */ - {0xc1, 0x3c}, /* CIF VSize 480 */ - {0x8c, 0x00}, /* CIF VSize LSB[2:0] */ - {0x8d, 0x1c}, /* output YUV */ - {0x34, 0x05}, /* enable Audio Suspend mode */ - {0xc2, 0x4c}, /* output YUV and Enable DCW */ - {0xc3, 0xf9}, /* enable PRE */ - {0x1c, 0x00}, /* indirect addressing */ - {0x1d, 0x48}, /* output YUV422 */ - {0x50, 0x89}, /* H/V divider=/2; plus DCW AVG */ - {0x51, 0xa0}, /* DCW input H=640/4 */ - {0x52, 0x78}, /* DCW input V=480/4 */ - {0x53, 0x00}, /* offset X=0 */ - {0x54, 0x00}, /* offset Y=0 */ - {0x55, 0x00}, /* H/V size[8]=0 */ - {0x57, 0x00}, /* H-size[9]=0 */ - {0x5c, 0x00}, /* DCW output size[9:8]=0 */ - {0x5a, 0x50}, /* DCW output H=320/4 */ - {0x5b, 0x3c}, /* DCW output V=240/4 */ - {0x1c, 0x0a}, - {0x1d, 0x0a}, - {0x94, 0x11}, -}; -static const u8 sensor_start_qvga_767x[][2] = { - {0x11, 0x01}, - {0x1e, 0x04}, - {0x19, 0x02}, - {0x1a, 0x7a}, -}; - -static const u8 bridge_init_772x[][2] = { - { 0xc2, 0x0c }, - { 0x88, 0xf8 }, - { 0xc3, 0x69 }, - { 0x89, 0xff }, - { 0x76, 0x03 }, - { 0x92, 0x01 }, - { 0x93, 0x18 }, - { 0x94, 0x10 }, - { 0x95, 0x10 }, - { 0xe2, 0x00 }, - { 0xe7, 0x3e }, - - { 0x96, 0x00 }, - - { 0x97, 0x20 }, - { 0x97, 0x20 }, - { 0x97, 0x20 }, - { 0x97, 0x0a }, - { 0x97, 0x3f }, - { 0x97, 0x4a }, - { 0x97, 0x20 }, - { 0x97, 0x15 }, - { 0x97, 0x0b }, - - { 0x8e, 0x40 }, - { 0x1f, 0x81 }, - { 0x34, 0x05 }, - { 0xe3, 0x04 }, - { 0x88, 0x00 }, - { 0x89, 0x00 }, - { 0x76, 0x00 }, - { 0xe7, 0x2e }, - { 0x31, 0xf9 }, - { 0x25, 0x42 }, - { 0x21, 0xf0 }, - - { 0x1c, 0x00 }, - { 0x1d, 0x40 }, - { 0x1d, 0x02 }, /* payload size 0x0200 * 4 = 2048 bytes */ - { 0x1d, 0x00 }, /* payload size */ - - { 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */ - { 0x1d, 0x58 }, /* frame size */ - { 0x1d, 0x00 }, /* frame size */ - - { 0x1c, 0x0a }, - { 0x1d, 0x08 }, /* turn on UVC header */ - { 0x1d, 0x0e }, /* .. */ - - { 0x8d, 0x1c }, - { 0x8e, 0x80 }, - { 0xe5, 0x04 }, - - { 0xc0, 0x50 }, - { 0xc1, 0x3c }, - { 0xc2, 0x0c }, -}; -static const u8 sensor_init_772x[][2] = { - { 0x12, 0x80 }, - { 0x11, 0x01 }, -/*fixme: better have a delay?*/ - { 0x11, 0x01 }, - { 0x11, 0x01 }, - { 0x11, 0x01 }, - { 0x11, 0x01 }, - { 0x11, 0x01 }, - { 0x11, 0x01 }, - { 0x11, 0x01 }, - { 0x11, 0x01 }, - { 0x11, 0x01 }, - { 0x11, 0x01 }, - - { 0x3d, 0x03 }, - { 0x17, 0x26 }, - { 0x18, 0xa0 }, - { 0x19, 0x07 }, - { 0x1a, 0xf0 }, - { 0x32, 0x00 }, - { 0x29, 0xa0 }, - { 0x2c, 0xf0 }, - { 0x65, 0x20 }, - { 0x11, 0x01 }, - { 0x42, 0x7f }, - { 0x63, 0xaa }, /* AWB - was e0 */ - { 0x64, 0xff }, - { 0x66, 0x00 }, - { 0x13, 0xf0 }, /* com8 */ - { 0x0d, 0x41 }, - { 0x0f, 0xc5 }, - { 0x14, 0x11 }, - - { 0x22, 0x7f }, - { 0x23, 0x03 }, - { 0x24, 0x40 }, - { 0x25, 0x30 }, - { 0x26, 0xa1 }, - { 0x2a, 0x00 }, - { 0x2b, 0x00 }, - { 0x6b, 0xaa }, - { 0x13, 0xff }, /* AWB */ - - { 0x90, 0x05 }, - { 0x91, 0x01 }, - { 0x92, 0x03 }, - { 0x93, 0x00 }, - { 0x94, 0x60 }, - { 0x95, 0x3c }, - { 0x96, 0x24 }, - { 0x97, 0x1e }, - { 0x98, 0x62 }, - { 0x99, 0x80 }, - { 0x9a, 0x1e }, - { 0x9b, 0x08 }, - { 0x9c, 0x20 }, - { 0x9e, 0x81 }, - - { 0xa6, 0x07 }, - { 0x7e, 0x0c }, - { 0x7f, 0x16 }, - { 0x80, 0x2a }, - { 0x81, 0x4e }, - { 0x82, 0x61 }, - { 0x83, 0x6f }, - { 0x84, 0x7b }, - { 0x85, 0x86 }, - { 0x86, 0x8e }, - { 0x87, 0x97 }, - { 0x88, 0xa4 }, - { 0x89, 0xaf }, - { 0x8a, 0xc5 }, - { 0x8b, 0xd7 }, - { 0x8c, 0xe8 }, - { 0x8d, 0x20 }, - - { 0x0c, 0x90 }, - - { 0x2b, 0x00 }, - { 0x22, 0x7f }, - { 0x23, 0x03 }, - { 0x11, 0x01 }, - { 0x0c, 0xd0 }, - { 0x64, 0xff }, - { 0x0d, 0x41 }, - - { 0x14, 0x41 }, - { 0x0e, 0xcd }, - { 0xac, 0xbf }, - { 0x8e, 0x00 }, /* De-noise threshold */ - { 0x0c, 0xd0 } -}; -static const u8 bridge_start_vga_772x[][2] = { - {0x1c, 0x00}, - {0x1d, 0x40}, - {0x1d, 0x02}, - {0x1d, 0x00}, - {0x1d, 0x02}, - {0x1d, 0x58}, - {0x1d, 0x00}, - {0xc0, 0x50}, - {0xc1, 0x3c}, -}; -static const u8 sensor_start_vga_772x[][2] = { - {0x12, 0x00}, - {0x17, 0x26}, - {0x18, 0xa0}, - {0x19, 0x07}, - {0x1a, 0xf0}, - {0x29, 0xa0}, - {0x2c, 0xf0}, - {0x65, 0x20}, -}; -static const u8 bridge_start_qvga_772x[][2] = { - {0x1c, 0x00}, - {0x1d, 0x40}, - {0x1d, 0x02}, - {0x1d, 0x00}, - {0x1d, 0x01}, - {0x1d, 0x4b}, - {0x1d, 0x00}, - {0xc0, 0x28}, - {0xc1, 0x1e}, -}; -static const u8 sensor_start_qvga_772x[][2] = { - {0x12, 0x40}, - {0x17, 0x3f}, - {0x18, 0x50}, - {0x19, 0x03}, - {0x1a, 0x78}, - {0x29, 0x50}, - {0x2c, 0x78}, - {0x65, 0x2f}, -}; - -static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) -{ - struct usb_device *udev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return; - - PDEBUG(D_USBO, "SET 01 0000 %04x %02x", reg, val); - gspca_dev->usb_buf[0] = val; - ret = usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), - 0x01, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); - if (ret < 0) { - pr_err("write failed %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg) -{ - struct usb_device *udev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return 0; - ret = usb_control_msg(udev, - usb_rcvctrlpipe(udev, 0), - 0x01, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); - PDEBUG(D_USBI, "GET 01 0000 %04x %02x", reg, gspca_dev->usb_buf[0]); - if (ret < 0) { - pr_err("read failed %d\n", ret); - gspca_dev->usb_err = ret; - } - return gspca_dev->usb_buf[0]; -} - -/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7. - * (direction and output)? */ -static void ov534_set_led(struct gspca_dev *gspca_dev, int status) -{ - u8 data; - - PDEBUG(D_CONF, "led status: %d", status); - - data = ov534_reg_read(gspca_dev, 0x21); - data |= 0x80; - ov534_reg_write(gspca_dev, 0x21, data); - - data = ov534_reg_read(gspca_dev, 0x23); - if (status) - data |= 0x80; - else - data &= ~0x80; - - ov534_reg_write(gspca_dev, 0x23, data); - - if (!status) { - data = ov534_reg_read(gspca_dev, 0x21); - data &= ~0x80; - ov534_reg_write(gspca_dev, 0x21, data); - } -} - -static int sccb_check_status(struct gspca_dev *gspca_dev) -{ - u8 data; - int i; - - for (i = 0; i < 5; i++) { - msleep(10); - data = ov534_reg_read(gspca_dev, OV534_REG_STATUS); - - switch (data) { - case 0x00: - return 1; - case 0x04: - return 0; - case 0x03: - break; - default: - PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5", - data, i + 1); - } - } - return 0; -} - -static void sccb_reg_write(struct gspca_dev *gspca_dev, u8 reg, u8 val) -{ - PDEBUG(D_USBO, "sccb write: %02x %02x", reg, val); - ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg); - ov534_reg_write(gspca_dev, OV534_REG_WRITE, val); - ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3); - - if (!sccb_check_status(gspca_dev)) { - pr_err("sccb_reg_write failed\n"); - gspca_dev->usb_err = -EIO; - } -} - -static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg) -{ - ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg); - ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2); - if (!sccb_check_status(gspca_dev)) - pr_err("sccb_reg_read failed 1\n"); - - ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2); - if (!sccb_check_status(gspca_dev)) - pr_err("sccb_reg_read failed 2\n"); - - return ov534_reg_read(gspca_dev, OV534_REG_READ); -} - -/* output a bridge sequence (reg - val) */ -static void reg_w_array(struct gspca_dev *gspca_dev, - const u8 (*data)[2], int len) -{ - while (--len >= 0) { - ov534_reg_write(gspca_dev, (*data)[0], (*data)[1]); - data++; - } -} - -/* output a sensor sequence (reg - val) */ -static void sccb_w_array(struct gspca_dev *gspca_dev, - const u8 (*data)[2], int len) -{ - while (--len >= 0) { - if ((*data)[0] != 0xff) { - sccb_reg_write(gspca_dev, (*data)[0], (*data)[1]); - } else { - sccb_reg_read(gspca_dev, (*data)[1]); - sccb_reg_write(gspca_dev, 0xff, 0x00); - } - data++; - } -} - -/* ov772x specific controls */ -static void set_frame_rate(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i; - struct rate_s { - u8 fps; - u8 r11; - u8 r0d; - u8 re5; - }; - const struct rate_s *r; - static const struct rate_s rate_0[] = { /* 640x480 */ - {60, 0x01, 0xc1, 0x04}, - {50, 0x01, 0x41, 0x02}, - {40, 0x02, 0xc1, 0x04}, - {30, 0x04, 0x81, 0x02}, - {15, 0x03, 0x41, 0x04}, - }; - static const struct rate_s rate_1[] = { /* 320x240 */ - {125, 0x02, 0x81, 0x02}, - {100, 0x02, 0xc1, 0x04}, - {75, 0x03, 0xc1, 0x04}, - {60, 0x04, 0xc1, 0x04}, - {50, 0x02, 0x41, 0x04}, - {40, 0x03, 0x41, 0x04}, - {30, 0x04, 0x41, 0x04}, - }; - - if (sd->sensor != SENSOR_OV772x) - return; - if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv == 0) { - r = rate_0; - i = ARRAY_SIZE(rate_0); - } else { - r = rate_1; - i = ARRAY_SIZE(rate_1); - } - while (--i > 0) { - if (sd->frame_rate >= r->fps) - break; - r++; - } - - sccb_reg_write(gspca_dev, 0x11, r->r11); - sccb_reg_write(gspca_dev, 0x0d, r->r0d); - ov534_reg_write(gspca_dev, 0xe5, r->re5); - - PDEBUG(D_PROBE, "frame_rate: %d", r->fps); -} - -static void sethue(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_OV767x) { - /* TBD */ - } else { - s16 huesin; - s16 huecos; - - /* fixp_sin and fixp_cos accept only positive values, while - * our val is between -90 and 90 - */ - val += 360; - - /* According to the datasheet the registers expect HUESIN and - * HUECOS to be the result of the trigonometric functions, - * scaled by 0x80. - * - * The 0x100 here represents the maximun absolute value - * returned byt fixp_sin and fixp_cos, so the scaling will - * consider the result like in the interval [-1.0, 1.0]. - */ - huesin = fixp_sin(val) * 0x80 / 0x100; - huecos = fixp_cos(val) * 0x80 / 0x100; - - if (huesin < 0) { - sccb_reg_write(gspca_dev, 0xab, - sccb_reg_read(gspca_dev, 0xab) | 0x2); - huesin = -huesin; - } else { - sccb_reg_write(gspca_dev, 0xab, - sccb_reg_read(gspca_dev, 0xab) & ~0x2); - - } - sccb_reg_write(gspca_dev, 0xa9, (u8)huecos); - sccb_reg_write(gspca_dev, 0xaa, (u8)huesin); - } -} - -static void setsaturation(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_OV767x) { - int i; - static u8 color_tb[][6] = { - {0x42, 0x42, 0x00, 0x11, 0x30, 0x41}, - {0x52, 0x52, 0x00, 0x16, 0x3c, 0x52}, - {0x66, 0x66, 0x00, 0x1b, 0x4b, 0x66}, - {0x80, 0x80, 0x00, 0x22, 0x5e, 0x80}, - {0x9a, 0x9a, 0x00, 0x29, 0x71, 0x9a}, - {0xb8, 0xb8, 0x00, 0x31, 0x87, 0xb8}, - {0xdd, 0xdd, 0x00, 0x3b, 0xa2, 0xdd}, - }; - - for (i = 0; i < ARRAY_SIZE(color_tb[0]); i++) - sccb_reg_write(gspca_dev, 0x4f + i, color_tb[val][i]); - } else { - sccb_reg_write(gspca_dev, 0xa7, val); /* U saturation */ - sccb_reg_write(gspca_dev, 0xa8, val); /* V saturation */ - } -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_OV767x) { - if (val < 0) - val = 0x80 - val; - sccb_reg_write(gspca_dev, 0x55, val); /* bright */ - } else { - sccb_reg_write(gspca_dev, 0x9b, val); - } -} - -static void setcontrast(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_OV767x) - sccb_reg_write(gspca_dev, 0x56, val); /* contras */ - else - sccb_reg_write(gspca_dev, 0x9c, val); -} - -static void setgain(struct gspca_dev *gspca_dev, s32 val) -{ - switch (val & 0x30) { - case 0x00: - val &= 0x0f; - break; - case 0x10: - val &= 0x0f; - val |= 0x30; - break; - case 0x20: - val &= 0x0f; - val |= 0x70; - break; - default: -/* case 0x30: */ - val &= 0x0f; - val |= 0xf0; - break; - } - sccb_reg_write(gspca_dev, 0x00, val); -} - -static s32 getgain(struct gspca_dev *gspca_dev) -{ - return sccb_reg_read(gspca_dev, 0x00); -} - -static void setexposure(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_OV767x) { - - /* set only aec[9:2] */ - sccb_reg_write(gspca_dev, 0x10, val); /* aech */ - } else { - - /* 'val' is one byte and represents half of the exposure value - * we are going to set into registers, a two bytes value: - * - * MSB: ((u16) val << 1) >> 8 == val >> 7 - * LSB: ((u16) val << 1) & 0xff == val << 1 - */ - sccb_reg_write(gspca_dev, 0x08, val >> 7); - sccb_reg_write(gspca_dev, 0x10, val << 1); - } -} - -static s32 getexposure(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_OV767x) { - /* get only aec[9:2] */ - return sccb_reg_read(gspca_dev, 0x10); /* aech */ - } else { - u8 hi = sccb_reg_read(gspca_dev, 0x08); - u8 lo = sccb_reg_read(gspca_dev, 0x10); - return (hi << 8 | lo) >> 1; - } -} - -static void setagc(struct gspca_dev *gspca_dev, s32 val) -{ - if (val) { - sccb_reg_write(gspca_dev, 0x13, - sccb_reg_read(gspca_dev, 0x13) | 0x04); - sccb_reg_write(gspca_dev, 0x64, - sccb_reg_read(gspca_dev, 0x64) | 0x03); - } else { - sccb_reg_write(gspca_dev, 0x13, - sccb_reg_read(gspca_dev, 0x13) & ~0x04); - sccb_reg_write(gspca_dev, 0x64, - sccb_reg_read(gspca_dev, 0x64) & ~0x03); - } -} - -static void setawb(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (val) { - sccb_reg_write(gspca_dev, 0x13, - sccb_reg_read(gspca_dev, 0x13) | 0x02); - if (sd->sensor == SENSOR_OV772x) - sccb_reg_write(gspca_dev, 0x63, - sccb_reg_read(gspca_dev, 0x63) | 0xc0); - } else { - sccb_reg_write(gspca_dev, 0x13, - sccb_reg_read(gspca_dev, 0x13) & ~0x02); - if (sd->sensor == SENSOR_OV772x) - sccb_reg_write(gspca_dev, 0x63, - sccb_reg_read(gspca_dev, 0x63) & ~0xc0); - } -} - -static void setaec(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 data; - - data = sd->sensor == SENSOR_OV767x ? - 0x05 : /* agc + aec */ - 0x01; /* agc */ - switch (val) { - case V4L2_EXPOSURE_AUTO: - sccb_reg_write(gspca_dev, 0x13, - sccb_reg_read(gspca_dev, 0x13) | data); - break; - case V4L2_EXPOSURE_MANUAL: - sccb_reg_write(gspca_dev, 0x13, - sccb_reg_read(gspca_dev, 0x13) & ~data); - break; - } -} - -static void setsharpness(struct gspca_dev *gspca_dev, s32 val) -{ - sccb_reg_write(gspca_dev, 0x91, val); /* Auto de-noise threshold */ - sccb_reg_write(gspca_dev, 0x8e, val); /* De-noise threshold */ -} - -static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 val; - - if (sd->sensor == SENSOR_OV767x) { - val = sccb_reg_read(gspca_dev, 0x1e); /* mvfp */ - val &= ~0x30; - if (hflip) - val |= 0x20; - if (vflip) - val |= 0x10; - sccb_reg_write(gspca_dev, 0x1e, val); - } else { - val = sccb_reg_read(gspca_dev, 0x0c); - val &= ~0xc0; - if (hflip == 0) - val |= 0x40; - if (vflip == 0) - val |= 0x80; - sccb_reg_write(gspca_dev, 0x0c, val); - } -} - -static void setlightfreq(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - val = val ? 0x9e : 0x00; - if (sd->sensor == SENSOR_OV767x) { - sccb_reg_write(gspca_dev, 0x2a, 0x00); - if (val) - val = 0x9d; /* insert dummy to 25fps for 50Hz */ - } - sccb_reg_write(gspca_dev, 0x2b, val); -} - - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - - cam = &gspca_dev->cam; - - cam->cam_mode = ov772x_mode; - cam->nmodes = ARRAY_SIZE(ov772x_mode); - - sd->frame_rate = 30; - - return 0; -} - -static int ov534_g_volatile_ctrl(struct v4l2_ctrl *ctrl) -{ - struct sd *sd = container_of(ctrl->handler, struct sd, ctrl_handler); - struct gspca_dev *gspca_dev = &sd->gspca_dev; - - switch (ctrl->id) { - case V4L2_CID_AUTOGAIN: - gspca_dev->usb_err = 0; - if (ctrl->val && sd->gain && gspca_dev->streaming) - sd->gain->val = getgain(gspca_dev); - return gspca_dev->usb_err; - - case V4L2_CID_EXPOSURE_AUTO: - gspca_dev->usb_err = 0; - if (ctrl->val == V4L2_EXPOSURE_AUTO && sd->exposure && - gspca_dev->streaming) - sd->exposure->val = getexposure(gspca_dev); - return gspca_dev->usb_err; - } - return -EINVAL; -} - -static int ov534_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct sd *sd = container_of(ctrl->handler, struct sd, ctrl_handler); - struct gspca_dev *gspca_dev = &sd->gspca_dev; - - gspca_dev->usb_err = 0; - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_HUE: - sethue(gspca_dev, ctrl->val); - break; - case V4L2_CID_SATURATION: - setsaturation(gspca_dev, ctrl->val); - break; - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_CONTRAST: - setcontrast(gspca_dev, ctrl->val); - break; - case V4L2_CID_AUTOGAIN: - /* case V4L2_CID_GAIN: */ - setagc(gspca_dev, ctrl->val); - if (!gspca_dev->usb_err && !ctrl->val && sd->gain) - setgain(gspca_dev, sd->gain->val); - break; - case V4L2_CID_AUTO_WHITE_BALANCE: - setawb(gspca_dev, ctrl->val); - break; - case V4L2_CID_EXPOSURE_AUTO: - /* case V4L2_CID_EXPOSURE: */ - setaec(gspca_dev, ctrl->val); - if (!gspca_dev->usb_err && ctrl->val == V4L2_EXPOSURE_MANUAL && - sd->exposure) - setexposure(gspca_dev, sd->exposure->val); - break; - case V4L2_CID_SHARPNESS: - setsharpness(gspca_dev, ctrl->val); - break; - case V4L2_CID_HFLIP: - sethvflip(gspca_dev, ctrl->val, sd->vflip->val); - break; - case V4L2_CID_VFLIP: - sethvflip(gspca_dev, sd->hflip->val, ctrl->val); - break; - case V4L2_CID_POWER_LINE_FREQUENCY: - setlightfreq(gspca_dev, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops ov534_ctrl_ops = { - .g_volatile_ctrl = ov534_g_volatile_ctrl, - .s_ctrl = ov534_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct v4l2_ctrl_handler *hdl = &sd->ctrl_handler; - /* parameters with different values between the supported sensors */ - int saturation_min; - int saturation_max; - int saturation_def; - int brightness_min; - int brightness_max; - int brightness_def; - int contrast_max; - int contrast_def; - int exposure_min; - int exposure_max; - int exposure_def; - int hflip_def; - - if (sd->sensor == SENSOR_OV767x) { - saturation_min = 0, - saturation_max = 6, - saturation_def = 3, - brightness_min = -127; - brightness_max = 127; - brightness_def = 0; - contrast_max = 0x80; - contrast_def = 0x40; - exposure_min = 0x08; - exposure_max = 0x60; - exposure_def = 0x13; - hflip_def = 1; - } else { - saturation_min = 0, - saturation_max = 255, - saturation_def = 64, - brightness_min = 0; - brightness_max = 255; - brightness_def = 0; - contrast_max = 255; - contrast_def = 32; - exposure_min = 0; - exposure_max = 255; - exposure_def = 120; - hflip_def = 0; - } - - gspca_dev->vdev.ctrl_handler = hdl; - - v4l2_ctrl_handler_init(hdl, 13); - - if (sd->sensor == SENSOR_OV772x) - sd->hue = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops, - V4L2_CID_HUE, -90, 90, 1, 0); - - sd->saturation = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops, - V4L2_CID_SATURATION, saturation_min, saturation_max, 1, - saturation_def); - sd->brightness = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops, - V4L2_CID_BRIGHTNESS, brightness_min, brightness_max, 1, - brightness_def); - sd->contrast = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops, - V4L2_CID_CONTRAST, 0, contrast_max, 1, contrast_def); - - if (sd->sensor == SENSOR_OV772x) { - sd->autogain = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - sd->gain = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops, - V4L2_CID_GAIN, 0, 63, 1, 20); - } - - sd->autoexposure = v4l2_ctrl_new_std_menu(hdl, &ov534_ctrl_ops, - V4L2_CID_EXPOSURE_AUTO, - V4L2_EXPOSURE_MANUAL, 0, - V4L2_EXPOSURE_AUTO); - sd->exposure = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops, - V4L2_CID_EXPOSURE, exposure_min, exposure_max, 1, - exposure_def); - - sd->autowhitebalance = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops, - V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1); - - if (sd->sensor == SENSOR_OV772x) - sd->sharpness = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops, - V4L2_CID_SHARPNESS, 0, 63, 1, 0); - - sd->hflip = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops, - V4L2_CID_HFLIP, 0, 1, 1, hflip_def); - sd->vflip = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops, - V4L2_CID_VFLIP, 0, 1, 1, 0); - sd->plfreq = v4l2_ctrl_new_std_menu(hdl, &ov534_ctrl_ops, - V4L2_CID_POWER_LINE_FREQUENCY, - V4L2_CID_POWER_LINE_FREQUENCY_50HZ, 0, - V4L2_CID_POWER_LINE_FREQUENCY_DISABLED); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - - if (sd->sensor == SENSOR_OV772x) - v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, true); - - v4l2_ctrl_auto_cluster(2, &sd->autoexposure, V4L2_EXPOSURE_MANUAL, - true); - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u16 sensor_id; - static const struct reg_array bridge_init[NSENSORS] = { - [SENSOR_OV767x] = {bridge_init_767x, ARRAY_SIZE(bridge_init_767x)}, - [SENSOR_OV772x] = {bridge_init_772x, ARRAY_SIZE(bridge_init_772x)}, - }; - static const struct reg_array sensor_init[NSENSORS] = { - [SENSOR_OV767x] = {sensor_init_767x, ARRAY_SIZE(sensor_init_767x)}, - [SENSOR_OV772x] = {sensor_init_772x, ARRAY_SIZE(sensor_init_772x)}, - }; - - /* reset bridge */ - ov534_reg_write(gspca_dev, 0xe7, 0x3a); - ov534_reg_write(gspca_dev, 0xe0, 0x08); - msleep(100); - - /* initialize the sensor address */ - ov534_reg_write(gspca_dev, OV534_REG_ADDRESS, 0x42); - - /* reset sensor */ - sccb_reg_write(gspca_dev, 0x12, 0x80); - msleep(10); - - /* probe the sensor */ - sccb_reg_read(gspca_dev, 0x0a); - sensor_id = sccb_reg_read(gspca_dev, 0x0a) << 8; - sccb_reg_read(gspca_dev, 0x0b); - sensor_id |= sccb_reg_read(gspca_dev, 0x0b); - PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id); - - if ((sensor_id & 0xfff0) == 0x7670) { - sd->sensor = SENSOR_OV767x; - gspca_dev->cam.cam_mode = ov767x_mode; - gspca_dev->cam.nmodes = ARRAY_SIZE(ov767x_mode); - } else { - sd->sensor = SENSOR_OV772x; - gspca_dev->cam.bulk = 1; - gspca_dev->cam.bulk_size = 16384; - gspca_dev->cam.bulk_nurbs = 2; - gspca_dev->cam.mode_framerates = ov772x_framerates; - } - - /* initialize */ - reg_w_array(gspca_dev, bridge_init[sd->sensor].val, - bridge_init[sd->sensor].len); - ov534_set_led(gspca_dev, 1); - sccb_w_array(gspca_dev, sensor_init[sd->sensor].val, - sensor_init[sd->sensor].len); - if (sd->sensor == SENSOR_OV767x) - sd_start(gspca_dev); - sd_stopN(gspca_dev); -/* set_frame_rate(gspca_dev); */ - - return gspca_dev->usb_err; -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int mode; - static const struct reg_array bridge_start[NSENSORS][2] = { - [SENSOR_OV767x] = {{bridge_start_qvga_767x, - ARRAY_SIZE(bridge_start_qvga_767x)}, - {bridge_start_vga_767x, - ARRAY_SIZE(bridge_start_vga_767x)}}, - [SENSOR_OV772x] = {{bridge_start_qvga_772x, - ARRAY_SIZE(bridge_start_qvga_772x)}, - {bridge_start_vga_772x, - ARRAY_SIZE(bridge_start_vga_772x)}}, - }; - static const struct reg_array sensor_start[NSENSORS][2] = { - [SENSOR_OV767x] = {{sensor_start_qvga_767x, - ARRAY_SIZE(sensor_start_qvga_767x)}, - {sensor_start_vga_767x, - ARRAY_SIZE(sensor_start_vga_767x)}}, - [SENSOR_OV772x] = {{sensor_start_qvga_772x, - ARRAY_SIZE(sensor_start_qvga_772x)}, - {sensor_start_vga_772x, - ARRAY_SIZE(sensor_start_vga_772x)}}, - }; - - /* (from ms-win trace) */ - if (sd->sensor == SENSOR_OV767x) - sccb_reg_write(gspca_dev, 0x1e, 0x04); - /* black sun enable ? */ - - mode = gspca_dev->curr_mode; /* 0: 320x240, 1: 640x480 */ - reg_w_array(gspca_dev, bridge_start[sd->sensor][mode].val, - bridge_start[sd->sensor][mode].len); - sccb_w_array(gspca_dev, sensor_start[sd->sensor][mode].val, - sensor_start[sd->sensor][mode].len); - - set_frame_rate(gspca_dev); - - if (sd->hue) - sethue(gspca_dev, v4l2_ctrl_g_ctrl(sd->hue)); - setsaturation(gspca_dev, v4l2_ctrl_g_ctrl(sd->saturation)); - if (sd->autogain) - setagc(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain)); - setawb(gspca_dev, v4l2_ctrl_g_ctrl(sd->autowhitebalance)); - setaec(gspca_dev, v4l2_ctrl_g_ctrl(sd->autoexposure)); - if (sd->gain) - setgain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain)); - setexposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure)); - setbrightness(gspca_dev, v4l2_ctrl_g_ctrl(sd->brightness)); - setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->contrast)); - if (sd->sharpness) - setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness)); - sethvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip), - v4l2_ctrl_g_ctrl(sd->vflip)); - setlightfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->plfreq)); - - ov534_set_led(gspca_dev, 1); - ov534_reg_write(gspca_dev, 0xe0, 0x00); - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - ov534_reg_write(gspca_dev, 0xe0, 0x09); - ov534_set_led(gspca_dev, 0); -} - -/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ -#define UVC_STREAM_EOH (1 << 7) -#define UVC_STREAM_ERR (1 << 6) -#define UVC_STREAM_STI (1 << 5) -#define UVC_STREAM_RES (1 << 4) -#define UVC_STREAM_SCR (1 << 3) -#define UVC_STREAM_PTS (1 << 2) -#define UVC_STREAM_EOF (1 << 1) -#define UVC_STREAM_FID (1 << 0) - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - __u32 this_pts; - u16 this_fid; - int remaining_len = len; - int payload_len; - - payload_len = gspca_dev->cam.bulk ? 2048 : 2040; - do { - len = min(remaining_len, payload_len); - - /* Payloads are prefixed with a UVC-style header. We - consider a frame to start when the FID toggles, or the PTS - changes. A frame ends when EOF is set, and we've received - the correct number of bytes. */ - - /* Verify UVC header. Header length is always 12 */ - if (data[0] != 12 || len < 12) { - PDEBUG(D_PACK, "bad header"); - goto discard; - } - - /* Check errors */ - if (data[1] & UVC_STREAM_ERR) { - PDEBUG(D_PACK, "payload error"); - goto discard; - } - - /* Extract PTS and FID */ - if (!(data[1] & UVC_STREAM_PTS)) { - PDEBUG(D_PACK, "PTS not present"); - goto discard; - } - this_pts = (data[5] << 24) | (data[4] << 16) - | (data[3] << 8) | data[2]; - this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0; - - /* If PTS or FID has changed, start a new frame. */ - if (this_pts != sd->last_pts || this_fid != sd->last_fid) { - if (gspca_dev->last_packet_type == INTER_PACKET) - gspca_frame_add(gspca_dev, LAST_PACKET, - NULL, 0); - sd->last_pts = this_pts; - sd->last_fid = this_fid; - gspca_frame_add(gspca_dev, FIRST_PACKET, - data + 12, len - 12); - /* If this packet is marked as EOF, end the frame */ - } else if (data[1] & UVC_STREAM_EOF) { - sd->last_pts = 0; - if (gspca_dev->pixfmt == V4L2_PIX_FMT_YUYV - && gspca_dev->image_len + len - 12 != - gspca_dev->width * gspca_dev->height * 2) { - PDEBUG(D_PACK, "wrong sized frame"); - goto discard; - } - gspca_frame_add(gspca_dev, LAST_PACKET, - data + 12, len - 12); - } else { - - /* Add the data from this payload */ - gspca_frame_add(gspca_dev, INTER_PACKET, - data + 12, len - 12); - } - - /* Done this payload */ - goto scan_next; - -discard: - /* Discard data until a new frame starts. */ - gspca_dev->last_packet_type = DISCARD_PACKET; - -scan_next: - remaining_len -= len; - data += len; - } while (remaining_len > 0); -} - -/* get stream parameters (framerate) */ -static void sd_get_streamparm(struct gspca_dev *gspca_dev, - struct v4l2_streamparm *parm) -{ - struct v4l2_captureparm *cp = &parm->parm.capture; - struct v4l2_fract *tpf = &cp->timeperframe; - struct sd *sd = (struct sd *) gspca_dev; - - cp->capability |= V4L2_CAP_TIMEPERFRAME; - tpf->numerator = 1; - tpf->denominator = sd->frame_rate; -} - -/* set stream parameters (framerate) */ -static void sd_set_streamparm(struct gspca_dev *gspca_dev, - struct v4l2_streamparm *parm) -{ - struct v4l2_captureparm *cp = &parm->parm.capture; - struct v4l2_fract *tpf = &cp->timeperframe; - struct sd *sd = (struct sd *) gspca_dev; - - /* Set requested framerate */ - sd->frame_rate = tpf->denominator / tpf->numerator; - if (gspca_dev->streaming) - set_frame_rate(gspca_dev); - - /* Return the actual framerate */ - tpf->numerator = 1; - tpf->denominator = sd->frame_rate; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, - .get_streamparm = sd_get_streamparm, - .set_streamparm = sd_set_streamparm, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x1415, 0x2000)}, - {USB_DEVICE(0x06f8, 0x3002)}, - {} -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c deleted file mode 100644 index c4cd028fe0b4..000000000000 --- a/drivers/media/video/gspca/ov534_9.c +++ /dev/null @@ -1,1500 +0,0 @@ -/* - * ov534-ov9xxx gspca driver - * - * Copyright (C) 2009-2011 Jean-Francois Moine http://moinejf.free.fr - * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it> - * Copyright (C) 2008 Jim Paris <jim@jtan.com> - * - * Based on a prototype written by Mark Ferrell <majortrips@gmail.com> - * USB protocol reverse engineered by Jim Paris <jim@jtan.com> - * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/ - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "ov534_9" - -#include "gspca.h" - -#define OV534_REG_ADDRESS 0xf1 /* sensor address */ -#define OV534_REG_SUBADDR 0xf2 -#define OV534_REG_WRITE 0xf3 -#define OV534_REG_READ 0xf4 -#define OV534_REG_OPERATION 0xf5 -#define OV534_REG_STATUS 0xf6 - -#define OV534_OP_WRITE_3 0x37 -#define OV534_OP_WRITE_2 0x33 -#define OV534_OP_READ_2 0xf9 - -#define CTRL_TIMEOUT 500 - -MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>"); -MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - __u32 last_pts; - u8 last_fid; - - u8 sensor; -}; -enum sensors { - SENSOR_OV965x, /* ov9657 */ - SENSOR_OV971x, /* ov9712 */ - SENSOR_OV562x, /* ov5621 */ - NSENSORS -}; - -static const struct v4l2_pix_format ov965x_mode[] = { -#define QVGA_MODE 0 - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG}, -#define VGA_MODE 1 - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG}, -#define SVGA_MODE 2 - {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 800, - .sizeimage = 800 * 600 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG}, -#define XGA_MODE 3 - {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 1024, - .sizeimage = 1024 * 768 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG}, -#define SXGA_MODE 4 - {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 1280, - .sizeimage = 1280 * 1024 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG}, -}; - -static const struct v4l2_pix_format ov971x_mode[] = { - {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB - } -}; - -static const struct v4l2_pix_format ov562x_mode[] = { - {2592, 1680, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 2592, - .sizeimage = 2592 * 1680, - .colorspace = V4L2_COLORSPACE_SRGB - } -}; - -static const u8 bridge_init[][2] = { - {0x88, 0xf8}, - {0x89, 0xff}, - {0x76, 0x03}, - {0x92, 0x03}, - {0x95, 0x10}, - {0xe2, 0x00}, - {0xe7, 0x3e}, - {0x8d, 0x1c}, - {0x8e, 0x00}, - {0x8f, 0x00}, - {0x1f, 0x00}, - {0xc3, 0xf9}, - {0x89, 0xff}, - {0x88, 0xf8}, - {0x76, 0x03}, - {0x92, 0x01}, - {0x93, 0x18}, - {0x1c, 0x0a}, - {0x1d, 0x48}, - {0xc0, 0x50}, - {0xc1, 0x3c}, - {0x34, 0x05}, - {0xc2, 0x0c}, - {0xc3, 0xf9}, - {0x34, 0x05}, - {0xe7, 0x2e}, - {0x31, 0xf9}, - {0x35, 0x02}, - {0xd9, 0x10}, - {0x25, 0x42}, - {0x94, 0x11}, -}; - -static const u8 ov965x_init[][2] = { - {0x12, 0x80}, /* com7 - SSCB reset */ - {0x00, 0x00}, /* gain */ - {0x01, 0x80}, /* blue */ - {0x02, 0x80}, /* red */ - {0x03, 0x1b}, /* vref */ - {0x04, 0x03}, /* com1 - exposure low bits */ - {0x0b, 0x57}, /* ver */ - {0x0e, 0x61}, /* com5 */ - {0x0f, 0x42}, /* com6 */ - {0x11, 0x00}, /* clkrc */ - {0x12, 0x02}, /* com7 - 15fps VGA YUYV */ - {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ - {0x14, 0x28}, /* com9 */ - {0x16, 0x24}, /* reg16 */ - {0x17, 0x1d}, /* hstart*/ - {0x18, 0xbd}, /* hstop */ - {0x19, 0x01}, /* vstrt */ - {0x1a, 0x81}, /* vstop*/ - {0x1e, 0x04}, /* mvfp */ - {0x24, 0x3c}, /* aew */ - {0x25, 0x36}, /* aeb */ - {0x26, 0x71}, /* vpt */ - {0x27, 0x08}, /* bbias */ - {0x28, 0x08}, /* gbbias */ - {0x29, 0x15}, /* gr com */ - {0x2a, 0x00}, /* exhch */ - {0x2b, 0x00}, /* exhcl */ - {0x2c, 0x08}, /* rbias */ - {0x32, 0xff}, /* href */ - {0x33, 0x00}, /* chlf */ - {0x34, 0x3f}, /* aref1 */ - {0x35, 0x00}, /* aref2 */ - {0x36, 0xf8}, /* aref3 */ - {0x38, 0x72}, /* adc2 */ - {0x39, 0x57}, /* aref4 */ - {0x3a, 0x80}, /* tslb - yuyv */ - {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ - {0x3d, 0x99}, /* com13 */ - {0x3f, 0xc1}, /* edge */ - {0x40, 0xc0}, /* com15 */ - {0x41, 0x40}, /* com16 */ - {0x42, 0xc0}, /* com17 */ - {0x43, 0x0a}, /* rsvd */ - {0x44, 0xf0}, - {0x45, 0x46}, - {0x46, 0x62}, - {0x47, 0x2a}, - {0x48, 0x3c}, - {0x4a, 0xfc}, - {0x4b, 0xfc}, - {0x4c, 0x7f}, - {0x4d, 0x7f}, - {0x4e, 0x7f}, - {0x4f, 0x98}, /* matrix */ - {0x50, 0x98}, - {0x51, 0x00}, - {0x52, 0x28}, - {0x53, 0x70}, - {0x54, 0x98}, - {0x58, 0x1a}, /* matrix coef sign */ - {0x59, 0x85}, /* AWB control */ - {0x5a, 0xa9}, - {0x5b, 0x64}, - {0x5c, 0x84}, - {0x5d, 0x53}, - {0x5e, 0x0e}, - {0x5f, 0xf0}, /* AWB blue limit */ - {0x60, 0xf0}, /* AWB red limit */ - {0x61, 0xf0}, /* AWB green limit */ - {0x62, 0x00}, /* lcc1 */ - {0x63, 0x00}, /* lcc2 */ - {0x64, 0x02}, /* lcc3 */ - {0x65, 0x16}, /* lcc4 */ - {0x66, 0x01}, /* lcc5 */ - {0x69, 0x02}, /* hv */ - {0x6b, 0x5a}, /* dbvl */ - {0x6c, 0x04}, - {0x6d, 0x55}, - {0x6e, 0x00}, - {0x6f, 0x9d}, - {0x70, 0x21}, /* dnsth */ - {0x71, 0x78}, - {0x72, 0x00}, /* poidx */ - {0x73, 0x01}, /* pckdv */ - {0x74, 0x3a}, /* xindx */ - {0x75, 0x35}, /* yindx */ - {0x76, 0x01}, - {0x77, 0x02}, - {0x7a, 0x12}, /* gamma curve */ - {0x7b, 0x08}, - {0x7c, 0x16}, - {0x7d, 0x30}, - {0x7e, 0x5e}, - {0x7f, 0x72}, - {0x80, 0x82}, - {0x81, 0x8e}, - {0x82, 0x9a}, - {0x83, 0xa4}, - {0x84, 0xac}, - {0x85, 0xb8}, - {0x86, 0xc3}, - {0x87, 0xd6}, - {0x88, 0xe6}, - {0x89, 0xf2}, - {0x8a, 0x03}, - {0x8c, 0x89}, /* com19 */ - {0x14, 0x28}, /* com9 */ - {0x90, 0x7d}, - {0x91, 0x7b}, - {0x9d, 0x03}, /* lcc6 */ - {0x9e, 0x04}, /* lcc7 */ - {0x9f, 0x7a}, - {0xa0, 0x79}, - {0xa1, 0x40}, /* aechm */ - {0xa4, 0x50}, /* com21 */ - {0xa5, 0x68}, /* com26 */ - {0xa6, 0x4a}, /* AWB green */ - {0xa8, 0xc1}, /* refa8 */ - {0xa9, 0xef}, /* refa9 */ - {0xaa, 0x92}, - {0xab, 0x04}, - {0xac, 0x80}, /* black level control */ - {0xad, 0x80}, - {0xae, 0x80}, - {0xaf, 0x80}, - {0xb2, 0xf2}, - {0xb3, 0x20}, - {0xb4, 0x20}, /* ctrlb4 */ - {0xb5, 0x00}, - {0xb6, 0xaf}, - {0xbb, 0xae}, - {0xbc, 0x7f}, /* ADC channel offsets */ - {0xdb, 0x7f}, - {0xbe, 0x7f}, - {0xbf, 0x7f}, - {0xc0, 0xe2}, - {0xc1, 0xc0}, - {0xc2, 0x01}, - {0xc3, 0x4e}, - {0xc6, 0x85}, - {0xc7, 0x80}, /* com24 */ - {0xc9, 0xe0}, - {0xca, 0xe8}, - {0xcb, 0xf0}, - {0xcc, 0xd8}, - {0xcd, 0xf1}, - {0x4f, 0x98}, /* matrix */ - {0x50, 0x98}, - {0x51, 0x00}, - {0x52, 0x28}, - {0x53, 0x70}, - {0x54, 0x98}, - {0x58, 0x1a}, - {0xff, 0x41}, /* read 41, write ff 00 */ - {0x41, 0x40}, /* com16 */ - - {0xc5, 0x03}, /* 60 Hz banding filter */ - {0x6a, 0x02}, /* 50 Hz banding filter */ - - {0x12, 0x62}, /* com7 - 30fps VGA YUV */ - {0x36, 0xfa}, /* aref3 */ - {0x69, 0x0a}, /* hv */ - {0x8c, 0x89}, /* com22 */ - {0x14, 0x28}, /* com9 */ - {0x3e, 0x0c}, - {0x41, 0x40}, /* com16 */ - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x3a}, - {0x75, 0x35}, - {0x76, 0x01}, - {0xc7, 0x80}, - {0x03, 0x12}, /* vref */ - {0x17, 0x16}, /* hstart */ - {0x18, 0x02}, /* hstop */ - {0x19, 0x01}, /* vstrt */ - {0x1a, 0x3d}, /* vstop */ - {0x32, 0xff}, /* href */ - {0xc0, 0xaa}, -}; - -static const u8 bridge_init_2[][2] = { - {0x94, 0xaa}, - {0xf1, 0x60}, - {0xe5, 0x04}, - {0xc0, 0x50}, - {0xc1, 0x3c}, - {0x8c, 0x00}, - {0x8d, 0x1c}, - {0x34, 0x05}, - - {0xc2, 0x0c}, - {0xc3, 0xf9}, - {0xda, 0x01}, - {0x50, 0x00}, - {0x51, 0xa0}, - {0x52, 0x3c}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x57, 0x00}, - {0x5c, 0x00}, - {0x5a, 0xa0}, - {0x5b, 0x78}, - {0x35, 0x02}, - {0xd9, 0x10}, - {0x94, 0x11}, -}; - -static const u8 ov965x_init_2[][2] = { - {0x3b, 0xc4}, - {0x1e, 0x04}, /* mvfp */ - {0x13, 0xe0}, /* com8 */ - {0x00, 0x00}, /* gain */ - {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ - {0x11, 0x03}, /* clkrc */ - {0x6b, 0x5a}, /* dblv */ - {0x6a, 0x05}, - {0xc5, 0x07}, - {0xa2, 0x4b}, - {0xa3, 0x3e}, - {0x2d, 0x00}, - {0xff, 0x42}, /* read 42, write ff 00 */ - {0x42, 0xc0}, /* com17 */ - {0x2d, 0x00}, - {0xff, 0x42}, /* read 42, write ff 00 */ - {0x42, 0xc1}, /* com17 */ -/* sharpness */ - {0x3f, 0x01}, - {0xff, 0x42}, /* read 42, write ff 00 */ - {0x42, 0xc1}, /* com17 */ -/* saturation */ - {0x4f, 0x98}, /* matrix */ - {0x50, 0x98}, - {0x51, 0x00}, - {0x52, 0x28}, - {0x53, 0x70}, - {0x54, 0x98}, - {0x58, 0x1a}, - {0xff, 0x41}, /* read 41, write ff 00 */ - {0x41, 0x40}, /* com16 */ -/* contrast */ - {0x56, 0x40}, -/* brightness */ - {0x55, 0x8f}, -/* expo */ - {0x10, 0x25}, /* aech - exposure high bits */ - {0xff, 0x13}, /* read 13, write ff 00 */ - {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ -}; - -static const u8 ov971x_init[][2] = { - {0x12, 0x80}, - {0x09, 0x10}, - {0x1e, 0x07}, - {0x5f, 0x18}, - {0x69, 0x04}, - {0x65, 0x2a}, - {0x68, 0x0a}, - {0x39, 0x28}, - {0x4d, 0x90}, - {0xc1, 0x80}, - {0x0c, 0x30}, - {0x6d, 0x02}, - {0x96, 0xf1}, - {0xbc, 0x68}, - {0x12, 0x00}, - {0x3b, 0x00}, - {0x97, 0x80}, - {0x17, 0x25}, - {0x18, 0xa2}, - {0x19, 0x01}, - {0x1a, 0xca}, - {0x03, 0x0a}, - {0x32, 0x07}, - {0x98, 0x40}, /*{0x98, 0x00},*/ - {0x99, 0xA0}, /*{0x99, 0x00},*/ - {0x9a, 0x01}, /*{0x9a, 0x00},*/ - {0x57, 0x00}, - {0x58, 0x78}, /*{0x58, 0xc8},*/ - {0x59, 0x50}, /*{0x59, 0xa0},*/ - {0x4c, 0x13}, - {0x4b, 0x36}, - {0x3d, 0x3c}, - {0x3e, 0x03}, - {0xbd, 0x50}, /*{0xbd, 0xa0},*/ - {0xbe, 0x78}, /*{0xbe, 0xc8},*/ - {0x4e, 0x55}, - {0x4f, 0x55}, - {0x50, 0x55}, - {0x51, 0x55}, - {0x24, 0x55}, - {0x25, 0x40}, - {0x26, 0xa1}, - {0x5c, 0x59}, - {0x5d, 0x00}, - {0x11, 0x00}, - {0x2a, 0x98}, - {0x2b, 0x06}, - {0x2d, 0x00}, - {0x2e, 0x00}, - {0x13, 0xa5}, - {0x14, 0x40}, - {0x4a, 0x00}, - {0x49, 0xce}, - {0x22, 0x03}, - {0x09, 0x00} -}; - -static const u8 ov965x_start_1_vga[][2] = { /* same for qvga */ - {0x12, 0x62}, /* com7 - 30fps VGA YUV */ - {0x36, 0xfa}, /* aref3 */ - {0x69, 0x0a}, /* hv */ - {0x8c, 0x89}, /* com22 */ - {0x14, 0x28}, /* com9 */ - {0x3e, 0x0c}, /* com14 */ - {0x41, 0x40}, /* com16 */ - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x3a}, - {0x75, 0x35}, - {0x76, 0x01}, - {0xc7, 0x80}, /* com24 */ - {0x03, 0x12}, /* vref */ - {0x17, 0x16}, /* hstart */ - {0x18, 0x02}, /* hstop */ - {0x19, 0x01}, /* vstrt */ - {0x1a, 0x3d}, /* vstop */ - {0x32, 0xff}, /* href */ - {0xc0, 0xaa}, -}; - -static const u8 ov965x_start_1_svga[][2] = { - {0x12, 0x02}, /* com7 - YUYV - VGA 15 full resolution */ - {0x36, 0xf8}, /* aref3 */ - {0x69, 0x02}, /* hv */ - {0x8c, 0x0d}, /* com22 */ - {0x3e, 0x0c}, /* com14 */ - {0x41, 0x40}, /* com16 */ - {0x72, 0x00}, - {0x73, 0x01}, - {0x74, 0x3a}, - {0x75, 0x35}, - {0x76, 0x01}, - {0xc7, 0x80}, /* com24 */ - {0x03, 0x1b}, /* vref */ - {0x17, 0x1d}, /* hstart */ - {0x18, 0xbd}, /* hstop */ - {0x19, 0x01}, /* vstrt */ - {0x1a, 0x81}, /* vstop */ - {0x32, 0xff}, /* href */ - {0xc0, 0xe2}, -}; - -static const u8 ov965x_start_1_xga[][2] = { - {0x12, 0x02}, /* com7 */ - {0x36, 0xf8}, /* aref3 */ - {0x69, 0x02}, /* hv */ - {0x8c, 0x89}, /* com22 */ - {0x14, 0x28}, /* com9 */ - {0x3e, 0x0c}, /* com14 */ - {0x41, 0x40}, /* com16 */ - {0x72, 0x00}, - {0x73, 0x01}, - {0x74, 0x3a}, - {0x75, 0x35}, - {0x76, 0x01}, - {0xc7, 0x80}, /* com24 */ - {0x03, 0x1b}, /* vref */ - {0x17, 0x1d}, /* hstart */ - {0x18, 0xbd}, /* hstop */ - {0x19, 0x01}, /* vstrt */ - {0x1a, 0x81}, /* vstop */ - {0x32, 0xff}, /* href */ - {0xc0, 0xe2}, -}; - -static const u8 ov965x_start_1_sxga[][2] = { - {0x12, 0x02}, /* com7 */ - {0x36, 0xf8}, /* aref3 */ - {0x69, 0x02}, /* hv */ - {0x8c, 0x89}, /* com22 */ - {0x14, 0x28}, /* com9 */ - {0x3e, 0x0c}, /* com14 */ - {0x41, 0x40}, /* com16 */ - {0x72, 0x00}, - {0x73, 0x01}, - {0x74, 0x3a}, - {0x75, 0x35}, - {0x76, 0x01}, - {0xc7, 0x80}, /* com24 */ - {0x03, 0x1b}, /* vref */ - {0x17, 0x1d}, /* hstart */ - {0x18, 0x02}, /* hstop */ - {0x19, 0x01}, /* vstrt */ - {0x1a, 0x81}, /* vstop */ - {0x32, 0xff}, /* href */ - {0xc0, 0xe2}, -}; - -static const u8 bridge_start_qvga[][2] = { - {0x94, 0xaa}, - {0xf1, 0x60}, - {0xe5, 0x04}, - {0xc0, 0x50}, - {0xc1, 0x3c}, - {0x8c, 0x00}, - {0x8d, 0x1c}, - {0x34, 0x05}, - - {0xc2, 0x4c}, - {0xc3, 0xf9}, - {0xda, 0x00}, - {0x50, 0x00}, - {0x51, 0xa0}, - {0x52, 0x78}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x57, 0x00}, - {0x5c, 0x00}, - {0x5a, 0x50}, - {0x5b, 0x3c}, - {0x35, 0x02}, - {0xd9, 0x10}, - {0x94, 0x11}, -}; - -static const u8 bridge_start_vga[][2] = { - {0x94, 0xaa}, - {0xf1, 0x60}, - {0xe5, 0x04}, - {0xc0, 0x50}, - {0xc1, 0x3c}, - {0x8c, 0x00}, - {0x8d, 0x1c}, - {0x34, 0x05}, - {0xc2, 0x0c}, - {0xc3, 0xf9}, - {0xda, 0x01}, - {0x50, 0x00}, - {0x51, 0xa0}, - {0x52, 0x3c}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x57, 0x00}, - {0x5c, 0x00}, - {0x5a, 0xa0}, - {0x5b, 0x78}, - {0x35, 0x02}, - {0xd9, 0x10}, - {0x94, 0x11}, -}; - -static const u8 bridge_start_svga[][2] = { - {0x94, 0xaa}, - {0xf1, 0x60}, - {0xe5, 0x04}, - {0xc0, 0xa0}, - {0xc1, 0x80}, - {0x8c, 0x00}, - {0x8d, 0x1c}, - {0x34, 0x05}, - {0xc2, 0x4c}, - {0xc3, 0xf9}, - {0x50, 0x00}, - {0x51, 0x40}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x88}, - {0x57, 0x00}, - {0x5c, 0x00}, - {0x5a, 0xc8}, - {0x5b, 0x96}, - {0x35, 0x02}, - {0xd9, 0x10}, - {0xda, 0x00}, - {0x94, 0x11}, -}; - -static const u8 bridge_start_xga[][2] = { - {0x94, 0xaa}, - {0xf1, 0x60}, - {0xe5, 0x04}, - {0xc0, 0xa0}, - {0xc1, 0x80}, - {0x8c, 0x00}, - {0x8d, 0x1c}, - {0x34, 0x05}, - {0xc2, 0x4c}, - {0xc3, 0xf9}, - {0x50, 0x00}, - {0x51, 0x40}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x88}, - {0x57, 0x00}, - {0x5c, 0x01}, - {0x5a, 0x00}, - {0x5b, 0xc0}, - {0x35, 0x02}, - {0xd9, 0x10}, - {0xda, 0x01}, - {0x94, 0x11}, -}; - -static const u8 bridge_start_sxga[][2] = { - {0x94, 0xaa}, - {0xf1, 0x60}, - {0xe5, 0x04}, - {0xc0, 0xa0}, - {0xc1, 0x80}, - {0x8c, 0x00}, - {0x8d, 0x1c}, - {0x34, 0x05}, - {0xc2, 0x0c}, - {0xc3, 0xf9}, - {0xda, 0x00}, - {0x35, 0x02}, - {0xd9, 0x10}, - {0x94, 0x11}, -}; - -static const u8 ov965x_start_2_qvga[][2] = { - {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */ - {0x1e, 0x04}, /* mvfp */ - {0x13, 0xe0}, /* com8 */ - {0x00, 0x00}, - {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ - {0x11, 0x01}, /* clkrc */ - {0x6b, 0x5a}, /* dblv */ - {0x6a, 0x02}, /* 50 Hz banding filter */ - {0xc5, 0x03}, /* 60 Hz banding filter */ - {0xa2, 0x96}, /* bd50 */ - {0xa3, 0x7d}, /* bd60 */ - - {0xff, 0x13}, /* read 13, write ff 00 */ - {0x13, 0xe7}, - {0x3a, 0x80}, /* tslb - yuyv */ -}; - -static const u8 ov965x_start_2_vga[][2] = { - {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ - {0x1e, 0x04}, /* mvfp */ - {0x13, 0xe0}, /* com8 */ - {0x00, 0x00}, - {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ - {0x11, 0x03}, /* clkrc */ - {0x6b, 0x5a}, /* dblv */ - {0x6a, 0x05}, /* 50 Hz banding filter */ - {0xc5, 0x07}, /* 60 Hz banding filter */ - {0xa2, 0x4b}, /* bd50 */ - {0xa3, 0x3e}, /* bd60 */ - - {0x2d, 0x00}, /* advfl */ -}; - -static const u8 ov965x_start_2_svga[][2] = { /* same for xga */ - {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ - {0x1e, 0x04}, /* mvfp */ - {0x13, 0xe0}, /* com8 */ - {0x00, 0x00}, - {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ - {0x11, 0x01}, /* clkrc */ - {0x6b, 0x5a}, /* dblv */ - {0x6a, 0x0c}, /* 50 Hz banding filter */ - {0xc5, 0x0f}, /* 60 Hz banding filter */ - {0xa2, 0x4e}, /* bd50 */ - {0xa3, 0x41}, /* bd60 */ -}; - -static const u8 ov965x_start_2_sxga[][2] = { - {0x13, 0xe0}, /* com8 */ - {0x00, 0x00}, - {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ - {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ - {0x1e, 0x04}, /* mvfp */ - {0x11, 0x01}, /* clkrc */ - {0x6b, 0x5a}, /* dblv */ - {0x6a, 0x0c}, /* 50 Hz banding filter */ - {0xc5, 0x0f}, /* 60 Hz banding filter */ - {0xa2, 0x4e}, /* bd50 */ - {0xa3, 0x41}, /* bd60 */ -}; - -static const u8 ov562x_init[][2] = { - {0x88, 0x20}, - {0x89, 0x0a}, - {0x8a, 0x90}, - {0x8b, 0x06}, - {0x8c, 0x01}, - {0x8d, 0x10}, - {0x1c, 0x00}, - {0x1d, 0x48}, - {0x1d, 0x00}, - {0x1d, 0xff}, - {0x1c, 0x0a}, - {0x1d, 0x2e}, - {0x1d, 0x1e}, -}; - -static const u8 ov562x_init_2[][2] = { - {0x12, 0x80}, - {0x11, 0x41}, - {0x13, 0x00}, - {0x10, 0x1e}, - {0x3b, 0x07}, - {0x5b, 0x40}, - {0x39, 0x07}, - {0x53, 0x02}, - {0x54, 0x60}, - {0x04, 0x20}, - {0x27, 0x04}, - {0x3d, 0x40}, - {0x36, 0x00}, - {0xc5, 0x04}, - {0x4e, 0x00}, - {0x4f, 0x93}, - {0x50, 0x7b}, - {0xca, 0x0c}, - {0xcb, 0x0f}, - {0x39, 0x07}, - {0x4a, 0x10}, - {0x3e, 0x0a}, - {0x3d, 0x00}, - {0x0c, 0x38}, - {0x38, 0x90}, - {0x46, 0x30}, - {0x4f, 0x93}, - {0x50, 0x7b}, - {0xab, 0x00}, - {0xca, 0x0c}, - {0xcb, 0x0f}, - {0x37, 0x02}, - {0x44, 0x48}, - {0x8d, 0x44}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x32, 0x00}, - {0x38, 0x90}, - {0x53, 0x02}, - {0x54, 0x60}, - {0x12, 0x00}, - {0x17, 0x12}, - {0x18, 0xb4}, - {0x19, 0x0c}, - {0x1a, 0xf4}, - {0x03, 0x4a}, - {0x89, 0x20}, - {0x83, 0x80}, - {0xb7, 0x9d}, - {0xb6, 0x11}, - {0xb5, 0x55}, - {0xb4, 0x00}, - {0xa9, 0xf0}, - {0xa8, 0x0a}, - {0xb8, 0xf0}, - {0xb9, 0xf0}, - {0xba, 0xf0}, - {0x81, 0x07}, - {0x63, 0x44}, - {0x13, 0xc7}, - {0x14, 0x60}, - {0x33, 0x75}, - {0x2c, 0x00}, - {0x09, 0x00}, - {0x35, 0x30}, - {0x27, 0x04}, - {0x3c, 0x07}, - {0x3a, 0x0a}, - {0x3b, 0x07}, - {0x01, 0x40}, - {0x02, 0x40}, - {0x16, 0x40}, - {0x52, 0xb0}, - {0x51, 0x83}, - {0x21, 0xbb}, - {0x22, 0x10}, - {0x23, 0x03}, - {0x35, 0x38}, - {0x20, 0x90}, - {0x28, 0x30}, - {0x73, 0xe1}, - {0x6c, 0x00}, - {0x6d, 0x80}, - {0x6e, 0x00}, - {0x70, 0x04}, - {0x71, 0x00}, - {0x8d, 0x04}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x71, 0x94}, - {0x74, 0x20}, - {0x80, 0x09}, - {0x85, 0xc0}, -}; - -static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val) -{ - struct usb_device *udev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return; - gspca_dev->usb_buf[0] = val; - ret = usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), - 0x01, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); - if (ret < 0) { - pr_err("reg_w failed %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -static void reg_w(struct gspca_dev *gspca_dev, u16 reg, u8 val) -{ - PDEBUG(D_USBO, "reg_w [%04x] = %02x", reg, val); - reg_w_i(gspca_dev, reg, val); -} - -static u8 reg_r(struct gspca_dev *gspca_dev, u16 reg) -{ - struct usb_device *udev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return 0; - ret = usb_control_msg(udev, - usb_rcvctrlpipe(udev, 0), - 0x01, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); - PDEBUG(D_USBI, "reg_r [%04x] -> %02x", reg, gspca_dev->usb_buf[0]); - if (ret < 0) { - pr_err("reg_r err %d\n", ret); - gspca_dev->usb_err = ret; - } - return gspca_dev->usb_buf[0]; -} - -static int sccb_check_status(struct gspca_dev *gspca_dev) -{ - u8 data; - int i; - - for (i = 0; i < 5; i++) { - msleep(10); - data = reg_r(gspca_dev, OV534_REG_STATUS); - - switch (data) { - case 0x00: - return 1; - case 0x04: - return 0; - case 0x03: - break; - default: - PDEBUG(D_USBI|D_USBO, - "sccb status 0x%02x, attempt %d/5", - data, i + 1); - } - } - return 0; -} - -static void sccb_write(struct gspca_dev *gspca_dev, u8 reg, u8 val) -{ - PDEBUG(D_USBO, "sccb_write [%02x] = %02x", reg, val); - reg_w_i(gspca_dev, OV534_REG_SUBADDR, reg); - reg_w_i(gspca_dev, OV534_REG_WRITE, val); - reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3); - - if (!sccb_check_status(gspca_dev)) - pr_err("sccb_write failed\n"); -} - -static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg) -{ - reg_w(gspca_dev, OV534_REG_SUBADDR, reg); - reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2); - if (!sccb_check_status(gspca_dev)) - pr_err("sccb_read failed 1\n"); - - reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2); - if (!sccb_check_status(gspca_dev)) - pr_err("sccb_read failed 2\n"); - - return reg_r(gspca_dev, OV534_REG_READ); -} - -/* output a bridge sequence (reg - val) */ -static void reg_w_array(struct gspca_dev *gspca_dev, - const u8 (*data)[2], int len) -{ - while (--len >= 0) { - reg_w(gspca_dev, (*data)[0], (*data)[1]); - data++; - } -} - -/* output a sensor sequence (reg - val) */ -static void sccb_w_array(struct gspca_dev *gspca_dev, - const u8 (*data)[2], int len) -{ - while (--len >= 0) { - if ((*data)[0] != 0xff) { - sccb_write(gspca_dev, (*data)[0], (*data)[1]); - } else { - sccb_read(gspca_dev, (*data)[1]); - sccb_write(gspca_dev, 0xff, 0x00); - } - data++; - } -} - -/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7. - * (direction and output)? */ -static void set_led(struct gspca_dev *gspca_dev, int status) -{ - u8 data; - - PDEBUG(D_CONF, "led status: %d", status); - - data = reg_r(gspca_dev, 0x21); - data |= 0x80; - reg_w(gspca_dev, 0x21, data); - - data = reg_r(gspca_dev, 0x23); - if (status) - data |= 0x80; - else - data &= ~0x80; - - reg_w(gspca_dev, 0x23, data); - - if (!status) { - data = reg_r(gspca_dev, 0x21); - data &= ~0x80; - reg_w(gspca_dev, 0x21, data); - } -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 val; - s8 sval; - - if (sd->sensor == SENSOR_OV562x) { - sval = brightness; - val = 0x76; - val += sval; - sccb_write(gspca_dev, 0x24, val); - val = 0x6a; - val += sval; - sccb_write(gspca_dev, 0x25, val); - if (sval < -40) - val = 0x71; - else if (sval < 20) - val = 0x94; - else - val = 0xe6; - sccb_write(gspca_dev, 0x26, val); - } else { - val = brightness; - if (val < 8) - val = 15 - val; /* f .. 8 */ - else - val = val - 8; /* 0 .. 7 */ - sccb_write(gspca_dev, 0x55, /* brtn - brightness adjustment */ - 0x0f | (val << 4)); - } -} - -static void setcontrast(struct gspca_dev *gspca_dev, s32 val) -{ - sccb_write(gspca_dev, 0x56, /* cnst1 - contrast 1 ctrl coeff */ - val << 4); -} - -static void setautogain(struct gspca_dev *gspca_dev, s32 autogain) -{ - u8 val; - -/*fixme: should adjust agc/awb/aec by different controls */ - val = sccb_read(gspca_dev, 0x13); /* com8 */ - sccb_write(gspca_dev, 0xff, 0x00); - if (autogain) - val |= 0x05; /* agc & aec */ - else - val &= 0xfa; - sccb_write(gspca_dev, 0x13, val); -} - -static void setexposure(struct gspca_dev *gspca_dev, s32 exposure) -{ - static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e}; - u8 val; - - sccb_write(gspca_dev, 0x10, expo[exposure]); /* aec[9:2] */ - - val = sccb_read(gspca_dev, 0x13); /* com8 */ - sccb_write(gspca_dev, 0xff, 0x00); - sccb_write(gspca_dev, 0x13, val); - - val = sccb_read(gspca_dev, 0xa1); /* aech */ - sccb_write(gspca_dev, 0xff, 0x00); - sccb_write(gspca_dev, 0xa1, val & 0xe0); /* aec[15:10] = 0 */ -} - -static void setsharpness(struct gspca_dev *gspca_dev, s32 val) -{ - if (val < 0) { /* auto */ - val = sccb_read(gspca_dev, 0x42); /* com17 */ - sccb_write(gspca_dev, 0xff, 0x00); - sccb_write(gspca_dev, 0x42, val | 0x40); - /* Edge enhancement strength auto adjust */ - return; - } - if (val != 0) - val = 1 << (val - 1); - sccb_write(gspca_dev, 0x3f, /* edge - edge enhance. factor */ - val); - val = sccb_read(gspca_dev, 0x42); /* com17 */ - sccb_write(gspca_dev, 0xff, 0x00); - sccb_write(gspca_dev, 0x42, val & 0xbf); -} - -static void setsatur(struct gspca_dev *gspca_dev, s32 val) -{ - u8 val1, val2, val3; - static const u8 matrix[5][2] = { - {0x14, 0x38}, - {0x1e, 0x54}, - {0x28, 0x70}, - {0x32, 0x8c}, - {0x48, 0x90} - }; - - val1 = matrix[val][0]; - val2 = matrix[val][1]; - val3 = val1 + val2; - sccb_write(gspca_dev, 0x4f, val3); /* matrix coeff */ - sccb_write(gspca_dev, 0x50, val3); - sccb_write(gspca_dev, 0x51, 0x00); - sccb_write(gspca_dev, 0x52, val1); - sccb_write(gspca_dev, 0x53, val2); - sccb_write(gspca_dev, 0x54, val3); - sccb_write(gspca_dev, 0x58, 0x1a); /* mtxs - coeff signs */ - - val1 = sccb_read(gspca_dev, 0x41); /* com16 */ - sccb_write(gspca_dev, 0xff, 0x00); - sccb_write(gspca_dev, 0x41, val1); -} - -static void setlightfreq(struct gspca_dev *gspca_dev, s32 freq) -{ - u8 val; - - val = sccb_read(gspca_dev, 0x13); /* com8 */ - sccb_write(gspca_dev, 0xff, 0x00); - if (freq == 0) { - sccb_write(gspca_dev, 0x13, val & 0xdf); - return; - } - sccb_write(gspca_dev, 0x13, val | 0x20); - - val = sccb_read(gspca_dev, 0x42); /* com17 */ - sccb_write(gspca_dev, 0xff, 0x00); - if (freq == 1) - val |= 0x01; - else - val &= 0xfe; - sccb_write(gspca_dev, 0x42, val); -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u16 sensor_id; - - /* reset bridge */ - reg_w(gspca_dev, 0xe7, 0x3a); - reg_w(gspca_dev, 0xe0, 0x08); - msleep(100); - - /* initialize the sensor address */ - reg_w(gspca_dev, OV534_REG_ADDRESS, 0x60); - - /* reset sensor */ - sccb_write(gspca_dev, 0x12, 0x80); - msleep(10); - - /* probe the sensor */ - sccb_read(gspca_dev, 0x0a); - sensor_id = sccb_read(gspca_dev, 0x0a) << 8; - sccb_read(gspca_dev, 0x0b); - sensor_id |= sccb_read(gspca_dev, 0x0b); - PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id); - - /* initialize */ - if ((sensor_id & 0xfff0) == 0x9650) { - sd->sensor = SENSOR_OV965x; - - gspca_dev->cam.cam_mode = ov965x_mode; - gspca_dev->cam.nmodes = ARRAY_SIZE(ov965x_mode); - - reg_w_array(gspca_dev, bridge_init, - ARRAY_SIZE(bridge_init)); - sccb_w_array(gspca_dev, ov965x_init, - ARRAY_SIZE(ov965x_init)); - reg_w_array(gspca_dev, bridge_init_2, - ARRAY_SIZE(bridge_init_2)); - sccb_w_array(gspca_dev, ov965x_init_2, - ARRAY_SIZE(ov965x_init_2)); - reg_w(gspca_dev, 0xe0, 0x00); - reg_w(gspca_dev, 0xe0, 0x01); - set_led(gspca_dev, 0); - reg_w(gspca_dev, 0xe0, 0x00); - } else if ((sensor_id & 0xfff0) == 0x9710) { - const char *p; - int l; - - sd->sensor = SENSOR_OV971x; - - gspca_dev->cam.cam_mode = ov971x_mode; - gspca_dev->cam.nmodes = ARRAY_SIZE(ov971x_mode); - - gspca_dev->cam.bulk = 1; - gspca_dev->cam.bulk_size = 16384; - gspca_dev->cam.bulk_nurbs = 2; - - sccb_w_array(gspca_dev, ov971x_init, - ARRAY_SIZE(ov971x_init)); - - /* set video format on bridge processor */ - /* access bridge processor's video format registers at: 0x00 */ - reg_w(gspca_dev, 0x1c, 0x00); - /*set register: 0x00 is 'RAW8', 0x40 is 'YUV422' (YUYV?)*/ - reg_w(gspca_dev, 0x1d, 0x00); - - /* Will W. specific stuff - * set VSYNC to - * output (0x1f) if first webcam - * input (0x17) if 2nd or 3rd webcam */ - p = video_device_node_name(&gspca_dev->vdev); - l = strlen(p) - 1; - if (p[l] == '0') - reg_w(gspca_dev, 0x56, 0x1f); - else - reg_w(gspca_dev, 0x56, 0x17); - } else if ((sensor_id & 0xfff0) == 0x5620) { - sd->sensor = SENSOR_OV562x; - gspca_dev->cam.cam_mode = ov562x_mode; - gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode); - - reg_w_array(gspca_dev, ov562x_init, - ARRAY_SIZE(ov562x_init)); - sccb_w_array(gspca_dev, ov562x_init_2, - ARRAY_SIZE(ov562x_init_2)); - reg_w(gspca_dev, 0xe0, 0x00); - } else { - pr_err("Unknown sensor %04x", sensor_id); - return -EINVAL; - } - - return gspca_dev->usb_err; -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_OV971x) - return gspca_dev->usb_err; - if (sd->sensor == SENSOR_OV562x) - return gspca_dev->usb_err; - - switch (gspca_dev->curr_mode) { - case QVGA_MODE: /* 320x240 */ - sccb_w_array(gspca_dev, ov965x_start_1_vga, - ARRAY_SIZE(ov965x_start_1_vga)); - reg_w_array(gspca_dev, bridge_start_qvga, - ARRAY_SIZE(bridge_start_qvga)); - sccb_w_array(gspca_dev, ov965x_start_2_qvga, - ARRAY_SIZE(ov965x_start_2_qvga)); - break; - case VGA_MODE: /* 640x480 */ - sccb_w_array(gspca_dev, ov965x_start_1_vga, - ARRAY_SIZE(ov965x_start_1_vga)); - reg_w_array(gspca_dev, bridge_start_vga, - ARRAY_SIZE(bridge_start_vga)); - sccb_w_array(gspca_dev, ov965x_start_2_vga, - ARRAY_SIZE(ov965x_start_2_vga)); - break; - case SVGA_MODE: /* 800x600 */ - sccb_w_array(gspca_dev, ov965x_start_1_svga, - ARRAY_SIZE(ov965x_start_1_svga)); - reg_w_array(gspca_dev, bridge_start_svga, - ARRAY_SIZE(bridge_start_svga)); - sccb_w_array(gspca_dev, ov965x_start_2_svga, - ARRAY_SIZE(ov965x_start_2_svga)); - break; - case XGA_MODE: /* 1024x768 */ - sccb_w_array(gspca_dev, ov965x_start_1_xga, - ARRAY_SIZE(ov965x_start_1_xga)); - reg_w_array(gspca_dev, bridge_start_xga, - ARRAY_SIZE(bridge_start_xga)); - sccb_w_array(gspca_dev, ov965x_start_2_svga, - ARRAY_SIZE(ov965x_start_2_svga)); - break; - default: -/* case SXGA_MODE: * 1280x1024 */ - sccb_w_array(gspca_dev, ov965x_start_1_sxga, - ARRAY_SIZE(ov965x_start_1_sxga)); - reg_w_array(gspca_dev, bridge_start_sxga, - ARRAY_SIZE(bridge_start_sxga)); - sccb_w_array(gspca_dev, ov965x_start_2_sxga, - ARRAY_SIZE(ov965x_start_2_sxga)); - break; - } - - reg_w(gspca_dev, 0xe0, 0x00); - reg_w(gspca_dev, 0xe0, 0x00); - set_led(gspca_dev, 1); - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - reg_w(gspca_dev, 0xe0, 0x01); - set_led(gspca_dev, 0); - reg_w(gspca_dev, 0xe0, 0x00); -} - -/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ -#define UVC_STREAM_EOH (1 << 7) -#define UVC_STREAM_ERR (1 << 6) -#define UVC_STREAM_STI (1 << 5) -#define UVC_STREAM_RES (1 << 4) -#define UVC_STREAM_SCR (1 << 3) -#define UVC_STREAM_PTS (1 << 2) -#define UVC_STREAM_EOF (1 << 1) -#define UVC_STREAM_FID (1 << 0) - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - __u32 this_pts; - u8 this_fid; - int remaining_len = len; - int payload_len; - - payload_len = gspca_dev->cam.bulk ? 2048 : 2040; - do { - len = min(remaining_len, payload_len); - - /* Payloads are prefixed with a UVC-style header. We - consider a frame to start when the FID toggles, or the PTS - changes. A frame ends when EOF is set, and we've received - the correct number of bytes. */ - - /* Verify UVC header. Header length is always 12 */ - if (data[0] != 12 || len < 12) { - PDEBUG(D_PACK, "bad header"); - goto discard; - } - - /* Check errors */ - if (data[1] & UVC_STREAM_ERR) { - PDEBUG(D_PACK, "payload error"); - goto discard; - } - - /* Extract PTS and FID */ - if (!(data[1] & UVC_STREAM_PTS)) { - PDEBUG(D_PACK, "PTS not present"); - goto discard; - } - this_pts = (data[5] << 24) | (data[4] << 16) - | (data[3] << 8) | data[2]; - this_fid = data[1] & UVC_STREAM_FID; - - /* If PTS or FID has changed, start a new frame. */ - if (this_pts != sd->last_pts || this_fid != sd->last_fid) { - if (gspca_dev->last_packet_type == INTER_PACKET) - gspca_frame_add(gspca_dev, LAST_PACKET, - NULL, 0); - sd->last_pts = this_pts; - sd->last_fid = this_fid; - gspca_frame_add(gspca_dev, FIRST_PACKET, - data + 12, len - 12); - /* If this packet is marked as EOF, end the frame */ - } else if (data[1] & UVC_STREAM_EOF) { - sd->last_pts = 0; - gspca_frame_add(gspca_dev, LAST_PACKET, - data + 12, len - 12); - } else { - - /* Add the data from this payload */ - gspca_frame_add(gspca_dev, INTER_PACKET, - data + 12, len - 12); - } - - /* Done this payload */ - goto scan_next; - -discard: - /* Discard data until a new frame starts. */ - gspca_dev->last_packet_type = DISCARD_PACKET; - -scan_next: - remaining_len -= len; - data += len; - } while (remaining_len > 0); -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_CONTRAST: - setcontrast(gspca_dev, ctrl->val); - break; - case V4L2_CID_SATURATION: - setsatur(gspca_dev, ctrl->val); - break; - case V4L2_CID_POWER_LINE_FREQUENCY: - setlightfreq(gspca_dev, ctrl->val); - break; - case V4L2_CID_SHARPNESS: - setsharpness(gspca_dev, ctrl->val); - break; - case V4L2_CID_AUTOGAIN: - if (ctrl->is_new) - setautogain(gspca_dev, ctrl->val); - if (!ctrl->val && gspca_dev->exposure->is_new) - setexposure(gspca_dev, gspca_dev->exposure->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - if (sd->sensor == SENSOR_OV971x) - return 0; - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 7); - if (sd->sensor == SENSOR_OV562x) { - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, -90, 90, 1, 0); - } else { - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 15, 1, 7); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 15, 1, 3); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SATURATION, 0, 4, 1, 2); - /* -1 = auto */ - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SHARPNESS, -1, 4, 1, -1); - gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 3, 1, 0); - v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, - V4L2_CID_POWER_LINE_FREQUENCY, - V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0); - v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false); - } - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x05a9, 0x8065)}, - {USB_DEVICE(0x06f8, 0x3003)}, - {USB_DEVICE(0x05a9, 0x1550)}, - {} -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c deleted file mode 100644 index d236d1791f78..000000000000 --- a/drivers/media/video/gspca/pac207.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Pixart PAC207BCA library - * - * Copyright (C) 2008 Hans de Goede <hdegoede@redhat.com> - * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li - * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr - * - * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "pac207" - -#include <linux/input.h> -#include "gspca.h" -/* Include pac common sof detection functions */ -#include "pac_common.h" - -MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); -MODULE_DESCRIPTION("Pixart PAC207"); -MODULE_LICENSE("GPL"); - -#define PAC207_CTRL_TIMEOUT 100 /* ms */ - -#define PAC207_BRIGHTNESS_MIN 0 -#define PAC207_BRIGHTNESS_MAX 255 -#define PAC207_BRIGHTNESS_DEFAULT 46 -#define PAC207_BRIGHTNESS_REG 0x08 - -#define PAC207_EXPOSURE_MIN 3 -#define PAC207_EXPOSURE_MAX 90 /* 1 sec expo time / 1 fps */ -#define PAC207_EXPOSURE_DEFAULT 5 /* power on default: 3 */ -#define PAC207_EXPOSURE_REG 0x02 - -#define PAC207_GAIN_MIN 0 -#define PAC207_GAIN_MAX 31 -#define PAC207_GAIN_DEFAULT 7 /* power on default: 9 */ -#define PAC207_GAIN_REG 0x0e - -#define PAC207_AUTOGAIN_DEADZONE 30 - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - struct v4l2_ctrl *brightness; - - u8 mode; - u8 sof_read; - u8 header_read; - u8 autogain_ignore_frames; - - atomic_t avg_lum; -}; - -static const struct v4l2_pix_format sif_mode[] = { - {176, 144, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = (176 + 2) * 144, - /* uncompressed, add 2 bytes / line for line header */ - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {352, 288, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE, - .bytesperline = 352, - /* compressed, but only when needed (not compressed - when the framerate is low) */ - .sizeimage = (352 + 2) * 288, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; - -static const __u8 pac207_sensor_init[][8] = { - {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0x84}, - {0x49, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30}, - {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00}, - {0x32, 0x00, 0x96, 0x00, 0xa2, 0x02, 0xaf, 0x00}, -}; - -static void pac207_write_regs(struct gspca_dev *gspca_dev, u16 index, - const u8 *buffer, u16 length) -{ - struct usb_device *udev = gspca_dev->dev; - int err; - - if (gspca_dev->usb_err < 0) - return; - - memcpy(gspca_dev->usb_buf, buffer, length); - - err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x00, index, - gspca_dev->usb_buf, length, PAC207_CTRL_TIMEOUT); - if (err < 0) { - pr_err("Failed to write registers to index 0x%04X, error %d\n", - index, err); - gspca_dev->usb_err = err; - } -} - -static void pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value) -{ - struct usb_device *udev = gspca_dev->dev; - int err; - - if (gspca_dev->usb_err < 0) - return; - - err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - value, index, NULL, 0, PAC207_CTRL_TIMEOUT); - if (err) { - pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n", - index, value, err); - gspca_dev->usb_err = err; - } -} - -static int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index) -{ - struct usb_device *udev = gspca_dev->dev; - int res; - - if (gspca_dev->usb_err < 0) - return 0; - - res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x00, index, - gspca_dev->usb_buf, 1, PAC207_CTRL_TIMEOUT); - if (res < 0) { - pr_err("Failed to read a register (index 0x%04X, error %d)\n", - index, res); - gspca_dev->usb_err = res; - return 0; - } - - return gspca_dev->usb_buf[0]; -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct cam *cam; - u8 idreg[2]; - - idreg[0] = pac207_read_reg(gspca_dev, 0x0000); - idreg[1] = pac207_read_reg(gspca_dev, 0x0001); - idreg[0] = ((idreg[0] & 0x0f) << 4) | ((idreg[1] & 0xf0) >> 4); - idreg[1] = idreg[1] & 0x0f; - PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X", - idreg[0], idreg[1]); - - if (idreg[0] != 0x27) { - PDEBUG(D_PROBE, "Error invalid sensor ID!"); - return -ENODEV; - } - - PDEBUG(D_PROBE, - "Pixart PAC207BCA Image Processor and Control Chip detected" - " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); - - cam = &gspca_dev->cam; - cam->cam_mode = sif_mode; - cam->nmodes = ARRAY_SIZE(sif_mode); - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - pac207_write_reg(gspca_dev, 0x41, 0x00); - /* Bit_0=Image Format, - * Bit_1=LED, - * Bit_2=Compression test mode enable */ - pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */ - - return gspca_dev->usb_err; -} - -static void setcontrol(struct gspca_dev *gspca_dev, u16 reg, u16 val) -{ - pac207_write_reg(gspca_dev, reg, val); - pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */ - pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */ -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) { - /* when switching to autogain set defaults to make sure - we are on a valid point of the autogain gain / - exposure knee graph, and give this change time to - take effect before doing autogain. */ - gspca_dev->exposure->val = PAC207_EXPOSURE_DEFAULT; - gspca_dev->gain->val = PAC207_GAIN_DEFAULT; - sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; - } - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setcontrol(gspca_dev, PAC207_BRIGHTNESS_REG, ctrl->val); - break; - case V4L2_CID_AUTOGAIN: - if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val)) - setcontrol(gspca_dev, PAC207_EXPOSURE_REG, - gspca_dev->exposure->val); - if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val)) - setcontrol(gspca_dev, PAC207_GAIN_REG, - gspca_dev->gain->val); - break; - default: - return -EINVAL; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -/* this function is called at probe time */ -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 4); - - sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, - PAC207_BRIGHTNESS_MIN, PAC207_BRIGHTNESS_MAX, - 1, PAC207_BRIGHTNESS_DEFAULT); - gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, - PAC207_EXPOSURE_MIN, PAC207_EXPOSURE_MAX, - 1, PAC207_EXPOSURE_DEFAULT); - gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, - PAC207_GAIN_MIN, PAC207_GAIN_MAX, - 1, PAC207_GAIN_DEFAULT); - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false); - return 0; -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - __u8 mode; - - pac207_write_reg(gspca_dev, 0x0f, 0x10); /* Power control (Bit 6-0) */ - pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8); - pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8); - pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8); - pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[3], 8); - - /* Compression Balance */ - if (gspca_dev->width == 176) - pac207_write_reg(gspca_dev, 0x4a, 0xff); - else - pac207_write_reg(gspca_dev, 0x4a, 0x30); - pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */ - pac207_write_reg(gspca_dev, 0x08, v4l2_ctrl_g_ctrl(sd->brightness)); - - /* PGA global gain (Bit 4-0) */ - pac207_write_reg(gspca_dev, 0x0e, - v4l2_ctrl_g_ctrl(gspca_dev->gain)); - pac207_write_reg(gspca_dev, 0x02, - v4l2_ctrl_g_ctrl(gspca_dev->exposure)); /* PXCK = 12MHz /n */ - - mode = 0x02; /* Image Format (Bit 0), LED (1), Compr. test mode (2) */ - if (gspca_dev->width == 176) { /* 176x144 */ - mode |= 0x01; - PDEBUG(D_STREAM, "pac207_start mode 176x144"); - } else { /* 352x288 */ - PDEBUG(D_STREAM, "pac207_start mode 352x288"); - } - pac207_write_reg(gspca_dev, 0x41, mode); - - pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */ - pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */ - msleep(10); - pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */ - - sd->sof_read = 0; - sd->autogain_ignore_frames = 0; - atomic_set(&sd->avg_lum, -1); - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */ - pac207_write_reg(gspca_dev, 0x41, 0x00); /* Turn of LED */ - pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */ -} - - -static void pac207_do_auto_gain(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int avg_lum = atomic_read(&sd->avg_lum); - - if (avg_lum == -1) - return; - - if (sd->autogain_ignore_frames > 0) - sd->autogain_ignore_frames--; - else if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum, - 90, PAC207_AUTOGAIN_DEADZONE)) - sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, - int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - unsigned char *sof; - - sof = pac_find_sof(&sd->sof_read, data, len); - if (sof) { - int n; - - /* finish decoding current frame */ - n = sof - data; - if (n > sizeof pac_sof_marker) - n -= sizeof pac_sof_marker; - else - n = 0; - gspca_frame_add(gspca_dev, LAST_PACKET, - data, n); - sd->header_read = 0; - gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); - len -= sof - data; - data = sof; - } - if (sd->header_read < 11) { - int needed; - - /* get average lumination from frame header (byte 5) */ - if (sd->header_read < 5) { - needed = 5 - sd->header_read; - if (len >= needed) - atomic_set(&sd->avg_lum, data[needed - 1]); - } - /* skip the rest of the header */ - needed = 11 - sd->header_read; - if (len <= needed) { - sd->header_read += len; - return; - } - data += needed; - len -= needed; - sd->header_read = 11; - } - - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) -static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* interrupt packet data */ - int len) /* interrput packet length */ -{ - int ret = -EINVAL; - - if (len == 2 && data[0] == 0x5a && data[1] == 0x5a) { - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); - input_sync(gspca_dev->input_dev); - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); - input_sync(gspca_dev->input_dev); - ret = 0; - } - - return ret; -} -#endif - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .dq_callback = pac207_do_auto_gain, - .pkt_scan = sd_pkt_scan, -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .int_pkt_scan = sd_int_pkt_scan, -#endif -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x041e, 0x4028)}, - {USB_DEVICE(0x093a, 0x2460)}, - {USB_DEVICE(0x093a, 0x2461)}, - {USB_DEVICE(0x093a, 0x2463)}, - {USB_DEVICE(0x093a, 0x2464)}, - {USB_DEVICE(0x093a, 0x2468)}, - {USB_DEVICE(0x093a, 0x2470)}, - {USB_DEVICE(0x093a, 0x2471)}, - {USB_DEVICE(0x093a, 0x2472)}, - {USB_DEVICE(0x093a, 0x2474)}, - {USB_DEVICE(0x093a, 0x2476)}, - {USB_DEVICE(0x145f, 0x013a)}, - {USB_DEVICE(0x2001, 0xf115)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c deleted file mode 100644 index 4877f7ab3d59..000000000000 --- a/drivers/media/video/gspca/pac7302.c +++ /dev/null @@ -1,932 +0,0 @@ -/* - * Pixart PAC7302 driver - * - * Copyright (C) 2008-2012 Jean-Francois Moine <http://moinejf.free.fr> - * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li - * - * Separated from Pixart PAC7311 library by Márton Németh - * Camera button input handling by Márton Németh <nm127@freemail.hu> - * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Some documentation about various registers as determined by trial and error. - * - * Register page 1: - * - * Address Description - * 0x78 Global control, bit 6 controls the LED (inverted) - * 0x80 Compression balance, 2 interesting settings: - * 0x0f Default - * 0x50 Values >= this switch the camera to a lower compression, - * using the same table for both luminance and chrominance. - * This gives a sharper picture. Only usable when running - * at < 15 fps! Note currently the driver does not use this - * as the quality gain is small and the generated JPG-s are - * only understood by v4l-utils >= 0.8.9 - * - * Register page 3: - * - * Address Description - * 0x02 Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on - * the 7302, so one of 3, 6, 9, ..., except when between 6 and 12? - * 0x03 Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps - * 0x04 Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps, - * 63 -> ~27 fps, the 2 msb's must always be 1 !! - * 0x05 Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0: - * 1 -> ~30 fps, 2 -> ~20 fps - * 0x0e Exposure bits 0-7, 0-448, 0 = use full frame time - * 0x0f Exposure bit 8, 0-448, 448 = no exposure at all - * 0x10 Gain 0-31 - * 0x12 Another gain 0-31, unlike 0x10 this one seems to start with an - * amplification value of 1 rather then 0 at its lowest setting - * 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused - * 0x80 Another framerate control, best left at 1, moving it from 1 to - * 2 causes the framerate to become 3/4th of what it was, and - * also seems to cause pixel averaging, resulting in an effective - * resolution of 320x240 and thus a much blockier image - * - * The registers are accessed in the following functions: - * - * Page | Register | Function - * -----+------------+--------------------------------------------------- - * 0 | 0x0f..0x20 | setcolors() - * 0 | 0xa2..0xab | setbrightcont() - * 0 | 0xc5 | setredbalance() - * 0 | 0xc6 | setwhitebalance() - * 0 | 0xc7 | setbluebalance() - * 0 | 0xdc | setbrightcont(), setcolors() - * 3 | 0x02 | setexposure() - * 3 | 0x10, 0x12 | setgain() - * 3 | 0x11 | setcolors(), setgain(), setexposure(), sethvflip() - * 3 | 0x21 | sethvflip() - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/input.h> -#include <media/v4l2-chip-ident.h> -#include "gspca.h" -/* Include pac common sof detection functions */ -#include "pac_common.h" - -#define PAC7302_GAIN_DEFAULT 15 -#define PAC7302_GAIN_KNEE 42 -#define PAC7302_EXPOSURE_DEFAULT 66 /* 33 ms / 30 fps */ -#define PAC7302_EXPOSURE_KNEE 133 /* 66 ms / 15 fps */ - -MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, " - "Thomas Kaiser thomas@kaiser-linux.li"); -MODULE_DESCRIPTION("Pixart PAC7302"); -MODULE_LICENSE("GPL"); - -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - struct { /* brightness / contrast cluster */ - struct v4l2_ctrl *brightness; - struct v4l2_ctrl *contrast; - }; - struct v4l2_ctrl *saturation; - struct v4l2_ctrl *white_balance; - struct v4l2_ctrl *red_balance; - struct v4l2_ctrl *blue_balance; - struct { /* flip cluster */ - struct v4l2_ctrl *hflip; - struct v4l2_ctrl *vflip; - }; - u8 flags; -#define FL_HFLIP 0x01 /* mirrored by default */ -#define FL_VFLIP 0x02 /* vertical flipped by default */ - - u8 sof_read; - s8 autogain_ignore_frames; - - atomic_t avg_lum; -}; - -static const struct v4l2_pix_format vga_mode[] = { - {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - }, -}; - -#define LOAD_PAGE3 255 -#define END_OF_SEQUENCE 0 - -static const u8 init_7302[] = { -/* index,value */ - 0xff, 0x01, /* page 1 */ - 0x78, 0x00, /* deactivate */ - 0xff, 0x01, - 0x78, 0x40, /* led off */ -}; -static const u8 start_7302[] = { -/* index, len, [value]* */ - 0xff, 1, 0x00, /* page 0 */ - 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, - 0x00, 0x00, 0x00, 0x00, - 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00, - 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7, - 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11, - 0x26, 2, 0xaa, 0xaa, - 0x2e, 1, 0x31, - 0x38, 1, 0x01, - 0x3a, 3, 0x14, 0xff, 0x5a, - 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11, - 0x00, 0x54, 0x11, - 0x55, 1, 0x00, - 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, - 0x6b, 1, 0x00, - 0x6e, 3, 0x08, 0x06, 0x00, - 0x72, 3, 0x00, 0xff, 0x00, - 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c, - 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50, - 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00, - 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9, - 0xd2, 0xeb, - 0xaf, 1, 0x02, - 0xb5, 2, 0x08, 0x08, - 0xb8, 2, 0x08, 0x88, - 0xc4, 4, 0xae, 0x01, 0x04, 0x01, - 0xcc, 1, 0x00, - 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9, - 0xc1, 0xd7, 0xec, - 0xdc, 1, 0x01, - 0xff, 1, 0x01, /* page 1 */ - 0x12, 3, 0x02, 0x00, 0x01, - 0x3e, 2, 0x00, 0x00, - 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2, - 0x7c, 1, 0x00, - 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20, - 0x02, 0x00, - 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04, - 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x07, 0x00, 0x01, 0x07, 0x04, 0x01, - 0xd8, 1, 0x01, - 0xdb, 2, 0x00, 0x01, - 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00, - 0xe6, 4, 0x00, 0x00, 0x00, 0x01, - 0xeb, 1, 0x00, - 0xff, 1, 0x02, /* page 2 */ - 0x22, 1, 0x00, - 0xff, 1, 0x03, /* page 3 */ - 0, LOAD_PAGE3, /* load the page 3 */ - 0x11, 1, 0x01, - 0xff, 1, 0x02, /* page 2 */ - 0x13, 1, 0x00, - 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96, - 0x27, 2, 0x14, 0x0c, - 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22, - 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44, - 0x6e, 1, 0x08, - 0xff, 1, 0x01, /* page 1 */ - 0x78, 1, 0x00, - 0, END_OF_SEQUENCE /* end of sequence */ -}; - -#define SKIP 0xaa -/* page 3 - the value SKIP says skip the index - see reg_w_page() */ -static const u8 page3_7302[] = { - 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16, - 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, - 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21, - 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54, - 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00, - 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00, - SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8, - 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00, - 0x00 -}; - -static void reg_w_buf(struct gspca_dev *gspca_dev, - u8 index, - const u8 *buffer, int len) -{ - int ret; - - if (gspca_dev->usb_err < 0) - return; - memcpy(gspca_dev->usb_buf, buffer, len); - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, /* value */ - index, gspca_dev->usb_buf, len, - 500); - if (ret < 0) { - pr_err("reg_w_buf failed i: %02x error %d\n", - index, ret); - gspca_dev->usb_err = ret; - } -} - - -static void reg_w(struct gspca_dev *gspca_dev, - u8 index, - u8 value) -{ - int ret; - - if (gspca_dev->usb_err < 0) - return; - gspca_dev->usb_buf[0] = value; - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, index, gspca_dev->usb_buf, 1, - 500); - if (ret < 0) { - pr_err("reg_w() failed i: %02x v: %02x error %d\n", - index, value, ret); - gspca_dev->usb_err = ret; - } -} - -static void reg_w_seq(struct gspca_dev *gspca_dev, - const u8 *seq, int len) -{ - while (--len >= 0) { - reg_w(gspca_dev, seq[0], seq[1]); - seq += 2; - } -} - -/* load the beginning of a page */ -static void reg_w_page(struct gspca_dev *gspca_dev, - const u8 *page, int len) -{ - int index; - int ret = 0; - - if (gspca_dev->usb_err < 0) - return; - for (index = 0; index < len; index++) { - if (page[index] == SKIP) /* skip this index */ - continue; - gspca_dev->usb_buf[0] = page[index]; - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, index, gspca_dev->usb_buf, 1, - 500); - if (ret < 0) { - pr_err("reg_w_page() failed i: %02x v: %02x error %d\n", - index, page[index], ret); - gspca_dev->usb_err = ret; - break; - } - } -} - -/* output a variable sequence */ -static void reg_w_var(struct gspca_dev *gspca_dev, - const u8 *seq, - const u8 *page3, unsigned int page3_len) -{ - int index, len; - - for (;;) { - index = *seq++; - len = *seq++; - switch (len) { - case END_OF_SEQUENCE: - return; - case LOAD_PAGE3: - reg_w_page(gspca_dev, page3, page3_len); - break; - default: -#ifdef GSPCA_DEBUG - if (len > USB_BUF_SZ) { - PDEBUG(D_ERR|D_STREAM, - "Incorrect variable sequence"); - return; - } -#endif - while (len > 0) { - if (len < 8) { - reg_w_buf(gspca_dev, - index, seq, len); - seq += len; - break; - } - reg_w_buf(gspca_dev, index, seq, 8); - seq += 8; - index += 8; - len -= 8; - } - } - } - /* not reached */ -} - -/* this function is called at probe time for pac7302 */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - - cam = &gspca_dev->cam; - - cam->cam_mode = vga_mode; /* only 640x480 */ - cam->nmodes = ARRAY_SIZE(vga_mode); - - sd->flags = id->driver_info; - return 0; -} - -static void setbrightcont(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i, v; - static const u8 max[10] = - {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, - 0xd4, 0xec}; - static const u8 delta[10] = - {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, - 0x11, 0x0b}; - - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ - for (i = 0; i < 10; i++) { - v = max[i]; - v += (sd->brightness->val - sd->brightness->maximum) - * 150 / sd->brightness->maximum; /* 200 ? */ - v -= delta[i] * sd->contrast->val / sd->contrast->maximum; - if (v < 0) - v = 0; - else if (v > 0xff) - v = 0xff; - reg_w(gspca_dev, 0xa2 + i, v); - } - reg_w(gspca_dev, 0xdc, 0x01); -} - -static void setcolors(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i, v; - static const int a[9] = - {217, -212, 0, -101, 170, -67, -38, -315, 355}; - static const int b[9] = - {19, 106, 0, 19, 106, 1, 19, 106, 1}; - - reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ - reg_w(gspca_dev, 0x11, 0x01); - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ - for (i = 0; i < 9; i++) { - v = a[i] * sd->saturation->val / sd->saturation->maximum; - v += b[i]; - reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); - reg_w(gspca_dev, 0x0f + 2 * i + 1, v); - } - reg_w(gspca_dev, 0xdc, 0x01); -} - -static void setwhitebalance(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ - reg_w(gspca_dev, 0xc6, sd->white_balance->val); - - reg_w(gspca_dev, 0xdc, 0x01); -} - -static void setredbalance(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ - reg_w(gspca_dev, 0xc5, sd->red_balance->val); - - reg_w(gspca_dev, 0xdc, 0x01); -} - -static void setbluebalance(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ - reg_w(gspca_dev, 0xc7, sd->blue_balance->val); - - reg_w(gspca_dev, 0xdc, 0x01); -} - -static void setgain(struct gspca_dev *gspca_dev) -{ - u8 reg10, reg12; - - if (gspca_dev->gain->val < 32) { - reg10 = gspca_dev->gain->val; - reg12 = 0; - } else { - reg10 = 31; - reg12 = gspca_dev->gain->val - 31; - } - - reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ - reg_w(gspca_dev, 0x10, reg10); - reg_w(gspca_dev, 0x12, reg12); - - /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); -} - -static void setexposure(struct gspca_dev *gspca_dev) -{ - u8 clockdiv; - u16 exposure; - - /* - * Register 2 of frame 3 contains the clock divider configuring the - * no fps according to the formula: 90 / reg. sd->exposure is the - * desired exposure time in 0.5 ms. - */ - clockdiv = (90 * gspca_dev->exposure->val + 1999) / 2000; - - /* - * Note clockdiv = 3 also works, but when running at 30 fps, depending - * on the scene being recorded, the camera switches to another - * quantization table for certain JPEG blocks, and we don't know how - * to decompress these blocks. So we cap the framerate at 15 fps. - */ - if (clockdiv < 6) - clockdiv = 6; - else if (clockdiv > 63) - clockdiv = 63; - - /* - * Register 2 MUST be a multiple of 3, except when between 6 and 12? - * Always round up, otherwise we cannot get the desired frametime - * using the partial frame time exposure control. - */ - if (clockdiv < 6 || clockdiv > 12) - clockdiv = ((clockdiv + 2) / 3) * 3; - - /* - * frame exposure time in ms = 1000 * clockdiv / 90 -> - * exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) - */ - exposure = (gspca_dev->exposure->val * 45 * 448) / (1000 * clockdiv); - /* 0 = use full frametime, 448 = no exposure, reverse it */ - exposure = 448 - exposure; - - reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ - reg_w(gspca_dev, 0x02, clockdiv); - reg_w(gspca_dev, 0x0e, exposure & 0xff); - reg_w(gspca_dev, 0x0f, exposure >> 8); - - /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); -} - -static void sethvflip(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 data, hflip, vflip; - - hflip = sd->hflip->val; - if (sd->flags & FL_HFLIP) - hflip = !hflip; - vflip = sd->vflip->val; - if (sd->flags & FL_VFLIP) - vflip = !vflip; - - reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ - data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00); - reg_w(gspca_dev, 0x21, data); - - /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); -} - -/* this function is called at probe and resume time for pac7302 */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2); - return gspca_dev->usb_err; -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) { - /* when switching to autogain set defaults to make sure - we are on a valid point of the autogain gain / - exposure knee graph, and give this change time to - take effect before doing autogain. */ - gspca_dev->exposure->val = PAC7302_EXPOSURE_DEFAULT; - gspca_dev->gain->val = PAC7302_GAIN_DEFAULT; - sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; - } - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightcont(gspca_dev); - break; - case V4L2_CID_SATURATION: - setcolors(gspca_dev); - break; - case V4L2_CID_WHITE_BALANCE_TEMPERATURE: - setwhitebalance(gspca_dev); - break; - case V4L2_CID_RED_BALANCE: - setredbalance(gspca_dev); - break; - case V4L2_CID_BLUE_BALANCE: - setbluebalance(gspca_dev); - break; - case V4L2_CID_AUTOGAIN: - if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val)) - setexposure(gspca_dev); - if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val)) - setgain(gspca_dev); - break; - case V4L2_CID_HFLIP: - sethvflip(gspca_dev); - break; - default: - return -EINVAL; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -/* this function is called at probe time */ -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 11); - - sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 32, 1, 16); - sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 255, 1, 127); - - sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SATURATION, 0, 255, 1, 127); - sd->white_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_WHITE_BALANCE_TEMPERATURE, - 0, 255, 1, 4); - sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_RED_BALANCE, 0, 3, 1, 1); - sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_RED_BALANCE, 0, 3, 1, 1); - - gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 1023, 1, - PAC7302_EXPOSURE_DEFAULT); - gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 62, 1, - PAC7302_GAIN_DEFAULT); - - sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_HFLIP, 0, 1, 1, 0); - sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_VFLIP, 0, 1, 1, 0); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - - v4l2_ctrl_cluster(2, &sd->brightness); - v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false); - v4l2_ctrl_cluster(2, &sd->hflip); - return 0; -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - reg_w_var(gspca_dev, start_7302, - page3_7302, sizeof(page3_7302)); - setbrightcont(gspca_dev); - setcolors(gspca_dev); - setwhitebalance(gspca_dev); - setredbalance(gspca_dev); - setbluebalance(gspca_dev); - setexposure(gspca_dev); - setgain(gspca_dev); - sethvflip(gspca_dev); - - sd->sof_read = 0; - sd->autogain_ignore_frames = 0; - atomic_set(&sd->avg_lum, 270 + sd->brightness->val); - - /* start stream */ - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x78, 0x01); - - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - - /* stop stream */ - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x78, 0x00); -} - -/* called on streamoff with alt 0 and on disconnect for pac7302 */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - if (!gspca_dev->present) - return; - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x78, 0x40); -} - -static void do_autogain(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int avg_lum = atomic_read(&sd->avg_lum); - int desired_lum; - const int deadzone = 30; - - if (sd->autogain_ignore_frames < 0) - return; - - if (sd->autogain_ignore_frames > 0) { - sd->autogain_ignore_frames--; - } else { - desired_lum = 270 + sd->brightness->val; - - if (gspca_expo_autogain(gspca_dev, avg_lum, desired_lum, - deadzone, PAC7302_GAIN_KNEE, - PAC7302_EXPOSURE_KNEE)) - sd->autogain_ignore_frames = - PAC_AUTOGAIN_IGNORE_FRAMES; - } -} - -/* JPEG header */ -static const u8 jpeg_header[] = { - 0xff, 0xd8, /* SOI: Start of Image */ - - 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ - 0x00, 0x11, /* length = 17 bytes (including this length field) */ - 0x08, /* Precision: 8 */ - 0x02, 0x80, /* height = 640 (image rotated) */ - 0x01, 0xe0, /* width = 480 */ - 0x03, /* Number of image components: 3 */ - 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ - 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ - 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ - - 0xff, 0xda, /* SOS: Start Of Scan */ - 0x00, 0x0c, /* length = 12 bytes (including this length field) */ - 0x03, /* number of components: 3 */ - 0x01, 0x00, /* selector 1, table 0x00 */ - 0x02, 0x11, /* selector 2, table 0x11 */ - 0x03, 0x11, /* selector 3, table 0x11 */ - 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ - 0x00 /* Successive approximation: 0 */ -}; - -/* this function is run at interrupt level */ -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 *image; - u8 *sof; - - sof = pac_find_sof(&sd->sof_read, data, len); - if (sof) { - int n, lum_offset, footer_length; - - /* - * 6 bytes after the FF D9 EOF marker a number of lumination - * bytes are send corresponding to different parts of the - * image, the 14th and 15th byte after the EOF seem to - * correspond to the center of the image. - */ - lum_offset = 61 + sizeof pac_sof_marker; - footer_length = 74; - - /* Finish decoding current frame */ - n = (sof - data) - (footer_length + sizeof pac_sof_marker); - if (n < 0) { - gspca_dev->image_len += n; - n = 0; - } else { - gspca_frame_add(gspca_dev, INTER_PACKET, data, n); - } - - image = gspca_dev->image; - if (image != NULL - && image[gspca_dev->image_len - 2] == 0xff - && image[gspca_dev->image_len - 1] == 0xd9) - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - - n = sof - data; - len -= n; - data = sof; - - /* Get average lumination */ - if (gspca_dev->last_packet_type == LAST_PACKET && - n >= lum_offset) - atomic_set(&sd->avg_lum, data[-lum_offset] + - data[-lum_offset + 1]); - - /* Start the new frame with the jpeg header */ - /* The PAC7302 has the image rotated 90 degrees */ - gspca_frame_add(gspca_dev, FIRST_PACKET, - jpeg_header, sizeof jpeg_header); - } - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int sd_dbg_s_register(struct gspca_dev *gspca_dev, - struct v4l2_dbg_register *reg) -{ - u8 index; - u8 value; - - /* - * reg->reg: bit0..15: reserved for register index (wIndex is 16bit - * long on the USB bus) - */ - if (reg->match.type == V4L2_CHIP_MATCH_HOST && - reg->match.addr == 0 && - (reg->reg < 0x000000ff) && - (reg->val <= 0x000000ff) - ) { - /* Currently writing to page 0 is only supported. */ - /* reg_w() only supports 8bit index */ - index = reg->reg; - value = reg->val; - - /* - * Note that there shall be no access to other page - * by any other function between the page switch and - * the actual register write. - */ - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ - reg_w(gspca_dev, index, value); - - reg_w(gspca_dev, 0xdc, 0x01); - } - return gspca_dev->usb_err; -} - -static int sd_chip_ident(struct gspca_dev *gspca_dev, - struct v4l2_dbg_chip_ident *chip) -{ - int ret = -EINVAL; - - if (chip->match.type == V4L2_CHIP_MATCH_HOST && - chip->match.addr == 0) { - chip->revision = 0; - chip->ident = V4L2_IDENT_UNKNOWN; - ret = 0; - } - return ret; -} -#endif - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) -static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* interrupt packet data */ - int len) /* interrput packet length */ -{ - int ret = -EINVAL; - u8 data0, data1; - - if (len == 2) { - data0 = data[0]; - data1 = data[1]; - if ((data0 == 0x00 && data1 == 0x11) || - (data0 == 0x22 && data1 == 0x33) || - (data0 == 0x44 && data1 == 0x55) || - (data0 == 0x66 && data1 == 0x77) || - (data0 == 0x88 && data1 == 0x99) || - (data0 == 0xaa && data1 == 0xbb) || - (data0 == 0xcc && data1 == 0xdd) || - (data0 == 0xee && data1 == 0xff)) { - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); - input_sync(gspca_dev->input_dev); - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); - input_sync(gspca_dev->input_dev); - ret = 0; - } - } - - return ret; -} -#endif - -/* sub-driver description for pac7302 */ -static const struct sd_desc sd_desc = { - .name = KBUILD_MODNAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, - .dq_callback = do_autogain, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .set_register = sd_dbg_s_register, - .get_chip_ident = sd_chip_ident, -#endif -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .int_pkt_scan = sd_int_pkt_scan, -#endif -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x06f8, 0x3009)}, - {USB_DEVICE(0x06f8, 0x301b)}, - {USB_DEVICE(0x093a, 0x2620)}, - {USB_DEVICE(0x093a, 0x2621)}, - {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP}, - {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP}, - {USB_DEVICE(0x093a, 0x2625)}, - {USB_DEVICE(0x093a, 0x2626)}, - {USB_DEVICE(0x093a, 0x2627), .driver_info = FL_VFLIP}, - {USB_DEVICE(0x093a, 0x2628)}, - {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP}, - {USB_DEVICE(0x093a, 0x262a)}, - {USB_DEVICE(0x093a, 0x262c)}, - {USB_DEVICE(0x145f, 0x013c)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = KBUILD_MODNAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c deleted file mode 100644 index ba3558d3f017..000000000000 --- a/drivers/media/video/gspca/pac7311.c +++ /dev/null @@ -1,701 +0,0 @@ -/* - * Pixart PAC7311 library - * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li - * - * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Some documentation about various registers as determined by trial and error. - * - * Register page 1: - * - * Address Description - * 0x08 Unknown compressor related, must always be 8 except when not - * in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 ! - * 0x1b Auto white balance related, bit 0 is AWB enable (inverted) - * bits 345 seem to toggle per color gains on/off (inverted) - * 0x78 Global control, bit 6 controls the LED (inverted) - * 0x80 Compression balance, interesting settings: - * 0x01 Use this to allow the camera to switch to higher compr. - * on the fly. Needed to stay within bandwidth @ 640x480@30 - * 0x1c From usb captures under Windows for 640x480 - * 0x2a Values >= this switch the camera to a lower compression, - * using the same table for both luminance and chrominance. - * This gives a sharper picture. Usable only at 640x480@ < - * 15 fps or 320x240 / 160x120. Note currently the driver - * does not use this as the quality gain is small and the - * generated JPG-s are only understood by v4l-utils >= 0.8.9 - * 0x3f From usb captures under Windows for 320x240 - * 0x69 From usb captures under Windows for 160x120 - * - * Register page 4: - * - * Address Description - * 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on - * the 7302, so one of 3, 6, 9, ..., except when between 6 and 12? - * 0x0f Master gain 1-245, low value = high gain - * 0x10 Another gain 0-15, limited influence (1-2x gain I guess) - * 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused - * Note setting vflip disabled leads to a much lower image quality, - * so we always vflip, and tell userspace to flip it back - * 0x27 Seems to toggle various gains on / off, Setting bit 7 seems to - * completely disable the analog amplification block. Set to 0x68 - * for max gain, 0x14 for minimal gain. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "pac7311" - -#include <linux/input.h> -#include "gspca.h" -/* Include pac common sof detection functions */ -#include "pac_common.h" - -#define PAC7311_GAIN_DEFAULT 122 -#define PAC7311_EXPOSURE_DEFAULT 3 /* 20 fps, avoid using high compr. */ - -MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); -MODULE_DESCRIPTION("Pixart PAC7311"); -MODULE_LICENSE("GPL"); - -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - struct v4l2_ctrl *contrast; - struct v4l2_ctrl *hflip; - - u8 sof_read; - u8 autogain_ignore_frames; - - atomic_t avg_lum; -}; - -static const struct v4l2_pix_format vga_mode[] = { - {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2}, - {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; - -#define LOAD_PAGE4 254 -#define END_OF_SEQUENCE 0 - -static const __u8 init_7311[] = { - 0xff, 0x01, - 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */ - 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */ - 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */ - 0xff, 0x04, - 0x27, 0x80, - 0x28, 0xca, - 0x29, 0x53, - 0x2a, 0x0e, - 0xff, 0x01, - 0x3e, 0x20, -}; - -static const __u8 start_7311[] = { -/* index, len, [value]* */ - 0xff, 1, 0x01, /* page 1 */ - 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00, - 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c, - 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e, - 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49, - 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48, - 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78, - 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b, - 0xd0, 0xff, - 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80, - 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84, - 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14, - 0x18, 0x20, - 0x96, 3, 0x01, 0x08, 0x04, - 0xa0, 4, 0x44, 0x44, 0x44, 0x04, - 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00, - 0x3f, 0x00, 0x0a, 0x01, 0x00, - 0xff, 1, 0x04, /* page 4 */ - 0, LOAD_PAGE4, /* load the page 4 */ - 0x11, 1, 0x01, - 0, END_OF_SEQUENCE /* end of sequence */ -}; - -#define SKIP 0xaa -/* page 4 - the value SKIP says skip the index - see reg_w_page() */ -static const __u8 page4_7311[] = { - SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f, - 0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62, - 0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP, - SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68, - 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 -}; - -static void reg_w_buf(struct gspca_dev *gspca_dev, - __u8 index, - const u8 *buffer, int len) -{ - int ret; - - if (gspca_dev->usb_err < 0) - return; - memcpy(gspca_dev->usb_buf, buffer, len); - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, /* value */ - index, gspca_dev->usb_buf, len, - 500); - if (ret < 0) { - pr_err("reg_w_buf() failed index 0x%02x, error %d\n", - index, ret); - gspca_dev->usb_err = ret; - } -} - - -static void reg_w(struct gspca_dev *gspca_dev, - __u8 index, - __u8 value) -{ - int ret; - - if (gspca_dev->usb_err < 0) - return; - gspca_dev->usb_buf[0] = value; - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, index, gspca_dev->usb_buf, 1, - 500); - if (ret < 0) { - pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n", - index, value, ret); - gspca_dev->usb_err = ret; - } -} - -static void reg_w_seq(struct gspca_dev *gspca_dev, - const __u8 *seq, int len) -{ - while (--len >= 0) { - reg_w(gspca_dev, seq[0], seq[1]); - seq += 2; - } -} - -/* load the beginning of a page */ -static void reg_w_page(struct gspca_dev *gspca_dev, - const __u8 *page, int len) -{ - int index; - int ret = 0; - - if (gspca_dev->usb_err < 0) - return; - for (index = 0; index < len; index++) { - if (page[index] == SKIP) /* skip this index */ - continue; - gspca_dev->usb_buf[0] = page[index]; - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, index, gspca_dev->usb_buf, 1, - 500); - if (ret < 0) { - pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n", - index, page[index], ret); - gspca_dev->usb_err = ret; - break; - } - } -} - -/* output a variable sequence */ -static void reg_w_var(struct gspca_dev *gspca_dev, - const __u8 *seq, - const __u8 *page4, unsigned int page4_len) -{ - int index, len; - - for (;;) { - index = *seq++; - len = *seq++; - switch (len) { - case END_OF_SEQUENCE: - return; - case LOAD_PAGE4: - reg_w_page(gspca_dev, page4, page4_len); - break; - default: - if (len > USB_BUF_SZ) { - PDEBUG(D_ERR|D_STREAM, - "Incorrect variable sequence"); - return; - } - while (len > 0) { - if (len < 8) { - reg_w_buf(gspca_dev, - index, seq, len); - seq += len; - break; - } - reg_w_buf(gspca_dev, index, seq, 8); - seq += 8; - index += 8; - len -= 8; - } - } - } - /* not reached */ -} - -/* this function is called at probe time for pac7311 */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct cam *cam = &gspca_dev->cam; - - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - cam->input_flags = V4L2_IN_ST_VFLIP; - - return 0; -} - -static void setcontrast(struct gspca_dev *gspca_dev, s32 val) -{ - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x10, val); - /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); -} - -static void setgain(struct gspca_dev *gspca_dev, s32 val) -{ - reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ - reg_w(gspca_dev, 0x0e, 0x00); - reg_w(gspca_dev, 0x0f, gspca_dev->gain->maximum - val + 1); - - /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); -} - -static void setexposure(struct gspca_dev *gspca_dev, s32 val) -{ - reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ - reg_w(gspca_dev, 0x02, val); - - /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); - - /* - * Page 1 register 8 must always be 0x08 except when not in - * 640x480 mode and page 4 reg 2 <= 3 then it must be 9 - */ - reg_w(gspca_dev, 0xff, 0x01); - if (gspca_dev->width != 640 && val <= 3) - reg_w(gspca_dev, 0x08, 0x09); - else - reg_w(gspca_dev, 0x08, 0x08); - - /* - * Page1 register 80 sets the compression balance, normally we - * want / use 0x1c, but for 640x480@30fps we must allow the - * camera to use higher compression or we may run out of - * bandwidth. - */ - if (gspca_dev->width == 640 && val == 2) - reg_w(gspca_dev, 0x80, 0x01); - else - reg_w(gspca_dev, 0x80, 0x1c); - - /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); -} - -static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip) -{ - __u8 data; - - reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ - data = (hflip ? 0x04 : 0x00) | - (vflip ? 0x08 : 0x00); - reg_w(gspca_dev, 0x21, data); - - /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); -} - -/* this function is called at probe and resume time for pac7311 */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2); - return gspca_dev->usb_err; -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) { - /* when switching to autogain set defaults to make sure - we are on a valid point of the autogain gain / - exposure knee graph, and give this change time to - take effect before doing autogain. */ - gspca_dev->exposure->val = PAC7311_EXPOSURE_DEFAULT; - gspca_dev->gain->val = PAC7311_GAIN_DEFAULT; - sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; - } - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_CONTRAST: - setcontrast(gspca_dev, ctrl->val); - break; - case V4L2_CID_AUTOGAIN: - if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val)) - setexposure(gspca_dev, gspca_dev->exposure->val); - if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val)) - setgain(gspca_dev, gspca_dev->gain->val); - break; - case V4L2_CID_HFLIP: - sethvflip(gspca_dev, sd->hflip->val, 1); - break; - default: - return -EINVAL; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -/* this function is called at probe time */ -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 5); - - sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 15, 1, 7); - gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, 2, 63, 1, - PAC7311_EXPOSURE_DEFAULT); - gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 244, 1, - PAC7311_GAIN_DEFAULT); - sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_HFLIP, 0, 1, 1, 0); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - - v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false); - return 0; -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->sof_read = 0; - - reg_w_var(gspca_dev, start_7311, - page4_7311, sizeof(page4_7311)); - setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->contrast)); - setgain(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->gain)); - setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure)); - sethvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip), 1); - - /* set correct resolution */ - switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { - case 2: /* 160x120 */ - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x17, 0x20); - reg_w(gspca_dev, 0x87, 0x10); - break; - case 1: /* 320x240 */ - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x17, 0x30); - reg_w(gspca_dev, 0x87, 0x11); - break; - case 0: /* 640x480 */ - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x17, 0x00); - reg_w(gspca_dev, 0x87, 0x12); - break; - } - - sd->sof_read = 0; - sd->autogain_ignore_frames = 0; - atomic_set(&sd->avg_lum, -1); - - /* start stream */ - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x78, 0x05); - - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x27, 0x80); - reg_w(gspca_dev, 0x28, 0xca); - reg_w(gspca_dev, 0x29, 0x53); - reg_w(gspca_dev, 0x2a, 0x0e); - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x3e, 0x20); - reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ - reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ - reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ -} - -static void do_autogain(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int avg_lum = atomic_read(&sd->avg_lum); - int desired_lum, deadzone; - - if (avg_lum == -1) - return; - - desired_lum = 170; - deadzone = 20; - - if (sd->autogain_ignore_frames > 0) - sd->autogain_ignore_frames--; - else if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum, - desired_lum, deadzone)) - sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; -} - -/* JPEG header, part 1 */ -static const unsigned char pac_jpeg_header1[] = { - 0xff, 0xd8, /* SOI: Start of Image */ - - 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ - 0x00, 0x11, /* length = 17 bytes (including this length field) */ - 0x08 /* Precision: 8 */ - /* 2 bytes is placed here: number of image lines */ - /* 2 bytes is placed here: samples per line */ -}; - -/* JPEG header, continued */ -static const unsigned char pac_jpeg_header2[] = { - 0x03, /* Number of image components: 3 */ - 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ - 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ - 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ - - 0xff, 0xda, /* SOS: Start Of Scan */ - 0x00, 0x0c, /* length = 12 bytes (including this length field) */ - 0x03, /* number of components: 3 */ - 0x01, 0x00, /* selector 1, table 0x00 */ - 0x02, 0x11, /* selector 2, table 0x11 */ - 0x03, 0x11, /* selector 3, table 0x11 */ - 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ - 0x00 /* Successive approximation: 0 */ -}; - -static void pac_start_frame(struct gspca_dev *gspca_dev, - __u16 lines, __u16 samples_per_line) -{ - unsigned char tmpbuf[4]; - - gspca_frame_add(gspca_dev, FIRST_PACKET, - pac_jpeg_header1, sizeof(pac_jpeg_header1)); - - tmpbuf[0] = lines >> 8; - tmpbuf[1] = lines & 0xff; - tmpbuf[2] = samples_per_line >> 8; - tmpbuf[3] = samples_per_line & 0xff; - - gspca_frame_add(gspca_dev, INTER_PACKET, - tmpbuf, sizeof(tmpbuf)); - gspca_frame_add(gspca_dev, INTER_PACKET, - pac_jpeg_header2, sizeof(pac_jpeg_header2)); -} - -/* this function is run at interrupt level */ -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 *image; - unsigned char *sof; - - sof = pac_find_sof(&sd->sof_read, data, len); - if (sof) { - int n, lum_offset, footer_length; - - /* - * 6 bytes after the FF D9 EOF marker a number of lumination - * bytes are send corresponding to different parts of the - * image, the 14th and 15th byte after the EOF seem to - * correspond to the center of the image. - */ - lum_offset = 24 + sizeof pac_sof_marker; - footer_length = 26; - - /* Finish decoding current frame */ - n = (sof - data) - (footer_length + sizeof pac_sof_marker); - if (n < 0) { - gspca_dev->image_len += n; - n = 0; - } else { - gspca_frame_add(gspca_dev, INTER_PACKET, data, n); - } - image = gspca_dev->image; - if (image != NULL - && image[gspca_dev->image_len - 2] == 0xff - && image[gspca_dev->image_len - 1] == 0xd9) - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - - n = sof - data; - len -= n; - data = sof; - - /* Get average lumination */ - if (gspca_dev->last_packet_type == LAST_PACKET && - n >= lum_offset) - atomic_set(&sd->avg_lum, data[-lum_offset] + - data[-lum_offset + 1]); - else - atomic_set(&sd->avg_lum, -1); - - /* Start the new frame with the jpeg header */ - pac_start_frame(gspca_dev, - gspca_dev->height, gspca_dev->width); - } - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) -static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* interrupt packet data */ - int len) /* interrupt packet length */ -{ - int ret = -EINVAL; - u8 data0, data1; - - if (len == 2) { - data0 = data[0]; - data1 = data[1]; - if ((data0 == 0x00 && data1 == 0x11) || - (data0 == 0x22 && data1 == 0x33) || - (data0 == 0x44 && data1 == 0x55) || - (data0 == 0x66 && data1 == 0x77) || - (data0 == 0x88 && data1 == 0x99) || - (data0 == 0xaa && data1 == 0xbb) || - (data0 == 0xcc && data1 == 0xdd) || - (data0 == 0xee && data1 == 0xff)) { - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); - input_sync(gspca_dev->input_dev); - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); - input_sync(gspca_dev->input_dev); - ret = 0; - } - } - - return ret; -} -#endif - -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, - .dq_callback = do_autogain, -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .int_pkt_scan = sd_int_pkt_scan, -#endif -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x093a, 0x2600)}, - {USB_DEVICE(0x093a, 0x2601)}, - {USB_DEVICE(0x093a, 0x2603)}, - {USB_DEVICE(0x093a, 0x2608)}, - {USB_DEVICE(0x093a, 0x260e)}, - {USB_DEVICE(0x093a, 0x260f)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/pac_common.h b/drivers/media/video/gspca/pac_common.h deleted file mode 100644 index 8462a7c1a338..000000000000 --- a/drivers/media/video/gspca/pac_common.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Pixart PAC207BCA / PAC73xx common functions - * - * Copyright (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl> - * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li - * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr - * - * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* We calculate the autogain at the end of the transfer of a frame, at this - moment a frame with the old settings is being captured and transmitted. So - if we adjust the gain or exposure we must ignore atleast the next frame for - the new settings to come into effect before doing any other adjustments. */ -#define PAC_AUTOGAIN_IGNORE_FRAMES 2 - -static const unsigned char pac_sof_marker[5] = - { 0xff, 0xff, 0x00, 0xff, 0x96 }; - -/* - The following state machine finds the SOF marker sequence - 0xff, 0xff, 0x00, 0xff, 0x96 in a byte stream. - - +----------+ - | 0: START |<---------------\ - +----------+<-\ | - | \---/otherwise | - v 0xff | - +----------+ otherwise | - | 1 |--------------->* - | | ^ - +----------+ | - | | - v 0xff | - +----------+<-\0xff | - /->| |--/ | - | | 2 |--------------->* - | | | otherwise ^ - | +----------+ | - | | | - | v 0x00 | - | +----------+ | - | | 3 | | - | | |--------------->* - | +----------+ otherwise ^ - | | | - 0xff | v 0xff | - | +----------+ | - \--| 4 | | - | |----------------/ - +----------+ otherwise - | - v 0x96 - +----------+ - | FOUND | - +----------+ -*/ - -static unsigned char *pac_find_sof(u8 *sof_read, - unsigned char *m, int len) -{ - int i; - - /* Search for the SOF marker (fixed part) in the header */ - for (i = 0; i < len; i++) { - switch (*sof_read) { - case 0: - if (m[i] == 0xff) - *sof_read = 1; - break; - case 1: - if (m[i] == 0xff) - *sof_read = 2; - else - *sof_read = 0; - break; - case 2: - switch (m[i]) { - case 0x00: - *sof_read = 3; - break; - case 0xff: - /* stay in this state */ - break; - default: - *sof_read = 0; - } - break; - case 3: - if (m[i] == 0xff) - *sof_read = 4; - else - *sof_read = 0; - break; - case 4: - switch (m[i]) { - case 0x96: - /* Pattern found */ - PDEBUG(D_FRAM, - "SOF found, bytes to analyze: %u." - " Frame starts at byte #%u", - len, i + 1); - *sof_read = 0; - return m + i + 1; - break; - case 0xff: - *sof_read = 2; - break; - default: - *sof_read = 0; - } - break; - default: - *sof_read = 0; - } - } - - return NULL; -} diff --git a/drivers/media/video/gspca/se401.c b/drivers/media/video/gspca/se401.c deleted file mode 100644 index a33cb78a839c..000000000000 --- a/drivers/media/video/gspca/se401.c +++ /dev/null @@ -1,739 +0,0 @@ -/* - * GSPCA Endpoints (formerly known as AOX) se401 USB Camera sub Driver - * - * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com> - * - * Based on the v4l1 se401 driver which is: - * - * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org) - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "se401" - -#define BULK_SIZE 4096 -#define PACKET_SIZE 1024 -#define READ_REQ_SIZE 64 -#define MAX_MODES ((READ_REQ_SIZE - 6) / 4) -/* The se401 compression algorithm uses a fixed quant factor, which - can be configured by setting the high nibble of the SE401_OPERATINGMODE - feature. This needs to exactly match what is in libv4l! */ -#define SE401_QUANT_FACT 8 - -#include <linux/input.h> -#include <linux/slab.h> -#include "gspca.h" -#include "se401.h" - -MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); -MODULE_DESCRIPTION("Endpoints se401"); -MODULE_LICENSE("GPL"); - -/* exposure change state machine states */ -enum { - EXPO_CHANGED, - EXPO_DROP_FRAME, - EXPO_NO_CHANGE, -}; - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - struct { /* exposure/freq control cluster */ - struct v4l2_ctrl *exposure; - struct v4l2_ctrl *freq; - }; - bool has_brightness; - struct v4l2_pix_format fmts[MAX_MODES]; - int pixels_read; - int packet_read; - u8 packet[PACKET_SIZE]; - u8 restart_stream; - u8 button_state; - u8 resetlevel; - u8 resetlevel_frame_count; - int resetlevel_adjust_dir; - int expo_change_state; -}; - - -static void se401_write_req(struct gspca_dev *gspca_dev, u16 req, u16 value, - int silent) -{ - int err; - - if (gspca_dev->usb_err < 0) - return; - - err = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, 0, NULL, 0, 1000); - if (err < 0) { - if (!silent) - pr_err("write req failed req %#04x val %#04x error %d\n", - req, value, err); - gspca_dev->usb_err = err; - } -} - -static void se401_read_req(struct gspca_dev *gspca_dev, u16 req, int silent) -{ - int err; - - if (gspca_dev->usb_err < 0) - return; - - if (USB_BUF_SZ < READ_REQ_SIZE) { - pr_err("USB_BUF_SZ too small!!\n"); - gspca_dev->usb_err = -ENOBUFS; - return; - } - - err = usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, 0, gspca_dev->usb_buf, READ_REQ_SIZE, 1000); - if (err < 0) { - if (!silent) - pr_err("read req failed req %#04x error %d\n", - req, err); - gspca_dev->usb_err = err; - } -} - -static void se401_set_feature(struct gspca_dev *gspca_dev, - u16 selector, u16 param) -{ - int err; - - if (gspca_dev->usb_err < 0) - return; - - err = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - SE401_REQ_SET_EXT_FEATURE, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - param, selector, NULL, 0, 1000); - if (err < 0) { - pr_err("set feature failed sel %#04x param %#04x error %d\n", - selector, param, err); - gspca_dev->usb_err = err; - } -} - -static int se401_get_feature(struct gspca_dev *gspca_dev, u16 selector) -{ - int err; - - if (gspca_dev->usb_err < 0) - return gspca_dev->usb_err; - - if (USB_BUF_SZ < 2) { - pr_err("USB_BUF_SZ too small!!\n"); - gspca_dev->usb_err = -ENOBUFS; - return gspca_dev->usb_err; - } - - err = usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - SE401_REQ_GET_EXT_FEATURE, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, selector, gspca_dev->usb_buf, 2, 1000); - if (err < 0) { - pr_err("get feature failed sel %#04x error %d\n", - selector, err); - gspca_dev->usb_err = err; - return err; - } - return gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8); -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 val) -{ - /* HDG: this does not seem to do anything on my cam */ - se401_write_req(gspca_dev, SE401_REQ_SET_BRT, val, 0); -} - -static void setgain(struct gspca_dev *gspca_dev, s32 val) -{ - u16 gain = 63 - val; - - /* red color gain */ - se401_set_feature(gspca_dev, HV7131_REG_ARCG, gain); - /* green color gain */ - se401_set_feature(gspca_dev, HV7131_REG_AGCG, gain); - /* blue color gain */ - se401_set_feature(gspca_dev, HV7131_REG_ABCG, gain); -} - -static void setexposure(struct gspca_dev *gspca_dev, s32 val, s32 freq) -{ - struct sd *sd = (struct sd *) gspca_dev; - int integration = val << 6; - u8 expose_h, expose_m, expose_l; - - /* Do this before the set_feature calls, for proper timing wrt - the interrupt driven pkt_scan. Note we may still race but that - is not a big issue, the expo change state machine is merely for - avoiding underexposed frames getting send out, if one sneaks - through so be it */ - sd->expo_change_state = EXPO_CHANGED; - - if (freq == V4L2_CID_POWER_LINE_FREQUENCY_50HZ) - integration = integration - integration % 106667; - if (freq == V4L2_CID_POWER_LINE_FREQUENCY_60HZ) - integration = integration - integration % 88889; - - expose_h = (integration >> 16); - expose_m = (integration >> 8); - expose_l = integration; - - /* integration time low */ - se401_set_feature(gspca_dev, HV7131_REG_TITL, expose_l); - /* integration time mid */ - se401_set_feature(gspca_dev, HV7131_REG_TITM, expose_m); - /* integration time high */ - se401_set_feature(gspca_dev, HV7131_REG_TITU, expose_h); -} - -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *)gspca_dev; - struct cam *cam = &gspca_dev->cam; - u8 *cd = gspca_dev->usb_buf; - int i, j, n; - int widths[MAX_MODES], heights[MAX_MODES]; - - /* Read the camera descriptor */ - se401_read_req(gspca_dev, SE401_REQ_GET_CAMERA_DESCRIPTOR, 1); - if (gspca_dev->usb_err) { - /* Sometimes after being idle for a while the se401 won't - respond and needs a good kicking */ - usb_reset_device(gspca_dev->dev); - gspca_dev->usb_err = 0; - se401_read_req(gspca_dev, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0); - } - - /* Some cameras start with their LED on */ - se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 0, 0); - if (gspca_dev->usb_err) - return gspca_dev->usb_err; - - if (cd[1] != 0x41) { - pr_err("Wrong descriptor type\n"); - return -ENODEV; - } - - if (!(cd[2] & SE401_FORMAT_BAYER)) { - pr_err("Bayer format not supported!\n"); - return -ENODEV; - } - - if (cd[3]) - pr_info("ExtraFeatures: %d\n", cd[3]); - - n = cd[4] | (cd[5] << 8); - if (n > MAX_MODES) { - pr_err("Too many frame sizes\n"); - return -ENODEV; - } - - for (i = 0; i < n ; i++) { - widths[i] = cd[6 + i * 4 + 0] | (cd[6 + i * 4 + 1] << 8); - heights[i] = cd[6 + i * 4 + 2] | (cd[6 + i * 4 + 3] << 8); - } - - for (i = 0; i < n ; i++) { - sd->fmts[i].width = widths[i]; - sd->fmts[i].height = heights[i]; - sd->fmts[i].field = V4L2_FIELD_NONE; - sd->fmts[i].colorspace = V4L2_COLORSPACE_SRGB; - sd->fmts[i].priv = 1; - - /* janggu compression only works for 1/4th or 1/16th res */ - for (j = 0; j < n; j++) { - if (widths[j] / 2 == widths[i] && - heights[j] / 2 == heights[i]) { - sd->fmts[i].priv = 2; - break; - } - } - /* 1/16th if available too is better then 1/4th, because - we then use a larger area of the sensor */ - for (j = 0; j < n; j++) { - if (widths[j] / 4 == widths[i] && - heights[j] / 4 == heights[i]) { - sd->fmts[i].priv = 4; - break; - } - } - - if (sd->fmts[i].priv == 1) { - /* Not a 1/4th or 1/16th res, use bayer */ - sd->fmts[i].pixelformat = V4L2_PIX_FMT_SBGGR8; - sd->fmts[i].bytesperline = widths[i]; - sd->fmts[i].sizeimage = widths[i] * heights[i]; - pr_info("Frame size: %dx%d bayer\n", - widths[i], heights[i]); - } else { - /* Found a match use janggu compression */ - sd->fmts[i].pixelformat = V4L2_PIX_FMT_SE401; - sd->fmts[i].bytesperline = 0; - sd->fmts[i].sizeimage = widths[i] * heights[i] * 3; - pr_info("Frame size: %dx%d 1/%dth janggu\n", - widths[i], heights[i], - sd->fmts[i].priv * sd->fmts[i].priv); - } - } - - cam->cam_mode = sd->fmts; - cam->nmodes = n; - cam->bulk = 1; - cam->bulk_size = BULK_SIZE; - cam->bulk_nurbs = 4; - sd->resetlevel = 0x2d; /* Set initial resetlevel */ - - /* See if the camera supports brightness */ - se401_read_req(gspca_dev, SE401_REQ_GET_BRT, 1); - sd->has_brightness = !!gspca_dev->usb_err; - gspca_dev->usb_err = 0; - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - return 0; -} - -/* function called at start time before URB creation */ -static int sd_isoc_init(struct gspca_dev *gspca_dev) -{ - gspca_dev->alt = 1; /* Ignore the bogus isoc alt settings */ - - return gspca_dev->usb_err; -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - int mult = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - int mode = 0; - - se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 1, 1); - if (gspca_dev->usb_err) { - /* Sometimes after being idle for a while the se401 won't - respond and needs a good kicking */ - usb_reset_device(gspca_dev->dev); - gspca_dev->usb_err = 0; - se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 1, 0); - } - se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 1, 0); - - se401_set_feature(gspca_dev, HV7131_REG_MODE_B, 0x05); - - /* set size + mode */ - se401_write_req(gspca_dev, SE401_REQ_SET_WIDTH, - gspca_dev->width * mult, 0); - se401_write_req(gspca_dev, SE401_REQ_SET_HEIGHT, - gspca_dev->height * mult, 0); - /* - * HDG: disabled this as it does not seem to do anything - * se401_write_req(gspca_dev, SE401_REQ_SET_OUTPUT_MODE, - * SE401_FORMAT_BAYER, 0); - */ - - switch (mult) { - case 1: /* Raw bayer */ - mode = 0x03; break; - case 2: /* 1/4th janggu */ - mode = SE401_QUANT_FACT << 4; break; - case 4: /* 1/16th janggu */ - mode = (SE401_QUANT_FACT << 4) | 0x02; break; - } - se401_set_feature(gspca_dev, SE401_OPERATINGMODE, mode); - - se401_set_feature(gspca_dev, HV7131_REG_ARLV, sd->resetlevel); - - sd->packet_read = 0; - sd->pixels_read = 0; - sd->restart_stream = 0; - sd->resetlevel_frame_count = 0; - sd->resetlevel_adjust_dir = 0; - sd->expo_change_state = EXPO_NO_CHANGE; - - se401_write_req(gspca_dev, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, 0); - - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - se401_write_req(gspca_dev, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, 0); - se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 0, 0); - se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 0, 0); -} - -static void sd_dq_callback(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - unsigned int ahrc, alrc; - int oldreset, adjust_dir; - - /* Restart the stream if requested do so by pkt_scan */ - if (sd->restart_stream) { - sd_stopN(gspca_dev); - sd_start(gspca_dev); - sd->restart_stream = 0; - } - - /* Automatically adjust sensor reset level - Hyundai have some really nice docs about this and other sensor - related stuff on their homepage: www.hei.co.kr */ - sd->resetlevel_frame_count++; - if (sd->resetlevel_frame_count < 20) - return; - - /* For some reason this normally read-only register doesn't get reset - to zero after reading them just once... */ - se401_get_feature(gspca_dev, HV7131_REG_HIREFNOH); - se401_get_feature(gspca_dev, HV7131_REG_HIREFNOL); - se401_get_feature(gspca_dev, HV7131_REG_LOREFNOH); - se401_get_feature(gspca_dev, HV7131_REG_LOREFNOL); - ahrc = 256*se401_get_feature(gspca_dev, HV7131_REG_HIREFNOH) + - se401_get_feature(gspca_dev, HV7131_REG_HIREFNOL); - alrc = 256*se401_get_feature(gspca_dev, HV7131_REG_LOREFNOH) + - se401_get_feature(gspca_dev, HV7131_REG_LOREFNOL); - - /* Not an exact science, but it seems to work pretty well... */ - oldreset = sd->resetlevel; - if (alrc > 10) { - while (alrc >= 10 && sd->resetlevel < 63) { - sd->resetlevel++; - alrc /= 2; - } - } else if (ahrc > 20) { - while (ahrc >= 20 && sd->resetlevel > 0) { - sd->resetlevel--; - ahrc /= 2; - } - } - /* Detect ping-pong-ing and halve adjustment to avoid overshoot */ - if (sd->resetlevel > oldreset) - adjust_dir = 1; - else - adjust_dir = -1; - if (sd->resetlevel_adjust_dir && - sd->resetlevel_adjust_dir != adjust_dir) - sd->resetlevel = oldreset + (sd->resetlevel - oldreset) / 2; - - if (sd->resetlevel != oldreset) { - sd->resetlevel_adjust_dir = adjust_dir; - se401_set_feature(gspca_dev, HV7131_REG_ARLV, sd->resetlevel); - } - - sd->resetlevel_frame_count = 0; -} - -static void sd_complete_frame(struct gspca_dev *gspca_dev, u8 *data, int len) -{ - struct sd *sd = (struct sd *)gspca_dev; - - switch (sd->expo_change_state) { - case EXPO_CHANGED: - /* The exposure was changed while this frame - was being send, so this frame is ok */ - sd->expo_change_state = EXPO_DROP_FRAME; - break; - case EXPO_DROP_FRAME: - /* The exposure was changed while this frame - was being captured, drop it! */ - gspca_dev->last_packet_type = DISCARD_PACKET; - sd->expo_change_state = EXPO_NO_CHANGE; - break; - case EXPO_NO_CHANGE: - break; - } - gspca_frame_add(gspca_dev, LAST_PACKET, data, len); -} - -static void sd_pkt_scan_janggu(struct gspca_dev *gspca_dev, u8 *data, int len) -{ - struct sd *sd = (struct sd *)gspca_dev; - int imagesize = gspca_dev->width * gspca_dev->height; - int i, plen, bits, pixels, info, count; - - if (sd->restart_stream) - return; - - /* Sometimes a 1024 bytes garbage bulk packet is send between frames */ - if (gspca_dev->last_packet_type == LAST_PACKET && len == 1024) { - gspca_dev->last_packet_type = DISCARD_PACKET; - return; - } - - i = 0; - while (i < len) { - /* Read header if not already be present from prev bulk pkt */ - if (sd->packet_read < 4) { - count = 4 - sd->packet_read; - if (count > len - i) - count = len - i; - memcpy(&sd->packet[sd->packet_read], &data[i], count); - sd->packet_read += count; - i += count; - if (sd->packet_read < 4) - break; - } - bits = sd->packet[3] + (sd->packet[2] << 8); - pixels = sd->packet[1] + ((sd->packet[0] & 0x3f) << 8); - info = (sd->packet[0] & 0xc0) >> 6; - plen = ((bits + 47) >> 4) << 1; - /* Sanity checks */ - if (plen > 1024) { - pr_err("invalid packet len %d restarting stream\n", - plen); - goto error; - } - if (info == 3) { - pr_err("unknown frame info value restarting stream\n"); - goto error; - } - - /* Read (remainder of) packet contents */ - count = plen - sd->packet_read; - if (count > len - i) - count = len - i; - memcpy(&sd->packet[sd->packet_read], &data[i], count); - sd->packet_read += count; - i += count; - if (sd->packet_read < plen) - break; - - sd->pixels_read += pixels; - sd->packet_read = 0; - - switch (info) { - case 0: /* Frame data */ - gspca_frame_add(gspca_dev, INTER_PACKET, sd->packet, - plen); - break; - case 1: /* EOF */ - if (sd->pixels_read != imagesize) { - pr_err("frame size %d expected %d\n", - sd->pixels_read, imagesize); - goto error; - } - sd_complete_frame(gspca_dev, sd->packet, plen); - return; /* Discard the rest of the bulk packet !! */ - case 2: /* SOF */ - gspca_frame_add(gspca_dev, FIRST_PACKET, sd->packet, - plen); - sd->pixels_read = pixels; - break; - } - } - return; - -error: - sd->restart_stream = 1; - /* Give userspace a 0 bytes frame, so our dq callback gets - called and it can restart the stream */ - gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); -} - -static void sd_pkt_scan_bayer(struct gspca_dev *gspca_dev, u8 *data, int len) -{ - struct cam *cam = &gspca_dev->cam; - int imagesize = cam->cam_mode[gspca_dev->curr_mode].sizeimage; - - if (gspca_dev->image_len == 0) { - gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); - return; - } - - if (gspca_dev->image_len + len >= imagesize) { - sd_complete_frame(gspca_dev, data, len); - return; - } - - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len) -{ - int mult = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - - if (len == 0) - return; - - if (mult == 1) /* mult == 1 means raw bayer */ - sd_pkt_scan_bayer(gspca_dev, data, len); - else - sd_pkt_scan_janggu(gspca_dev, data, len); -} - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) -static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len) -{ - struct sd *sd = (struct sd *)gspca_dev; - u8 state; - - if (len != 2) - return -EINVAL; - - switch (data[0]) { - case 0: - case 1: - state = data[0]; - break; - default: - return -EINVAL; - } - if (sd->button_state != state) { - input_report_key(gspca_dev->input_dev, KEY_CAMERA, state); - input_sync(gspca_dev->input_dev); - sd->button_state = state; - } - - return 0; -} -#endif - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_GAIN: - setgain(gspca_dev, ctrl->val); - break; - case V4L2_CID_EXPOSURE: - setexposure(gspca_dev, ctrl->val, sd->freq->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 4); - if (sd->has_brightness) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 15); - /* max is really 63 but > 50 is not pretty */ - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 50, 1, 25); - sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 32767, 1, 15000); - sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, - V4L2_CID_POWER_LINE_FREQUENCY, - V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - v4l2_ctrl_cluster(2, &sd->exposure); - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .isoc_init = sd_isoc_init, - .start = sd_start, - .stopN = sd_stopN, - .dq_callback = sd_dq_callback, - .pkt_scan = sd_pkt_scan, -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .int_pkt_scan = sd_int_pkt_scan, -#endif -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x03e8, 0x0004)}, /* Endpoints/Aox SE401 */ - {USB_DEVICE(0x0471, 0x030b)}, /* Philips PCVC665K */ - {USB_DEVICE(0x047d, 0x5001)}, /* Kensington 67014 */ - {USB_DEVICE(0x047d, 0x5002)}, /* Kensington 6701(5/7) */ - {USB_DEVICE(0x047d, 0x5003)}, /* Kensington 67016 */ - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static int sd_pre_reset(struct usb_interface *intf) -{ - return 0; -} - -static int sd_post_reset(struct usb_interface *intf) -{ - return 0; -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif - .pre_reset = sd_pre_reset, - .post_reset = sd_post_reset, -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/se401.h b/drivers/media/video/gspca/se401.h deleted file mode 100644 index 96d8ebf3cf59..000000000000 --- a/drivers/media/video/gspca/se401.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * GSPCA Endpoints (formerly known as AOX) se401 USB Camera sub Driver - * - * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com> - * - * Based on the v4l1 se401 driver which is: - * - * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org) - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#define SE401_REQ_GET_CAMERA_DESCRIPTOR 0x06 -#define SE401_REQ_START_CONTINUOUS_CAPTURE 0x41 -#define SE401_REQ_STOP_CONTINUOUS_CAPTURE 0x42 -#define SE401_REQ_CAPTURE_FRAME 0x43 -#define SE401_REQ_GET_BRT 0x44 -#define SE401_REQ_SET_BRT 0x45 -#define SE401_REQ_GET_WIDTH 0x4c -#define SE401_REQ_SET_WIDTH 0x4d -#define SE401_REQ_GET_HEIGHT 0x4e -#define SE401_REQ_SET_HEIGHT 0x4f -#define SE401_REQ_GET_OUTPUT_MODE 0x50 -#define SE401_REQ_SET_OUTPUT_MODE 0x51 -#define SE401_REQ_GET_EXT_FEATURE 0x52 -#define SE401_REQ_SET_EXT_FEATURE 0x53 -#define SE401_REQ_CAMERA_POWER 0x56 -#define SE401_REQ_LED_CONTROL 0x57 -#define SE401_REQ_BIOS 0xff - -#define SE401_BIOS_READ 0x07 - -#define SE401_FORMAT_BAYER 0x40 - -/* Hyundai hv7131b registers - 7121 and 7141 should be the same (haven't really checked...) */ -/* Mode registers: */ -#define HV7131_REG_MODE_A 0x00 -#define HV7131_REG_MODE_B 0x01 -#define HV7131_REG_MODE_C 0x02 -/* Frame registers: */ -#define HV7131_REG_FRSU 0x10 -#define HV7131_REG_FRSL 0x11 -#define HV7131_REG_FCSU 0x12 -#define HV7131_REG_FCSL 0x13 -#define HV7131_REG_FWHU 0x14 -#define HV7131_REG_FWHL 0x15 -#define HV7131_REG_FWWU 0x16 -#define HV7131_REG_FWWL 0x17 -/* Timing registers: */ -#define HV7131_REG_THBU 0x20 -#define HV7131_REG_THBL 0x21 -#define HV7131_REG_TVBU 0x22 -#define HV7131_REG_TVBL 0x23 -#define HV7131_REG_TITU 0x25 -#define HV7131_REG_TITM 0x26 -#define HV7131_REG_TITL 0x27 -#define HV7131_REG_TMCD 0x28 -/* Adjust Registers: */ -#define HV7131_REG_ARLV 0x30 -#define HV7131_REG_ARCG 0x31 -#define HV7131_REG_AGCG 0x32 -#define HV7131_REG_ABCG 0x33 -#define HV7131_REG_APBV 0x34 -#define HV7131_REG_ASLP 0x54 -/* Offset Registers: */ -#define HV7131_REG_OFSR 0x50 -#define HV7131_REG_OFSG 0x51 -#define HV7131_REG_OFSB 0x52 -/* REset level statistics registers: */ -#define HV7131_REG_LOREFNOH 0x57 -#define HV7131_REG_LOREFNOL 0x58 -#define HV7131_REG_HIREFNOH 0x59 -#define HV7131_REG_HIREFNOL 0x5a - -/* se401 registers */ -#define SE401_OPERATINGMODE 0x2000 diff --git a/drivers/media/video/gspca/sn9c2028.c b/drivers/media/video/gspca/sn9c2028.c deleted file mode 100644 index 03fa3fd940b4..000000000000 --- a/drivers/media/video/gspca/sn9c2028.c +++ /dev/null @@ -1,735 +0,0 @@ -/* - * SN9C2028 library - * - * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "sn9c2028" - -#include "gspca.h" - -MODULE_AUTHOR("Theodore Kilgore"); -MODULE_DESCRIPTION("Sonix SN9C2028 USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - u8 sof_read; - u16 model; -}; - -struct init_command { - unsigned char instruction[6]; - unsigned char to_read; /* length to read. 0 means no reply requested */ -}; - -/* How to change the resolution of any of the VGA cams is unknown */ -static const struct v4l2_pix_format vga_mode[] = { - {640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 4, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; - -/* No way to change the resolution of the CIF cams is known */ -static const struct v4l2_pix_format cif_mode[] = { - {352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 3 / 4, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; - -/* the bytes to write are in gspca_dev->usb_buf */ -static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command) -{ - int rc; - - PDEBUG(D_USBO, "sending command %02x%02x%02x%02x%02x%02x", command[0], - command[1], command[2], command[3], command[4], command[5]); - - memcpy(gspca_dev->usb_buf, command, 6); - rc = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - USB_REQ_GET_CONFIGURATION, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 2, 0, gspca_dev->usb_buf, 6, 500); - if (rc < 0) { - pr_err("command write [%02x] error %d\n", - gspca_dev->usb_buf[0], rc); - return rc; - } - - return 0; -} - -static int sn9c2028_read1(struct gspca_dev *gspca_dev) -{ - int rc; - - rc = usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - USB_REQ_GET_STATUS, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 1, 0, gspca_dev->usb_buf, 1, 500); - if (rc != 1) { - pr_err("read1 error %d\n", rc); - return (rc < 0) ? rc : -EIO; - } - PDEBUG(D_USBI, "read1 response %02x", gspca_dev->usb_buf[0]); - return gspca_dev->usb_buf[0]; -} - -static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading) -{ - int rc; - rc = usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - USB_REQ_GET_STATUS, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 4, 0, gspca_dev->usb_buf, 4, 500); - if (rc != 4) { - pr_err("read4 error %d\n", rc); - return (rc < 0) ? rc : -EIO; - } - memcpy(reading, gspca_dev->usb_buf, 4); - PDEBUG(D_USBI, "read4 response %02x%02x%02x%02x", reading[0], - reading[1], reading[2], reading[3]); - return rc; -} - -static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command) -{ - int i, status; - __u8 reading[4]; - - status = sn9c2028_command(gspca_dev, command); - if (status < 0) - return status; - - status = -1; - for (i = 0; i < 256 && status < 2; i++) - status = sn9c2028_read1(gspca_dev); - if (status != 2) { - pr_err("long command status read error %d\n", status); - return (status < 0) ? status : -EIO; - } - - memset(reading, 0, 4); - status = sn9c2028_read4(gspca_dev, reading); - if (status < 0) - return status; - - /* in general, the first byte of the response is the first byte of - * the command, or'ed with 8 */ - status = sn9c2028_read1(gspca_dev); - if (status < 0) - return status; - - return 0; -} - -static int sn9c2028_short_command(struct gspca_dev *gspca_dev, u8 *command) -{ - int err_code; - - err_code = sn9c2028_command(gspca_dev, command); - if (err_code < 0) - return err_code; - - err_code = sn9c2028_read1(gspca_dev); - if (err_code < 0) - return err_code; - - return 0; -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam = &gspca_dev->cam; - - PDEBUG(D_PROBE, "SN9C2028 camera detected (vid/pid 0x%04X:0x%04X)", - id->idVendor, id->idProduct); - - sd->model = id->idProduct; - - switch (sd->model) { - case 0x7005: - PDEBUG(D_PROBE, "Genius Smart 300 camera"); - break; - case 0x8000: - PDEBUG(D_PROBE, "DC31VC"); - break; - case 0x8001: - PDEBUG(D_PROBE, "Spy camera"); - break; - case 0x8003: - PDEBUG(D_PROBE, "CIF camera"); - break; - case 0x8008: - PDEBUG(D_PROBE, "Mini-Shotz ms-350 camera"); - break; - case 0x800a: - PDEBUG(D_PROBE, "Vivitar 3350b type camera"); - cam->input_flags = V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP; - break; - } - - switch (sd->model) { - case 0x8000: - case 0x8001: - case 0x8003: - cam->cam_mode = cif_mode; - cam->nmodes = ARRAY_SIZE(cif_mode); - break; - default: - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - } - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - int status = -1; - - sn9c2028_read1(gspca_dev); - sn9c2028_read1(gspca_dev); - status = sn9c2028_read1(gspca_dev); - - return (status < 0) ? status : 0; -} - -static int run_start_commands(struct gspca_dev *gspca_dev, - struct init_command *cam_commands, int n) -{ - int i, err_code = -1; - - for (i = 0; i < n; i++) { - switch (cam_commands[i].to_read) { - case 4: - err_code = sn9c2028_long_command(gspca_dev, - cam_commands[i].instruction); - break; - case 1: - err_code = sn9c2028_short_command(gspca_dev, - cam_commands[i].instruction); - break; - case 0: - err_code = sn9c2028_command(gspca_dev, - cam_commands[i].instruction); - break; - } - if (err_code < 0) - return err_code; - } - return 0; -} - -static int start_spy_cam(struct gspca_dev *gspca_dev) -{ - struct init_command spy_start_commands[] = { - {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4}, - {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4}, - {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, /* width 352 */ - {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, /* height 288 */ - /* {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, */ - {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, - {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* red gain ?*/ - /* {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, */ - {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4}, - /* {{0x13, 0x29, 0x01, 0x0c, 0x00, 0x00}, 4}, */ - {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, - /* {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, */ - {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, - {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, - /* {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, */ - {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, - {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, - {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, - {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x02, 0x06, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x03, 0x13, 0x00, 0x00, 0x00}, 4}, /*don't mess with*/ - /*{{0x11, 0x04, 0x06, 0x00, 0x00, 0x00}, 4}, observed */ - {{0x11, 0x04, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */ - /*{{0x11, 0x05, 0x65, 0x00, 0x00, 0x00}, 4}, observed */ - {{0x11, 0x05, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */ - {{0x11, 0x06, 0xb1, 0x00, 0x00, 0x00}, 4}, /* observed */ - {{0x11, 0x07, 0x00, 0x00, 0x00, 0x00}, 4}, - /*{{0x11, 0x08, 0x06, 0x00, 0x00, 0x00}, 4}, observed */ - {{0x11, 0x08, 0x0b, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x09, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x0a, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x0c, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x0d, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x0e, 0x04, 0x00, 0x00, 0x00}, 4}, - /* {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, */ - /* brightness or gain. 0 is default. 4 is good - * indoors at night with incandescent lighting */ - {{0x11, 0x0f, 0x04, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x10, 0x06, 0x00, 0x00, 0x00}, 4}, /*hstart or hoffs*/ - {{0x11, 0x11, 0x06, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x14, 0x02, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x13, 0x01, 0x00, 0x00, 0x00}, 4}, - /* {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, observed */ - {{0x1b, 0x02, 0x11, 0x00, 0x00, 0x00}, 1}, /* brighter */ - /* {{0x1b, 0x13, 0x01, 0x00, 0x00, 0x00}, 1}, observed */ - {{0x1b, 0x13, 0x11, 0x00, 0x00, 0x00}, 1}, - {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}, /* compresses */ - /* Camera should start to capture now. */ - }; - - return run_start_commands(gspca_dev, spy_start_commands, - ARRAY_SIZE(spy_start_commands)); -} - -static int start_cif_cam(struct gspca_dev *gspca_dev) -{ - struct init_command cif_start_commands[] = { - {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, - /* The entire sequence below seems redundant */ - /* {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x22, 0x01, 0x06, 0x00, 0x00}, 4}, - {{0x13, 0x23, 0x01, 0x02, 0x00, 0x00}, 4}, - {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, width? - {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, height? - {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample? - {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4}, - {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, - {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, - {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, - {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, - {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, - {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},*/ - {{0x1b, 0x21, 0x00, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x17, 0x00, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x19, 0x00, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x03, 0x5a, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x04, 0x27, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x05, 0x01, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x12, 0x14, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x14, 0x00, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x15, 0x00, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x16, 0x00, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x77, 0xa2, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x06, 0x0f, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x07, 0x14, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x08, 0x0f, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x09, 0x10, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x12, 0x07, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x10, 0x1f, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, - {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 1}, /* width/8 */ - {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 1}, /* height/8 */ - /* {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample? - * {{0x13, 0x28, 0x01, 0x1e, 0x00, 0x00}, 4}, does nothing - * {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, */ - /* {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, - * causes subsampling - * but not a change in the resolution setting! */ - {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, - {{0x13, 0x2d, 0x01, 0x01, 0x00, 0x00}, 4}, - {{0x13, 0x2e, 0x01, 0x08, 0x00, 0x00}, 4}, - {{0x13, 0x2f, 0x01, 0x06, 0x00, 0x00}, 4}, - {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x1b, 0x04, 0x6d, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x05, 0x03, 0x00, 0x00, 0x00}, 1}, - {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x0e, 0x01, 0x00, 0x00, 0x00}, 1}, - {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1}, - {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x10, 0x0f, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, - {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1},/* use compression */ - /* Camera should start to capture now. */ - }; - - return run_start_commands(gspca_dev, cif_start_commands, - ARRAY_SIZE(cif_start_commands)); -} - -static int start_ms350_cam(struct gspca_dev *gspca_dev) -{ - struct init_command ms350_start_commands[] = { - {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4}, - {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4}, - {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, - {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, - {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, - {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, - {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, - {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, - {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, - {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, - {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, - {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x00, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x01, 0x70, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x02, 0x05, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x03, 0x5d, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x04, 0x07, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x05, 0x25, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x06, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x07, 0x09, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x08, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x09, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x0c, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x0d, 0x0c, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x0e, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x11, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x13, 0x63, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x15, 0x70, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x18, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x11, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* width */ - {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* height */ - {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* vstart? */ - {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, - {{0x13, 0x29, 0x01, 0x40, 0x00, 0x00}, 4}, /* hstart? */ - {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, - {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, - {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, - {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, - {{0x1b, 0x02, 0x05, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, - {{0x20, 0x18, 0x00, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x02, 0x0a, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 0}, - /* Camera should start to capture now. */ - }; - - return run_start_commands(gspca_dev, ms350_start_commands, - ARRAY_SIZE(ms350_start_commands)); -} - -static int start_genius_cam(struct gspca_dev *gspca_dev) -{ - struct init_command genius_start_commands[] = { - {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, - {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, - /* "preliminary" width and height settings */ - {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, - {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, - {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, - {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, - {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, - {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, - {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, - {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* real width */ - {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* real height */ - {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, - {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, - {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4}, - {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, - {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, - {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, - {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, - {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4}, - {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4}, - {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1}, - {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1}, - {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0} - /* Camera should start to capture now. */ - }; - - return run_start_commands(gspca_dev, genius_start_commands, - ARRAY_SIZE(genius_start_commands)); -} - -static int start_vivitar_cam(struct gspca_dev *gspca_dev) -{ - struct init_command vivitar_start_commands[] = { - {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x22, 0x01, 0x01, 0x00, 0x00}, 4}, - {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4}, - {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, - {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, - {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, - {{0x13, 0x28, 0x01, 0x0a, 0x00, 0x00}, 4}, - /* - * Above is changed from OEM 0x0b. Fixes Bayer tiling. - * Presumably gives a vertical shift of one row. - */ - {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4}, - /* Above seems to do horizontal shift. */ - {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, - {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, - {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, - {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, - /* Above three commands seem to relate to brightness. */ - {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, - {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x1b, 0x12, 0x80, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x01, 0x77, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x02, 0x3a, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x12, 0x78, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x14, 0x80, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x15, 0x34, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x1b, 0x04, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x20, 0x44, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x23, 0xee, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x26, 0xa0, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x27, 0x9a, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x28, 0xa0, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x29, 0x30, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x2b, 0x00, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x2f, 0x3d, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x30, 0x24, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x32, 0x86, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x60, 0xa9, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x61, 0x42, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x65, 0x00, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x69, 0x38, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x6f, 0x88, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x70, 0x0b, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x71, 0x00, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x74, 0x21, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x75, 0x86, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x76, 0x00, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x7d, 0xf3, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x17, 0x1c, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x18, 0xc0, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x19, 0x05, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x1a, 0xf6, 0x00, 0x00, 0x00}, 1}, - /* {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, - {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, - {{0x13, 0x28, 0x01, 0x0b, 0x00, 0x00}, 4}, */ - {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x10, 0x26, 0x00, 0x00, 0x00}, 1}, - {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x1b, 0x76, 0x03, 0x00, 0x00, 0x00}, 1}, - {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1}, - {{0x1b, 0x00, 0x3f, 0x00, 0x00, 0x00}, 1}, - /* Above is brightness; OEM driver setting is 0x10 */ - {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, - {{0x20, 0x29, 0x30, 0x00, 0x00, 0x00}, 1}, - {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1} - }; - - return run_start_commands(gspca_dev, vivitar_start_commands, - ARRAY_SIZE(vivitar_start_commands)); -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int err_code; - - sd->sof_read = 0; - - switch (sd->model) { - case 0x7005: - err_code = start_genius_cam(gspca_dev); - break; - case 0x8001: - err_code = start_spy_cam(gspca_dev); - break; - case 0x8003: - err_code = start_cif_cam(gspca_dev); - break; - case 0x8008: - err_code = start_ms350_cam(gspca_dev); - break; - case 0x800a: - err_code = start_vivitar_cam(gspca_dev); - break; - default: - pr_err("Starting unknown camera, please report this\n"); - return -ENXIO; - } - - return err_code; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - int result; - __u8 data[6]; - - result = sn9c2028_read1(gspca_dev); - if (result < 0) - PDEBUG(D_ERR, "Camera Stop read failed"); - - memset(data, 0, 6); - data[0] = 0x14; - result = sn9c2028_command(gspca_dev, data); - if (result < 0) - PDEBUG(D_ERR, "Camera Stop command failed"); -} - -/* Include sn9c2028 sof detection functions */ -#include "sn9c2028.h" - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - __u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - unsigned char *sof; - - sof = sn9c2028_find_sof(gspca_dev, data, len); - if (sof) { - int n; - - /* finish decoding current frame */ - n = sof - data; - if (n > sizeof sn9c2028_sof_marker) - n -= sizeof sn9c2028_sof_marker; - else - n = 0; - gspca_frame_add(gspca_dev, LAST_PACKET, data, n); - /* Start next frame. */ - gspca_frame_add(gspca_dev, FIRST_PACKET, - sn9c2028_sof_marker, sizeof sn9c2028_sof_marker); - len -= sof - data; - data = sof; - } - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */ - /* The Genius Smart is untested. I can't find an owner ! */ - /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */ - {USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */ - {USB_DEVICE(0x0c45, 0x8003)}, /* Several small CIF cameras */ - /* {USB_DEVICE(0x0c45, 0x8006)}, Unknown VGA camera */ - {USB_DEVICE(0x0c45, 0x8008)}, /* Mini-Shotz ms-350 */ - {USB_DEVICE(0x0c45, 0x800a)}, /* Vivicam 3350B */ - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/sn9c2028.h b/drivers/media/video/gspca/sn9c2028.h deleted file mode 100644 index 8fd1d3e05665..000000000000 --- a/drivers/media/video/gspca/sn9c2028.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SN9C2028 common functions - * - * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn,edu> - * - * Based closely upon the file gspca/pac_common.h - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -static const unsigned char sn9c2028_sof_marker[5] = - { 0xff, 0xff, 0x00, 0xc4, 0xc4 }; - -static unsigned char *sn9c2028_find_sof(struct gspca_dev *gspca_dev, - unsigned char *m, int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i; - - /* Search for the SOF marker (fixed part) in the header */ - for (i = 0; i < len; i++) { - if (m[i] == sn9c2028_sof_marker[sd->sof_read]) { - sd->sof_read++; - if (sd->sof_read == sizeof(sn9c2028_sof_marker)) { - PDEBUG(D_FRAM, - "SOF found, bytes to analyze: %u." - " Frame starts at byte #%u", - len, i + 1); - sd->sof_read = 0; - return m + i + 1; - } - } else { - sd->sof_read = 0; - } - } - - return NULL; -} diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c deleted file mode 100644 index b9c6f17eabb2..000000000000 --- a/drivers/media/video/gspca/sn9c20x.c +++ /dev/null @@ -1,2428 +0,0 @@ -/* - * Sonix sn9c201 sn9c202 library - * - * Copyright (C) 2012 Jean-Francois Moine <http://moinejf.free.fr> - * Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com> - * Copyright (C) 2009 Brian Johnson <brijohn@gmail.com> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/input.h> - -#include "gspca.h" -#include "jpeg.h" - -#include <media/v4l2-chip-ident.h> -#include <linux/dmi.h> - -MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, " - "microdia project <microdia@googlegroups.com>"); -MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* - * Pixel format private data - */ -#define SCALE_MASK 0x0f -#define SCALE_160x120 0 -#define SCALE_320x240 1 -#define SCALE_640x480 2 -#define SCALE_1280x1024 3 -#define MODE_RAW 0x10 -#define MODE_JPEG 0x20 -#define MODE_SXGA 0x80 - -#define SENSOR_OV9650 0 -#define SENSOR_OV9655 1 -#define SENSOR_SOI968 2 -#define SENSOR_OV7660 3 -#define SENSOR_OV7670 4 -#define SENSOR_MT9V011 5 -#define SENSOR_MT9V111 6 -#define SENSOR_MT9V112 7 -#define SENSOR_MT9M001 8 -#define SENSOR_MT9M111 9 -#define SENSOR_MT9M112 10 -#define SENSOR_HV7131R 11 -#define SENSOR_MT9VPRB 12 - -/* camera flags */ -#define HAS_NO_BUTTON 0x1 -#define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */ -#define FLIP_DETECT 0x4 - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; - - struct { /* color control cluster */ - struct v4l2_ctrl *brightness; - struct v4l2_ctrl *contrast; - struct v4l2_ctrl *saturation; - struct v4l2_ctrl *hue; - }; - struct { /* blue/red balance control cluster */ - struct v4l2_ctrl *blue; - struct v4l2_ctrl *red; - }; - struct { /* h/vflip control cluster */ - struct v4l2_ctrl *hflip; - struct v4l2_ctrl *vflip; - }; - struct v4l2_ctrl *gamma; - struct { /* autogain and exposure or gain control cluster */ - struct v4l2_ctrl *autogain; - struct v4l2_ctrl *exposure; - struct v4l2_ctrl *gain; - }; - struct v4l2_ctrl *jpegqual; - - struct work_struct work; - struct workqueue_struct *work_thread; - - u32 pktsz; /* (used by pkt_scan) */ - u16 npkt; - s8 nchg; - u8 fmt; /* (used for JPEG QTAB update */ - -#define MIN_AVG_LUM 80 -#define MAX_AVG_LUM 130 - atomic_t avg_lum; - u8 old_step; - u8 older_step; - u8 exposure_step; - - u8 i2c_addr; - u8 i2c_intf; - u8 sensor; - u8 hstart; - u8 vstart; - - u8 jpeg_hdr[JPEG_HDR_SZ]; - - u8 flags; -}; - -static void qual_upd(struct work_struct *work); - -struct i2c_reg_u8 { - u8 reg; - u8 val; -}; - -struct i2c_reg_u16 { - u8 reg; - u16 val; -}; - -static const struct dmi_system_id flip_dmi_table[] = { - { - .ident = "MSI MS-1034", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."), - DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"), - DMI_MATCH(DMI_PRODUCT_VERSION, "0341") - } - }, - { - .ident = "MSI MS-1632", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), - DMI_MATCH(DMI_BOARD_NAME, "MS-1632") - } - }, - { - .ident = "MSI MS-1633X", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), - DMI_MATCH(DMI_BOARD_NAME, "MS-1633X") - } - }, - { - .ident = "MSI MS-1635X", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), - DMI_MATCH(DMI_BOARD_NAME, "MS-1635X") - } - }, - { - .ident = "ASUSTeK W7J", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_BOARD_NAME, "W7J ") - } - }, - {} -}; - -static const struct v4l2_pix_format vga_mode[] = { - {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120 * 4 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = SCALE_160x120 | MODE_JPEG}, - {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_160x120 | MODE_RAW}, - {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 240 * 120, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_160x120}, - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 4 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = SCALE_320x240 | MODE_JPEG}, - {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 , - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_320x240 | MODE_RAW}, - {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 480 * 240 , - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_320x240}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 4 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = SCALE_640x480 | MODE_JPEG}, - {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_640x480 | MODE_RAW}, - {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 960 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_640x480}, -}; - -static const struct v4l2_pix_format sxga_mode[] = { - {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120 * 4 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = SCALE_160x120 | MODE_JPEG}, - {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_160x120 | MODE_RAW}, - {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 240 * 120, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_160x120}, - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 4 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = SCALE_320x240 | MODE_JPEG}, - {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 , - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_320x240 | MODE_RAW}, - {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 480 * 240 , - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_320x240}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 4 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = SCALE_640x480 | MODE_JPEG}, - {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_640x480 | MODE_RAW}, - {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 960 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_640x480}, - {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 1280, - .sizeimage = 1280 * 1024, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA}, -}; - -static const struct v4l2_pix_format mono_mode[] = { - {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_160x120 | MODE_RAW}, - {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 , - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_320x240 | MODE_RAW}, - {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_640x480 | MODE_RAW}, - {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE, - .bytesperline = 1280, - .sizeimage = 1280 * 1024, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA}, -}; - -static const s16 hsv_red_x[] = { - 41, 44, 46, 48, 50, 52, 54, 56, - 58, 60, 62, 64, 66, 68, 70, 72, - 74, 76, 78, 80, 81, 83, 85, 87, - 88, 90, 92, 93, 95, 97, 98, 100, - 101, 102, 104, 105, 107, 108, 109, 110, - 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 123, 124, 125, 125, - 126, 127, 127, 128, 128, 129, 129, 129, - 130, 130, 130, 130, 131, 131, 131, 131, - 131, 131, 131, 131, 130, 130, 130, 130, - 129, 129, 129, 128, 128, 127, 127, 126, - 125, 125, 124, 123, 122, 122, 121, 120, - 119, 118, 117, 116, 115, 114, 112, 111, - 110, 109, 107, 106, 105, 103, 102, 101, - 99, 98, 96, 94, 93, 91, 90, 88, - 86, 84, 83, 81, 79, 77, 75, 74, - 72, 70, 68, 66, 64, 62, 60, 58, - 56, 54, 52, 49, 47, 45, 43, 41, - 39, 36, 34, 32, 30, 28, 25, 23, - 21, 19, 16, 14, 12, 9, 7, 5, - 3, 0, -1, -3, -6, -8, -10, -12, - -15, -17, -19, -22, -24, -26, -28, -30, - -33, -35, -37, -39, -41, -44, -46, -48, - -50, -52, -54, -56, -58, -60, -62, -64, - -66, -68, -70, -72, -74, -76, -78, -80, - -81, -83, -85, -87, -88, -90, -92, -93, - -95, -97, -98, -100, -101, -102, -104, -105, - -107, -108, -109, -110, -112, -113, -114, -115, - -116, -117, -118, -119, -120, -121, -122, -123, - -123, -124, -125, -125, -126, -127, -127, -128, - -128, -128, -128, -128, -128, -128, -128, -128, - -128, -128, -128, -128, -128, -128, -128, -128, - -128, -128, -128, -128, -128, -128, -128, -128, - -128, -127, -127, -126, -125, -125, -124, -123, - -122, -122, -121, -120, -119, -118, -117, -116, - -115, -114, -112, -111, -110, -109, -107, -106, - -105, -103, -102, -101, -99, -98, -96, -94, - -93, -91, -90, -88, -86, -84, -83, -81, - -79, -77, -75, -74, -72, -70, -68, -66, - -64, -62, -60, -58, -56, -54, -52, -49, - -47, -45, -43, -41, -39, -36, -34, -32, - -30, -28, -25, -23, -21, -19, -16, -14, - -12, -9, -7, -5, -3, 0, 1, 3, - 6, 8, 10, 12, 15, 17, 19, 22, - 24, 26, 28, 30, 33, 35, 37, 39, 41 -}; - -static const s16 hsv_red_y[] = { - 82, 80, 78, 76, 74, 73, 71, 69, - 67, 65, 63, 61, 58, 56, 54, 52, - 50, 48, 46, 44, 41, 39, 37, 35, - 32, 30, 28, 26, 23, 21, 19, 16, - 14, 12, 10, 7, 5, 3, 0, -1, - -3, -6, -8, -10, -13, -15, -17, -19, - -22, -24, -26, -29, -31, -33, -35, -38, - -40, -42, -44, -46, -48, -51, -53, -55, - -57, -59, -61, -63, -65, -67, -69, -71, - -73, -75, -77, -79, -81, -82, -84, -86, - -88, -89, -91, -93, -94, -96, -98, -99, - -101, -102, -104, -105, -106, -108, -109, -110, - -112, -113, -114, -115, -116, -117, -119, -120, - -120, -121, -122, -123, -124, -125, -126, -126, - -127, -128, -128, -128, -128, -128, -128, -128, - -128, -128, -128, -128, -128, -128, -128, -128, - -128, -128, -128, -128, -128, -128, -128, -128, - -128, -128, -128, -128, -128, -128, -128, -128, - -127, -127, -126, -125, -125, -124, -123, -122, - -121, -120, -119, -118, -117, -116, -115, -114, - -113, -111, -110, -109, -107, -106, -105, -103, - -102, -100, -99, -97, -96, -94, -92, -91, - -89, -87, -85, -84, -82, -80, -78, -76, - -74, -73, -71, -69, -67, -65, -63, -61, - -58, -56, -54, -52, -50, -48, -46, -44, - -41, -39, -37, -35, -32, -30, -28, -26, - -23, -21, -19, -16, -14, -12, -10, -7, - -5, -3, 0, 1, 3, 6, 8, 10, - 13, 15, 17, 19, 22, 24, 26, 29, - 31, 33, 35, 38, 40, 42, 44, 46, - 48, 51, 53, 55, 57, 59, 61, 63, - 65, 67, 69, 71, 73, 75, 77, 79, - 81, 82, 84, 86, 88, 89, 91, 93, - 94, 96, 98, 99, 101, 102, 104, 105, - 106, 108, 109, 110, 112, 113, 114, 115, - 116, 117, 119, 120, 120, 121, 122, 123, - 124, 125, 126, 126, 127, 128, 128, 129, - 129, 130, 130, 131, 131, 131, 131, 132, - 132, 132, 132, 132, 132, 132, 132, 132, - 132, 132, 132, 131, 131, 131, 130, 130, - 130, 129, 129, 128, 127, 127, 126, 125, - 125, 124, 123, 122, 121, 120, 119, 118, - 117, 116, 115, 114, 113, 111, 110, 109, - 107, 106, 105, 103, 102, 100, 99, 97, - 96, 94, 92, 91, 89, 87, 85, 84, 82 -}; - -static const s16 hsv_green_x[] = { - -124, -124, -125, -125, -125, -125, -125, -125, - -125, -126, -126, -125, -125, -125, -125, -125, - -125, -124, -124, -124, -123, -123, -122, -122, - -121, -121, -120, -120, -119, -118, -117, -117, - -116, -115, -114, -113, -112, -111, -110, -109, - -108, -107, -105, -104, -103, -102, -100, -99, - -98, -96, -95, -93, -92, -91, -89, -87, - -86, -84, -83, -81, -79, -77, -76, -74, - -72, -70, -69, -67, -65, -63, -61, -59, - -57, -55, -53, -51, -49, -47, -45, -43, - -41, -39, -37, -35, -33, -30, -28, -26, - -24, -22, -20, -18, -15, -13, -11, -9, - -7, -4, -2, 0, 1, 3, 6, 8, - 10, 12, 14, 17, 19, 21, 23, 25, - 27, 29, 32, 34, 36, 38, 40, 42, - 44, 46, 48, 50, 52, 54, 56, 58, - 60, 62, 64, 66, 68, 70, 71, 73, - 75, 77, 78, 80, 82, 83, 85, 87, - 88, 90, 91, 93, 94, 96, 97, 98, - 100, 101, 102, 104, 105, 106, 107, 108, - 109, 111, 112, 113, 113, 114, 115, 116, - 117, 118, 118, 119, 120, 120, 121, 122, - 122, 123, 123, 124, 124, 124, 125, 125, - 125, 125, 125, 125, 125, 126, 126, 125, - 125, 125, 125, 125, 125, 124, 124, 124, - 123, 123, 122, 122, 121, 121, 120, 120, - 119, 118, 117, 117, 116, 115, 114, 113, - 112, 111, 110, 109, 108, 107, 105, 104, - 103, 102, 100, 99, 98, 96, 95, 93, - 92, 91, 89, 87, 86, 84, 83, 81, - 79, 77, 76, 74, 72, 70, 69, 67, - 65, 63, 61, 59, 57, 55, 53, 51, - 49, 47, 45, 43, 41, 39, 37, 35, - 33, 30, 28, 26, 24, 22, 20, 18, - 15, 13, 11, 9, 7, 4, 2, 0, - -1, -3, -6, -8, -10, -12, -14, -17, - -19, -21, -23, -25, -27, -29, -32, -34, - -36, -38, -40, -42, -44, -46, -48, -50, - -52, -54, -56, -58, -60, -62, -64, -66, - -68, -70, -71, -73, -75, -77, -78, -80, - -82, -83, -85, -87, -88, -90, -91, -93, - -94, -96, -97, -98, -100, -101, -102, -104, - -105, -106, -107, -108, -109, -111, -112, -113, - -113, -114, -115, -116, -117, -118, -118, -119, - -120, -120, -121, -122, -122, -123, -123, -124, -124 -}; - -static const s16 hsv_green_y[] = { - -100, -99, -98, -97, -95, -94, -93, -91, - -90, -89, -87, -86, -84, -83, -81, -80, - -78, -76, -75, -73, -71, -70, -68, -66, - -64, -63, -61, -59, -57, -55, -53, -51, - -49, -48, -46, -44, -42, -40, -38, -36, - -34, -32, -30, -27, -25, -23, -21, -19, - -17, -15, -13, -11, -9, -7, -4, -2, - 0, 1, 3, 5, 7, 9, 11, 14, - 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, - 48, 50, 52, 54, 56, 58, 59, 61, - 63, 65, 67, 68, 70, 72, 74, 75, - 77, 78, 80, 82, 83, 85, 86, 88, - 89, 90, 92, 93, 95, 96, 97, 98, - 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 112, 113, 114, - 115, 115, 116, 116, 117, 117, 118, 118, - 119, 119, 119, 120, 120, 120, 120, 120, - 121, 121, 121, 121, 121, 121, 120, 120, - 120, 120, 120, 119, 119, 119, 118, 118, - 117, 117, 116, 116, 115, 114, 114, 113, - 112, 111, 111, 110, 109, 108, 107, 106, - 105, 104, 103, 102, 100, 99, 98, 97, - 95, 94, 93, 91, 90, 89, 87, 86, - 84, 83, 81, 80, 78, 76, 75, 73, - 71, 70, 68, 66, 64, 63, 61, 59, - 57, 55, 53, 51, 49, 48, 46, 44, - 42, 40, 38, 36, 34, 32, 30, 27, - 25, 23, 21, 19, 17, 15, 13, 11, - 9, 7, 4, 2, 0, -1, -3, -5, - -7, -9, -11, -14, -16, -18, -20, -22, - -24, -26, -28, -30, -32, -34, -36, -38, - -40, -42, -44, -46, -48, -50, -52, -54, - -56, -58, -59, -61, -63, -65, -67, -68, - -70, -72, -74, -75, -77, -78, -80, -82, - -83, -85, -86, -88, -89, -90, -92, -93, - -95, -96, -97, -98, -100, -101, -102, -103, - -104, -105, -106, -107, -108, -109, -110, -111, - -112, -112, -113, -114, -115, -115, -116, -116, - -117, -117, -118, -118, -119, -119, -119, -120, - -120, -120, -120, -120, -121, -121, -121, -121, - -121, -121, -120, -120, -120, -120, -120, -119, - -119, -119, -118, -118, -117, -117, -116, -116, - -115, -114, -114, -113, -112, -111, -111, -110, - -109, -108, -107, -106, -105, -104, -103, -102, -100 -}; - -static const s16 hsv_blue_x[] = { - 112, 113, 114, 114, 115, 116, 117, 117, - 118, 118, 119, 119, 120, 120, 120, 121, - 121, 121, 122, 122, 122, 122, 122, 122, - 122, 122, 122, 122, 122, 122, 121, 121, - 121, 120, 120, 120, 119, 119, 118, 118, - 117, 116, 116, 115, 114, 113, 113, 112, - 111, 110, 109, 108, 107, 106, 105, 104, - 103, 102, 100, 99, 98, 97, 95, 94, - 93, 91, 90, 88, 87, 85, 84, 82, - 80, 79, 77, 76, 74, 72, 70, 69, - 67, 65, 63, 61, 60, 58, 56, 54, - 52, 50, 48, 46, 44, 42, 40, 38, - 36, 34, 32, 30, 28, 26, 24, 22, - 19, 17, 15, 13, 11, 9, 7, 5, - 2, 0, -1, -3, -5, -7, -9, -12, - -14, -16, -18, -20, -22, -24, -26, -28, - -31, -33, -35, -37, -39, -41, -43, -45, - -47, -49, -51, -53, -54, -56, -58, -60, - -62, -64, -66, -67, -69, -71, -73, -74, - -76, -78, -79, -81, -83, -84, -86, -87, - -89, -90, -92, -93, -94, -96, -97, -98, - -99, -101, -102, -103, -104, -105, -106, -107, - -108, -109, -110, -111, -112, -113, -114, -114, - -115, -116, -117, -117, -118, -118, -119, -119, - -120, -120, -120, -121, -121, -121, -122, -122, - -122, -122, -122, -122, -122, -122, -122, -122, - -122, -122, -121, -121, -121, -120, -120, -120, - -119, -119, -118, -118, -117, -116, -116, -115, - -114, -113, -113, -112, -111, -110, -109, -108, - -107, -106, -105, -104, -103, -102, -100, -99, - -98, -97, -95, -94, -93, -91, -90, -88, - -87, -85, -84, -82, -80, -79, -77, -76, - -74, -72, -70, -69, -67, -65, -63, -61, - -60, -58, -56, -54, -52, -50, -48, -46, - -44, -42, -40, -38, -36, -34, -32, -30, - -28, -26, -24, -22, -19, -17, -15, -13, - -11, -9, -7, -5, -2, 0, 1, 3, - 5, 7, 9, 12, 14, 16, 18, 20, - 22, 24, 26, 28, 31, 33, 35, 37, - 39, 41, 43, 45, 47, 49, 51, 53, - 54, 56, 58, 60, 62, 64, 66, 67, - 69, 71, 73, 74, 76, 78, 79, 81, - 83, 84, 86, 87, 89, 90, 92, 93, - 94, 96, 97, 98, 99, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112 -}; - -static const s16 hsv_blue_y[] = { - -11, -13, -15, -17, -19, -21, -23, -25, - -27, -29, -31, -33, -35, -37, -39, -41, - -43, -45, -46, -48, -50, -52, -54, -55, - -57, -59, -61, -62, -64, -66, -67, -69, - -71, -72, -74, -75, -77, -78, -80, -81, - -83, -84, -86, -87, -88, -90, -91, -92, - -93, -95, -96, -97, -98, -99, -100, -101, - -102, -103, -104, -105, -106, -106, -107, -108, - -109, -109, -110, -111, -111, -112, -112, -113, - -113, -114, -114, -114, -115, -115, -115, -115, - -116, -116, -116, -116, -116, -116, -116, -116, - -116, -115, -115, -115, -115, -114, -114, -114, - -113, -113, -112, -112, -111, -111, -110, -110, - -109, -108, -108, -107, -106, -105, -104, -103, - -102, -101, -100, -99, -98, -97, -96, -95, - -94, -93, -91, -90, -89, -88, -86, -85, - -84, -82, -81, -79, -78, -76, -75, -73, - -71, -70, -68, -67, -65, -63, -62, -60, - -58, -56, -55, -53, -51, -49, -47, -45, - -44, -42, -40, -38, -36, -34, -32, -30, - -28, -26, -24, -22, -20, -18, -16, -14, - -12, -10, -8, -6, -4, -2, 0, 1, - 3, 5, 7, 9, 11, 13, 15, 17, - 19, 21, 23, 25, 27, 29, 31, 33, - 35, 37, 39, 41, 43, 45, 46, 48, - 50, 52, 54, 55, 57, 59, 61, 62, - 64, 66, 67, 69, 71, 72, 74, 75, - 77, 78, 80, 81, 83, 84, 86, 87, - 88, 90, 91, 92, 93, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, - 106, 106, 107, 108, 109, 109, 110, 111, - 111, 112, 112, 113, 113, 114, 114, 114, - 115, 115, 115, 115, 116, 116, 116, 116, - 116, 116, 116, 116, 116, 115, 115, 115, - 115, 114, 114, 114, 113, 113, 112, 112, - 111, 111, 110, 110, 109, 108, 108, 107, - 106, 105, 104, 103, 102, 101, 100, 99, - 98, 97, 96, 95, 94, 93, 91, 90, - 89, 88, 86, 85, 84, 82, 81, 79, - 78, 76, 75, 73, 71, 70, 68, 67, - 65, 63, 62, 60, 58, 56, 55, 53, - 51, 49, 47, 45, 44, 42, 40, 38, - 36, 34, 32, 30, 28, 26, 24, 22, - 20, 18, 16, 14, 12, 10, 8, 6, - 4, 2, 0, -1, -3, -5, -7, -9, -11 -}; - -static const u16 i2c_ident[] = { - V4L2_IDENT_OV9650, - V4L2_IDENT_OV9655, - V4L2_IDENT_SOI968, - V4L2_IDENT_OV7660, - V4L2_IDENT_OV7670, - V4L2_IDENT_MT9V011, - V4L2_IDENT_MT9V111, - V4L2_IDENT_MT9V112, - V4L2_IDENT_MT9M001C12ST, - V4L2_IDENT_MT9M111, - V4L2_IDENT_MT9M112, - V4L2_IDENT_HV7131R, -[SENSOR_MT9VPRB] = V4L2_IDENT_UNKNOWN, -}; - -static const u16 bridge_init[][2] = { - {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c}, - {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40}, - {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10}, - {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00}, - {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50}, - {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50}, - {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04}, - {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05}, - {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00}, - {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d}, - {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04}, - {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8}, - {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32}, - {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd}, - {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01}, - {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f}, - {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f}, - {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01}, - {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80}, - {0x1007, 0x00} -}; - -/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */ -static const u8 ov_gain[] = { - 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */, - 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */, - 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */, - 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */, - 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */, - 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */, - 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */, - 0x70 /* 8x */ -}; - -/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */ -static const u16 micron1_gain[] = { - /* 1x 1.25x 1.5x 1.75x */ - 0x0020, 0x0028, 0x0030, 0x0038, - /* 2x 2.25x 2.5x 2.75x */ - 0x00a0, 0x00a4, 0x00a8, 0x00ac, - /* 3x 3.25x 3.5x 3.75x */ - 0x00b0, 0x00b4, 0x00b8, 0x00bc, - /* 4x 4.25x 4.5x 4.75x */ - 0x00c0, 0x00c4, 0x00c8, 0x00cc, - /* 5x 5.25x 5.5x 5.75x */ - 0x00d0, 0x00d4, 0x00d8, 0x00dc, - /* 6x 6.25x 6.5x 6.75x */ - 0x00e0, 0x00e4, 0x00e8, 0x00ec, - /* 7x 7.25x 7.5x 7.75x */ - 0x00f0, 0x00f4, 0x00f8, 0x00fc, - /* 8x */ - 0x01c0 -}; - -/* mt9m001 sensor uses a different gain formula then other micron sensors */ -/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */ -static const u16 micron2_gain[] = { - /* 1x 1.25x 1.5x 1.75x */ - 0x0008, 0x000a, 0x000c, 0x000e, - /* 2x 2.25x 2.5x 2.75x */ - 0x0010, 0x0012, 0x0014, 0x0016, - /* 3x 3.25x 3.5x 3.75x */ - 0x0018, 0x001a, 0x001c, 0x001e, - /* 4x 4.25x 4.5x 4.75x */ - 0x0020, 0x0051, 0x0052, 0x0053, - /* 5x 5.25x 5.5x 5.75x */ - 0x0054, 0x0055, 0x0056, 0x0057, - /* 6x 6.25x 6.5x 6.75x */ - 0x0058, 0x0059, 0x005a, 0x005b, - /* 7x 7.25x 7.5x 7.75x */ - 0x005c, 0x005d, 0x005e, 0x005f, - /* 8x */ - 0x0060 -}; - -/* Gain = .5 + bit[7:0] / 16 */ -static const u8 hv7131r_gain[] = { - 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */, - 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */, - 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */, - 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */, - 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */, - 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */, - 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */, - 0x78 /* 8x */ -}; - -static const struct i2c_reg_u8 soi968_init[] = { - {0x0c, 0x00}, {0x0f, 0x1f}, - {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00}, - {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c}, - {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff}, - {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20}, - {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e}, - {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13}, - {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79}, - {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40}, - {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32}, - {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80}, -}; - -static const struct i2c_reg_u8 ov7660_init[] = { - {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3}, - {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40}, - {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a}, - /* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using - 0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */ - {0x17, 0x10}, {0x18, 0x61}, - {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43}, - {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0x00}, - {0x2e, 0x00}, {0x01, 0x78}, {0x02, 0x50}, -}; - -static const struct i2c_reg_u8 ov7670_init[] = { - {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01}, - {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00}, - {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0}, - {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00}, - {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07}, - {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75}, - {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8}, - {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5}, - {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27}, - {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b}, - {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a}, - {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00}, - {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00}, - {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80}, - {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82}, - {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20}, - {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c}, - {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66}, - {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11}, - {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40}, - {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02}, - {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a}, - {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08}, - {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04}, - {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30}, - {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88}, - {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30}, - {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99}, - {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0}, - {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e}, - {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01}, - {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20}, - {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0}, - {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30}, - {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06}, - {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a}, - {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a}, - {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84}, - {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d}, - {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d}, - {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00}, - {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, - {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60}, - {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, - {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e}, - {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56}, - {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03}, - {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47}, - {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74}, - {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2}, - {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00}, - {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a}, - {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00}, - {0x93, 0x00}, -}; - -static const struct i2c_reg_u8 ov9650_init[] = { - {0x00, 0x00}, {0x01, 0x78}, - {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03}, - {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00}, - {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00}, - {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c}, - {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2}, - {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07}, - {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00}, - {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04}, - {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68}, - {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80}, - {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00}, - {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00}, - {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30}, - {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf}, - {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00}, - {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01}, - {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19}, - {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1}, - {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80}, - {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00}, - {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20}, - {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf}, - {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88}, - {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00}, - {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8}, - {0xaa, 0x92}, {0xab, 0x0a}, -}; - -static const struct i2c_reg_u8 ov9655_init[] = { - {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba}, - {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08}, - {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d}, - {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57}, - {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19}, - {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80}, - {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c}, - {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc}, - {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05}, - {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e}, - {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68}, - {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92}, - {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80}, - {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00}, - {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44}, - {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01}, - {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0}, - {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00}, - {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61}, - {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a}, - {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01}, - {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a}, - {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c}, - {0x04, 0x03}, {0x00, 0x13}, -}; - -static const struct i2c_reg_u16 mt9v112_init[] = { - {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020}, - {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b}, - {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001}, - {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a}, - {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58}, - {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001}, - {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020}, - {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020}, - {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020}, - {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c}, - {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2}, - {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0}, - {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020}, - {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c}, - {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae}, - {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae}, -}; - -static const struct i2c_reg_u16 mt9v111_init[] = { - {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000}, - {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0}, - {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e}, - {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016}, - {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004}, - {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008}, - {0x0e, 0x0008}, {0x20, 0x0000} -}; - -static const struct i2c_reg_u16 mt9v011_init[] = { - {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000}, - {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1}, - {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006}, - {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000}, - {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000}, - {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000}, - {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000}, - {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000}, - {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000}, - {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000}, - {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000}, - {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000}, - {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024}, - {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000}, - {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100}, - {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1}, - {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000}, - {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000}, - {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000}, - {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101}, - {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003}, - {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0}, - {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000}, - {0x06, 0x0029}, {0x05, 0x0009}, -}; - -static const struct i2c_reg_u16 mt9m001_init[] = { - {0x0d, 0x0001}, - {0x0d, 0x0000}, - {0x04, 0x0500}, /* hres = 1280 */ - {0x03, 0x0400}, /* vres = 1024 */ - {0x20, 0x1100}, - {0x06, 0x0010}, - {0x2b, 0x0024}, - {0x2e, 0x0024}, - {0x35, 0x0024}, - {0x2d, 0x0020}, - {0x2c, 0x0020}, - {0x09, 0x0ad4}, - {0x35, 0x0057}, -}; - -static const struct i2c_reg_u16 mt9m111_init[] = { - {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008}, - {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300}, - {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e}, - {0xf0, 0x0000}, -}; - -static const struct i2c_reg_u16 mt9m112_init[] = { - {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008}, - {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300}, - {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e}, - {0xf0, 0x0000}, -}; - -static const struct i2c_reg_u8 hv7131r_init[] = { - {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08}, - {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0}, - {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08}, - {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07}, - {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62}, - {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10}, - {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00}, - {0x23, 0x09}, {0x01, 0x08}, -}; - -static void reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length) -{ - struct usb_device *dev = gspca_dev->dev; - int result; - - if (gspca_dev->usb_err < 0) - return; - result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - 0x00, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - reg, - 0x00, - gspca_dev->usb_buf, - length, - 500); - if (unlikely(result < 0 || result != length)) { - pr_err("Read register %02x failed %d\n", reg, result); - gspca_dev->usb_err = result; - } -} - -static void reg_w(struct gspca_dev *gspca_dev, u16 reg, - const u8 *buffer, int length) -{ - struct usb_device *dev = gspca_dev->dev; - int result; - - if (gspca_dev->usb_err < 0) - return; - memcpy(gspca_dev->usb_buf, buffer, length); - result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x08, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - reg, - 0x00, - gspca_dev->usb_buf, - length, - 500); - if (unlikely(result < 0 || result != length)) { - pr_err("Write register %02x failed %d\n", reg, result); - gspca_dev->usb_err = result; - } -} - -static void reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value) -{ - reg_w(gspca_dev, reg, &value, 1); -} - -static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer) -{ - int i; - - reg_w(gspca_dev, 0x10c0, buffer, 8); - for (i = 0; i < 5; i++) { - reg_r(gspca_dev, 0x10c0, 1); - if (gspca_dev->usb_err < 0) - return; - if (gspca_dev->usb_buf[0] & 0x04) { - if (gspca_dev->usb_buf[0] & 0x08) { - pr_err("i2c_w error\n"); - gspca_dev->usb_err = -EIO; - } - return; - } - msleep(10); - } - pr_err("i2c_w reg %02x no response\n", buffer[2]); -/* gspca_dev->usb_err = -EIO; fixme: may occur */ -} - -static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 row[8]; - - /* - * from the point of view of the bridge, the length - * includes the address - */ - row[0] = sd->i2c_intf | (2 << 4); - row[1] = sd->i2c_addr; - row[2] = reg; - row[3] = val; - row[4] = 0x00; - row[5] = 0x00; - row[6] = 0x00; - row[7] = 0x10; - - i2c_w(gspca_dev, row); -} - -static void i2c_w1_buf(struct gspca_dev *gspca_dev, - const struct i2c_reg_u8 *buf, int sz) -{ - while (--sz >= 0) { - i2c_w1(gspca_dev, buf->reg, buf->val); - buf++; - } -} - -static void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 row[8]; - - /* - * from the point of view of the bridge, the length - * includes the address - */ - row[0] = sd->i2c_intf | (3 << 4); - row[1] = sd->i2c_addr; - row[2] = reg; - row[3] = val >> 8; - row[4] = val; - row[5] = 0x00; - row[6] = 0x00; - row[7] = 0x10; - - i2c_w(gspca_dev, row); -} - -static void i2c_w2_buf(struct gspca_dev *gspca_dev, - const struct i2c_reg_u16 *buf, int sz) -{ - while (--sz >= 0) { - i2c_w2(gspca_dev, buf->reg, buf->val); - buf++; - } -} - -static void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 row[8]; - - row[0] = sd->i2c_intf | (1 << 4); - row[1] = sd->i2c_addr; - row[2] = reg; - row[3] = 0; - row[4] = 0; - row[5] = 0; - row[6] = 0; - row[7] = 0x10; - i2c_w(gspca_dev, row); - row[0] = sd->i2c_intf | (1 << 4) | 0x02; - row[2] = 0; - i2c_w(gspca_dev, row); - reg_r(gspca_dev, 0x10c2, 5); - *val = gspca_dev->usb_buf[4]; -} - -static void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 row[8]; - - row[0] = sd->i2c_intf | (1 << 4); - row[1] = sd->i2c_addr; - row[2] = reg; - row[3] = 0; - row[4] = 0; - row[5] = 0; - row[6] = 0; - row[7] = 0x10; - i2c_w(gspca_dev, row); - row[0] = sd->i2c_intf | (2 << 4) | 0x02; - row[2] = 0; - i2c_w(gspca_dev, row); - reg_r(gspca_dev, 0x10c2, 5); - *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; -} - -static void ov9650_init_sensor(struct gspca_dev *gspca_dev) -{ - u16 id; - struct sd *sd = (struct sd *) gspca_dev; - - i2c_r2(gspca_dev, 0x1c, &id); - if (gspca_dev->usb_err < 0) - return; - - if (id != 0x7fa2) { - pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id); - gspca_dev->usb_err = -ENODEV; - return; - } - - i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ - msleep(200); - i2c_w1_buf(gspca_dev, ov9650_init, ARRAY_SIZE(ov9650_init)); - if (gspca_dev->usb_err < 0) - pr_err("OV9650 sensor initialization failed\n"); - sd->hstart = 1; - sd->vstart = 7; -} - -static void ov9655_init_sensor(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ - msleep(200); - i2c_w1_buf(gspca_dev, ov9655_init, ARRAY_SIZE(ov9655_init)); - if (gspca_dev->usb_err < 0) - pr_err("OV9655 sensor initialization failed\n"); - - sd->hstart = 1; - sd->vstart = 2; -} - -static void soi968_init_sensor(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ - msleep(200); - i2c_w1_buf(gspca_dev, soi968_init, ARRAY_SIZE(soi968_init)); - if (gspca_dev->usb_err < 0) - pr_err("SOI968 sensor initialization failed\n"); - - sd->hstart = 60; - sd->vstart = 11; -} - -static void ov7660_init_sensor(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ - msleep(200); - i2c_w1_buf(gspca_dev, ov7660_init, ARRAY_SIZE(ov7660_init)); - if (gspca_dev->usb_err < 0) - pr_err("OV7660 sensor initialization failed\n"); - sd->hstart = 3; - sd->vstart = 3; -} - -static void ov7670_init_sensor(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ - msleep(200); - i2c_w1_buf(gspca_dev, ov7670_init, ARRAY_SIZE(ov7670_init)); - if (gspca_dev->usb_err < 0) - pr_err("OV7670 sensor initialization failed\n"); - - sd->hstart = 0; - sd->vstart = 1; -} - -static void mt9v_init_sensor(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u16 value; - - sd->i2c_addr = 0x5d; - i2c_r2(gspca_dev, 0xff, &value); - if (gspca_dev->usb_err >= 0 - && value == 0x8243) { - i2c_w2_buf(gspca_dev, mt9v011_init, ARRAY_SIZE(mt9v011_init)); - if (gspca_dev->usb_err < 0) { - pr_err("MT9V011 sensor initialization failed\n"); - return; - } - sd->hstart = 2; - sd->vstart = 2; - sd->sensor = SENSOR_MT9V011; - pr_info("MT9V011 sensor detected\n"); - return; - } - - gspca_dev->usb_err = 0; - sd->i2c_addr = 0x5c; - i2c_w2(gspca_dev, 0x01, 0x0004); - i2c_r2(gspca_dev, 0xff, &value); - if (gspca_dev->usb_err >= 0 - && value == 0x823a) { - i2c_w2_buf(gspca_dev, mt9v111_init, ARRAY_SIZE(mt9v111_init)); - if (gspca_dev->usb_err < 0) { - pr_err("MT9V111 sensor initialization failed\n"); - return; - } - sd->hstart = 2; - sd->vstart = 2; - sd->sensor = SENSOR_MT9V111; - pr_info("MT9V111 sensor detected\n"); - return; - } - - gspca_dev->usb_err = 0; - sd->i2c_addr = 0x5d; - i2c_w2(gspca_dev, 0xf0, 0x0000); - if (gspca_dev->usb_err < 0) { - gspca_dev->usb_err = 0; - sd->i2c_addr = 0x48; - i2c_w2(gspca_dev, 0xf0, 0x0000); - } - i2c_r2(gspca_dev, 0x00, &value); - if (gspca_dev->usb_err >= 0 - && value == 0x1229) { - i2c_w2_buf(gspca_dev, mt9v112_init, ARRAY_SIZE(mt9v112_init)); - if (gspca_dev->usb_err < 0) { - pr_err("MT9V112 sensor initialization failed\n"); - return; - } - sd->hstart = 6; - sd->vstart = 2; - sd->sensor = SENSOR_MT9V112; - pr_info("MT9V112 sensor detected\n"); - return; - } - - gspca_dev->usb_err = -ENODEV; -} - -static void mt9m112_init_sensor(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - i2c_w2_buf(gspca_dev, mt9m112_init, ARRAY_SIZE(mt9m112_init)); - if (gspca_dev->usb_err < 0) - pr_err("MT9M112 sensor initialization failed\n"); - - sd->hstart = 0; - sd->vstart = 2; -} - -static void mt9m111_init_sensor(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - i2c_w2_buf(gspca_dev, mt9m111_init, ARRAY_SIZE(mt9m111_init)); - if (gspca_dev->usb_err < 0) - pr_err("MT9M111 sensor initialization failed\n"); - - sd->hstart = 0; - sd->vstart = 2; -} - -static void mt9m001_init_sensor(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u16 id; - - i2c_r2(gspca_dev, 0x00, &id); - if (gspca_dev->usb_err < 0) - return; - - /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ - switch (id) { - case 0x8411: - case 0x8421: - pr_info("MT9M001 color sensor detected\n"); - break; - case 0x8431: - pr_info("MT9M001 mono sensor detected\n"); - break; - default: - pr_err("No MT9M001 chip detected, ID = %x\n\n", id); - gspca_dev->usb_err = -ENODEV; - return; - } - - i2c_w2_buf(gspca_dev, mt9m001_init, ARRAY_SIZE(mt9m001_init)); - if (gspca_dev->usb_err < 0) - pr_err("MT9M001 sensor initialization failed\n"); - - sd->hstart = 1; - sd->vstart = 1; -} - -static void hv7131r_init_sensor(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - i2c_w1_buf(gspca_dev, hv7131r_init, ARRAY_SIZE(hv7131r_init)); - if (gspca_dev->usb_err < 0) - pr_err("HV7131R Sensor initialization failed\n"); - - sd->hstart = 0; - sd->vstart = 1; -} - -static void set_cmatrix(struct gspca_dev *gspca_dev, - s32 brightness, s32 contrast, s32 satur, s32 hue) -{ - s32 hue_coord, hue_index = 180 + hue; - u8 cmatrix[21]; - - memset(cmatrix, 0, sizeof cmatrix); - cmatrix[2] = (contrast * 0x25 / 0x100) + 0x26; - cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25; - cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25; - cmatrix[18] = brightness - 0x80; - - hue_coord = (hsv_red_x[hue_index] * satur) >> 8; - cmatrix[6] = hue_coord; - cmatrix[7] = (hue_coord >> 8) & 0x0f; - - hue_coord = (hsv_red_y[hue_index] * satur) >> 8; - cmatrix[8] = hue_coord; - cmatrix[9] = (hue_coord >> 8) & 0x0f; - - hue_coord = (hsv_green_x[hue_index] * satur) >> 8; - cmatrix[10] = hue_coord; - cmatrix[11] = (hue_coord >> 8) & 0x0f; - - hue_coord = (hsv_green_y[hue_index] * satur) >> 8; - cmatrix[12] = hue_coord; - cmatrix[13] = (hue_coord >> 8) & 0x0f; - - hue_coord = (hsv_blue_x[hue_index] * satur) >> 8; - cmatrix[14] = hue_coord; - cmatrix[15] = (hue_coord >> 8) & 0x0f; - - hue_coord = (hsv_blue_y[hue_index] * satur) >> 8; - cmatrix[16] = hue_coord; - cmatrix[17] = (hue_coord >> 8) & 0x0f; - - reg_w(gspca_dev, 0x10e1, cmatrix, 21); -} - -static void set_gamma(struct gspca_dev *gspca_dev, s32 val) -{ - u8 gamma[17]; - u8 gval = val * 0xb8 / 0x100; - - gamma[0] = 0x0a; - gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8); - gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8); - gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8); - gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8); - gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8); - gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8); - gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8); - gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8); - gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8); - gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8); - gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8); - gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8); - gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8); - gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8); - gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8); - gamma[16] = 0xf5; - - reg_w(gspca_dev, 0x1190, gamma, 17); -} - -static void set_redblue(struct gspca_dev *gspca_dev, s32 blue, s32 red) -{ - reg_w1(gspca_dev, 0x118c, red); - reg_w1(gspca_dev, 0x118f, blue); -} - -static void set_hvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip) -{ - u8 value, tslb; - u16 value2; - struct sd *sd = (struct sd *) gspca_dev; - - if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) { - hflip = !hflip; - vflip = !vflip; - } - - switch (sd->sensor) { - case SENSOR_OV7660: - value = 0x01; - if (hflip) - value |= 0x20; - if (vflip) { - value |= 0x10; - sd->vstart = 2; - } else { - sd->vstart = 3; - } - reg_w1(gspca_dev, 0x1182, sd->vstart); - i2c_w1(gspca_dev, 0x1e, value); - break; - case SENSOR_OV9650: - i2c_r1(gspca_dev, 0x1e, &value); - value &= ~0x30; - tslb = 0x01; - if (hflip) - value |= 0x20; - if (vflip) { - value |= 0x10; - tslb = 0x49; - } - i2c_w1(gspca_dev, 0x1e, value); - i2c_w1(gspca_dev, 0x3a, tslb); - break; - case SENSOR_MT9V111: - case SENSOR_MT9V011: - i2c_r2(gspca_dev, 0x20, &value2); - value2 &= ~0xc0a0; - if (hflip) - value2 |= 0x8080; - if (vflip) - value2 |= 0x4020; - i2c_w2(gspca_dev, 0x20, value2); - break; - case SENSOR_MT9M112: - case SENSOR_MT9M111: - case SENSOR_MT9V112: - i2c_r2(gspca_dev, 0x20, &value2); - value2 &= ~0x0003; - if (hflip) - value2 |= 0x0002; - if (vflip) - value2 |= 0x0001; - i2c_w2(gspca_dev, 0x20, value2); - break; - case SENSOR_HV7131R: - i2c_r1(gspca_dev, 0x01, &value); - value &= ~0x03; - if (vflip) - value |= 0x01; - if (hflip) - value |= 0x02; - i2c_w1(gspca_dev, 0x01, value); - break; - } -} - -static void set_exposure(struct gspca_dev *gspca_dev, s32 expo) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 exp[8] = {sd->i2c_intf, sd->i2c_addr, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; - int expo2; - - if (gspca_dev->streaming) - exp[7] = 0x1e; - - switch (sd->sensor) { - case SENSOR_OV7660: - case SENSOR_OV7670: - case SENSOR_OV9655: - case SENSOR_OV9650: - if (expo > 547) - expo2 = 547; - else - expo2 = expo; - exp[0] |= (2 << 4); - exp[2] = 0x10; /* AECH */ - exp[3] = expo2 >> 2; - exp[7] = 0x10; - i2c_w(gspca_dev, exp); - exp[2] = 0x04; /* COM1 */ - exp[3] = expo2 & 0x0003; - exp[7] = 0x10; - i2c_w(gspca_dev, exp); - expo -= expo2; - exp[7] = 0x1e; - exp[0] |= (3 << 4); - exp[2] = 0x2d; /* ADVFL & ADVFH */ - exp[3] = expo; - exp[4] = expo >> 8; - break; - case SENSOR_MT9M001: - case SENSOR_MT9V112: - case SENSOR_MT9V011: - exp[0] |= (3 << 4); - exp[2] = 0x09; - exp[3] = expo >> 8; - exp[4] = expo; - break; - case SENSOR_HV7131R: - exp[0] |= (4 << 4); - exp[2] = 0x25; - exp[3] = expo >> 5; - exp[4] = expo << 3; - exp[5] = 0; - break; - default: - return; - } - i2c_w(gspca_dev, exp); -} - -static void set_gain(struct gspca_dev *gspca_dev, s32 g) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 gain[8] = {sd->i2c_intf, sd->i2c_addr, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; - - if (gspca_dev->streaming) - gain[7] = 0x15; /* or 1d ? */ - - switch (sd->sensor) { - case SENSOR_OV7660: - case SENSOR_OV7670: - case SENSOR_SOI968: - case SENSOR_OV9655: - case SENSOR_OV9650: - gain[0] |= (2 << 4); - gain[3] = ov_gain[g]; - break; - case SENSOR_MT9V011: - gain[0] |= (3 << 4); - gain[2] = 0x35; - gain[3] = micron1_gain[g] >> 8; - gain[4] = micron1_gain[g]; - break; - case SENSOR_MT9V112: - gain[0] |= (3 << 4); - gain[2] = 0x2f; - gain[3] = micron1_gain[g] >> 8; - gain[4] = micron1_gain[g]; - break; - case SENSOR_MT9M001: - gain[0] |= (3 << 4); - gain[2] = 0x2f; - gain[3] = micron2_gain[g] >> 8; - gain[4] = micron2_gain[g]; - break; - case SENSOR_HV7131R: - gain[0] |= (2 << 4); - gain[2] = 0x30; - gain[3] = hv7131r_gain[g]; - break; - default: - return; - } - i2c_w(gspca_dev, gain); -} - -static void set_quality(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - jpeg_set_qual(sd->jpeg_hdr, val); - reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */ - reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */ - reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64); - reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64); - reg_w1(gspca_dev, 0x1061, 0x03); /* restart transfer */ - reg_w1(gspca_dev, 0x10e0, sd->fmt); - sd->fmt ^= 0x0c; /* invert QTAB use + write */ - reg_w1(gspca_dev, 0x10e0, sd->fmt); -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int sd_dbg_g_register(struct gspca_dev *gspca_dev, - struct v4l2_dbg_register *reg) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_HOST: - if (reg->match.addr != 0) - return -EINVAL; - if (reg->reg < 0x1000 || reg->reg > 0x11ff) - return -EINVAL; - reg_r(gspca_dev, reg->reg, 1); - reg->val = gspca_dev->usb_buf[0]; - return gspca_dev->usb_err; - case V4L2_CHIP_MATCH_I2C_ADDR: - if (reg->match.addr != sd->i2c_addr) - return -EINVAL; - if (sd->sensor >= SENSOR_MT9V011 && - sd->sensor <= SENSOR_MT9M112) { - i2c_r2(gspca_dev, reg->reg, (u16 *) ®->val); - } else { - i2c_r1(gspca_dev, reg->reg, (u8 *) ®->val); - } - return gspca_dev->usb_err; - } - return -EINVAL; -} - -static int sd_dbg_s_register(struct gspca_dev *gspca_dev, - struct v4l2_dbg_register *reg) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_HOST: - if (reg->match.addr != 0) - return -EINVAL; - if (reg->reg < 0x1000 || reg->reg > 0x11ff) - return -EINVAL; - reg_w1(gspca_dev, reg->reg, reg->val); - return gspca_dev->usb_err; - case V4L2_CHIP_MATCH_I2C_ADDR: - if (reg->match.addr != sd->i2c_addr) - return -EINVAL; - if (sd->sensor >= SENSOR_MT9V011 && - sd->sensor <= SENSOR_MT9M112) { - i2c_w2(gspca_dev, reg->reg, reg->val); - } else { - i2c_w1(gspca_dev, reg->reg, reg->val); - } - return gspca_dev->usb_err; - } - return -EINVAL; -} -#endif - -static int sd_chip_ident(struct gspca_dev *gspca_dev, - struct v4l2_dbg_chip_ident *chip) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (chip->match.type) { - case V4L2_CHIP_MATCH_HOST: - if (chip->match.addr != 0) - return -EINVAL; - chip->revision = 0; - chip->ident = V4L2_IDENT_SN9C20X; - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - if (chip->match.addr != sd->i2c_addr) - return -EINVAL; - chip->revision = 0; - chip->ident = i2c_ident[sd->sensor]; - return 0; - } - return -EINVAL; -} - -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - - cam = &gspca_dev->cam; - cam->needs_full_bandwidth = 1; - - sd->sensor = id->driver_info >> 8; - sd->i2c_addr = id->driver_info; - sd->flags = id->driver_info >> 16; - sd->i2c_intf = 0x80; /* i2c 100 Kb/s */ - - switch (sd->sensor) { - case SENSOR_MT9M112: - case SENSOR_MT9M111: - case SENSOR_OV9650: - case SENSOR_SOI968: - cam->cam_mode = sxga_mode; - cam->nmodes = ARRAY_SIZE(sxga_mode); - break; - case SENSOR_MT9M001: - cam->cam_mode = mono_mode; - cam->nmodes = ARRAY_SIZE(mono_mode); - break; - case SENSOR_HV7131R: - sd->i2c_intf = 0x81; /* i2c 400 Kb/s */ - /* fall thru */ - default: - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - break; - } - - sd->old_step = 0; - sd->older_step = 0; - sd->exposure_step = 16; - - INIT_WORK(&sd->work, qual_upd); - - return 0; -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - /* color control cluster */ - case V4L2_CID_BRIGHTNESS: - set_cmatrix(gspca_dev, sd->brightness->val, - sd->contrast->val, sd->saturation->val, sd->hue->val); - break; - case V4L2_CID_GAMMA: - set_gamma(gspca_dev, ctrl->val); - break; - /* blue/red balance cluster */ - case V4L2_CID_BLUE_BALANCE: - set_redblue(gspca_dev, sd->blue->val, sd->red->val); - break; - /* h/vflip cluster */ - case V4L2_CID_HFLIP: - set_hvflip(gspca_dev, sd->hflip->val, sd->vflip->val); - break; - /* standalone exposure control */ - case V4L2_CID_EXPOSURE: - set_exposure(gspca_dev, ctrl->val); - break; - /* standalone gain control */ - case V4L2_CID_GAIN: - set_gain(gspca_dev, ctrl->val); - break; - /* autogain + exposure or gain control cluster */ - case V4L2_CID_AUTOGAIN: - if (sd->sensor == SENSOR_SOI968) - set_gain(gspca_dev, sd->gain->val); - else - set_exposure(gspca_dev, sd->exposure->val); - break; - case V4L2_CID_JPEG_COMPRESSION_QUALITY: - set_quality(gspca_dev, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 13); - - sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); - sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 255, 1, 127); - sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SATURATION, 0, 255, 1, 127); - sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_HUE, -180, 180, 1, 0); - - sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAMMA, 0, 255, 1, 0x10); - - sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BLUE_BALANCE, 0, 127, 1, 0x28); - sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_RED_BALANCE, 0, 127, 1, 0x28); - - if (sd->sensor != SENSOR_OV9655 && sd->sensor != SENSOR_SOI968 && - sd->sensor != SENSOR_OV7670 && sd->sensor != SENSOR_MT9M001 && - sd->sensor != SENSOR_MT9VPRB) { - sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_HFLIP, 0, 1, 1, 0); - sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_VFLIP, 0, 1, 1, 0); - } - - if (sd->sensor != SENSOR_SOI968 && sd->sensor != SENSOR_MT9VPRB && - sd->sensor != SENSOR_MT9M112 && sd->sensor != SENSOR_MT9M111 && - sd->sensor != SENSOR_MT9V111) - sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 0x1780, 1, 0x33); - - if (sd->sensor != SENSOR_MT9VPRB && sd->sensor != SENSOR_MT9M112 && - sd->sensor != SENSOR_MT9M111 && sd->sensor != SENSOR_MT9V111) { - sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 28, 1, 0); - sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - } - - sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_JPEG_COMPRESSION_QUALITY, 50, 90, 1, 80); - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - - v4l2_ctrl_cluster(4, &sd->brightness); - v4l2_ctrl_cluster(2, &sd->blue); - if (sd->hflip) - v4l2_ctrl_cluster(2, &sd->hflip); - if (sd->autogain) { - if (sd->sensor == SENSOR_SOI968) - /* this sensor doesn't have the exposure control and - autogain is clustered with gain instead. This works - because sd->exposure == NULL. */ - v4l2_ctrl_auto_cluster(3, &sd->autogain, 0, false); - else - /* Otherwise autogain is clustered with exposure. */ - v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false); - } - return 0; -} - -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i; - u8 value; - u8 i2c_init[9] = - {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}; - - for (i = 0; i < ARRAY_SIZE(bridge_init); i++) { - value = bridge_init[i][1]; - reg_w(gspca_dev, bridge_init[i][0], &value, 1); - if (gspca_dev->usb_err < 0) { - pr_err("Device initialization failed\n"); - return gspca_dev->usb_err; - } - } - - if (sd->flags & LED_REVERSE) - reg_w1(gspca_dev, 0x1006, 0x00); - else - reg_w1(gspca_dev, 0x1006, 0x20); - - reg_w(gspca_dev, 0x10c0, i2c_init, 9); - if (gspca_dev->usb_err < 0) { - pr_err("Device initialization failed\n"); - return gspca_dev->usb_err; - } - - switch (sd->sensor) { - case SENSOR_OV9650: - ov9650_init_sensor(gspca_dev); - if (gspca_dev->usb_err < 0) - break; - pr_info("OV9650 sensor detected\n"); - break; - case SENSOR_OV9655: - ov9655_init_sensor(gspca_dev); - if (gspca_dev->usb_err < 0) - break; - pr_info("OV9655 sensor detected\n"); - break; - case SENSOR_SOI968: - soi968_init_sensor(gspca_dev); - if (gspca_dev->usb_err < 0) - break; - pr_info("SOI968 sensor detected\n"); - break; - case SENSOR_OV7660: - ov7660_init_sensor(gspca_dev); - if (gspca_dev->usb_err < 0) - break; - pr_info("OV7660 sensor detected\n"); - break; - case SENSOR_OV7670: - ov7670_init_sensor(gspca_dev); - if (gspca_dev->usb_err < 0) - break; - pr_info("OV7670 sensor detected\n"); - break; - case SENSOR_MT9VPRB: - mt9v_init_sensor(gspca_dev); - if (gspca_dev->usb_err < 0) - break; - pr_info("MT9VPRB sensor detected\n"); - break; - case SENSOR_MT9M111: - mt9m111_init_sensor(gspca_dev); - if (gspca_dev->usb_err < 0) - break; - pr_info("MT9M111 sensor detected\n"); - break; - case SENSOR_MT9M112: - mt9m112_init_sensor(gspca_dev); - if (gspca_dev->usb_err < 0) - break; - pr_info("MT9M112 sensor detected\n"); - break; - case SENSOR_MT9M001: - mt9m001_init_sensor(gspca_dev); - if (gspca_dev->usb_err < 0) - break; - break; - case SENSOR_HV7131R: - hv7131r_init_sensor(gspca_dev); - if (gspca_dev->usb_err < 0) - break; - pr_info("HV7131R sensor detected\n"); - break; - default: - pr_err("Unsupported sensor\n"); - gspca_dev->usb_err = -ENODEV; - } - return gspca_dev->usb_err; -} - -static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 value; - - switch (sd->sensor) { - case SENSOR_SOI968: - if (mode & MODE_SXGA) { - i2c_w1(gspca_dev, 0x17, 0x1d); - i2c_w1(gspca_dev, 0x18, 0xbd); - i2c_w1(gspca_dev, 0x19, 0x01); - i2c_w1(gspca_dev, 0x1a, 0x81); - i2c_w1(gspca_dev, 0x12, 0x00); - sd->hstart = 140; - sd->vstart = 19; - } else { - i2c_w1(gspca_dev, 0x17, 0x13); - i2c_w1(gspca_dev, 0x18, 0x63); - i2c_w1(gspca_dev, 0x19, 0x01); - i2c_w1(gspca_dev, 0x1a, 0x79); - i2c_w1(gspca_dev, 0x12, 0x40); - sd->hstart = 60; - sd->vstart = 11; - } - break; - case SENSOR_OV9650: - if (mode & MODE_SXGA) { - i2c_w1(gspca_dev, 0x17, 0x1b); - i2c_w1(gspca_dev, 0x18, 0xbc); - i2c_w1(gspca_dev, 0x19, 0x01); - i2c_w1(gspca_dev, 0x1a, 0x82); - i2c_r1(gspca_dev, 0x12, &value); - i2c_w1(gspca_dev, 0x12, value & 0x07); - } else { - i2c_w1(gspca_dev, 0x17, 0x24); - i2c_w1(gspca_dev, 0x18, 0xc5); - i2c_w1(gspca_dev, 0x19, 0x00); - i2c_w1(gspca_dev, 0x1a, 0x3c); - i2c_r1(gspca_dev, 0x12, &value); - i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40); - } - break; - case SENSOR_MT9M112: - case SENSOR_MT9M111: - if (mode & MODE_SXGA) { - i2c_w2(gspca_dev, 0xf0, 0x0002); - i2c_w2(gspca_dev, 0xc8, 0x970b); - i2c_w2(gspca_dev, 0xf0, 0x0000); - } else { - i2c_w2(gspca_dev, 0xf0, 0x0002); - i2c_w2(gspca_dev, 0xc8, 0x8000); - i2c_w2(gspca_dev, 0xf0, 0x0000); - } - break; - } -} - -static int sd_isoc_init(struct gspca_dev *gspca_dev) -{ - struct usb_interface *intf; - u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv; - - /* - * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth - * than our regular bandwidth calculations reserve, so we force the - * use of a specific altsetting when using the SN9C20X_I420 fmt. - */ - if (!(flags & (MODE_RAW | MODE_JPEG))) { - intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); - - if (intf->num_altsetting != 9) { - pr_warn("sn9c20x camera with unknown number of alt " - "settings (%d), please report!\n", - intf->num_altsetting); - gspca_dev->alt = intf->num_altsetting; - return 0; - } - - switch (gspca_dev->width) { - case 160: /* 160x120 */ - gspca_dev->alt = 2; - break; - case 320: /* 320x240 */ - gspca_dev->alt = 6; - break; - default: /* >= 640x480 */ - gspca_dev->alt = 9; - break; - } - } - - return 0; -} - -#define HW_WIN(mode, hstart, vstart) \ -((const u8 []){hstart, 0, vstart, 0, \ -(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \ -(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)}) - -#define CLR_WIN(width, height) \ -((const u8 [])\ -{0, width >> 2, 0, height >> 1,\ -((width >> 10) & 0x01) | ((height >> 8) & 0x6)}) - -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; - int width = gspca_dev->width; - int height = gspca_dev->height; - u8 fmt, scale = 0; - - jpeg_define(sd->jpeg_hdr, height, width, - 0x21); - jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual)); - - if (mode & MODE_RAW) - fmt = 0x2d; - else if (mode & MODE_JPEG) - fmt = 0x24; - else - fmt = 0x2f; /* YUV 420 */ - sd->fmt = fmt; - - switch (mode & SCALE_MASK) { - case SCALE_1280x1024: - scale = 0xc0; - pr_info("Set 1280x1024\n"); - break; - case SCALE_640x480: - scale = 0x80; - pr_info("Set 640x480\n"); - break; - case SCALE_320x240: - scale = 0x90; - pr_info("Set 320x240\n"); - break; - case SCALE_160x120: - scale = 0xa0; - pr_info("Set 160x120\n"); - break; - } - - configure_sensor_output(gspca_dev, mode); - reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64); - reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64); - reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5); - reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6); - reg_w1(gspca_dev, 0x1189, scale); - reg_w1(gspca_dev, 0x10e0, fmt); - - set_cmatrix(gspca_dev, v4l2_ctrl_g_ctrl(sd->brightness), - v4l2_ctrl_g_ctrl(sd->contrast), - v4l2_ctrl_g_ctrl(sd->saturation), - v4l2_ctrl_g_ctrl(sd->hue)); - set_gamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma)); - set_redblue(gspca_dev, v4l2_ctrl_g_ctrl(sd->blue), - v4l2_ctrl_g_ctrl(sd->red)); - if (sd->gain) - set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain)); - if (sd->exposure) - set_exposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure)); - if (sd->hflip) - set_hvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip), - v4l2_ctrl_g_ctrl(sd->vflip)); - - reg_w1(gspca_dev, 0x1007, 0x20); - reg_w1(gspca_dev, 0x1061, 0x03); - - /* if JPEG, prepare the compression quality update */ - if (mode & MODE_JPEG) { - sd->pktsz = sd->npkt = 0; - sd->nchg = 0; - sd->work_thread = - create_singlethread_workqueue(KBUILD_MODNAME); - } - - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - reg_w1(gspca_dev, 0x1007, 0x00); - reg_w1(gspca_dev, 0x1061, 0x01); -} - -/* called on streamoff with alt==0 and on disconnect */ -/* the usb_lock is held at entry - restore on exit */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->work_thread != NULL) { - mutex_unlock(&gspca_dev->usb_lock); - destroy_workqueue(sd->work_thread); - mutex_lock(&gspca_dev->usb_lock); - sd->work_thread = NULL; - } -} - -static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 cur_exp = v4l2_ctrl_g_ctrl(sd->exposure); - s32 max = sd->exposure->maximum - sd->exposure_step; - s32 min = sd->exposure->minimum + sd->exposure_step; - s16 new_exp; - - /* - * some hardcoded values are present - * like those for maximal/minimal exposure - * and exposure steps - */ - if (avg_lum < MIN_AVG_LUM) { - if (cur_exp > max) - return; - - new_exp = cur_exp + sd->exposure_step; - if (new_exp > max) - new_exp = max; - if (new_exp < min) - new_exp = min; - v4l2_ctrl_s_ctrl(sd->exposure, new_exp); - - sd->older_step = sd->old_step; - sd->old_step = 1; - - if (sd->old_step ^ sd->older_step) - sd->exposure_step /= 2; - else - sd->exposure_step += 2; - } - if (avg_lum > MAX_AVG_LUM) { - if (cur_exp < min) - return; - new_exp = cur_exp - sd->exposure_step; - if (new_exp > max) - new_exp = max; - if (new_exp < min) - new_exp = min; - v4l2_ctrl_s_ctrl(sd->exposure, new_exp); - sd->older_step = sd->old_step; - sd->old_step = 0; - - if (sd->old_step ^ sd->older_step) - sd->exposure_step /= 2; - else - sd->exposure_step += 2; - } -} - -static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 cur_gain = v4l2_ctrl_g_ctrl(sd->gain); - - if (avg_lum < MIN_AVG_LUM && cur_gain < sd->gain->maximum) - v4l2_ctrl_s_ctrl(sd->gain, cur_gain + 1); - if (avg_lum > MAX_AVG_LUM && cur_gain > sd->gain->minimum) - v4l2_ctrl_s_ctrl(sd->gain, cur_gain - 1); -} - -static void sd_dqcallback(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int avg_lum; - - if (sd->autogain == NULL || !v4l2_ctrl_g_ctrl(sd->autogain)) - return; - - avg_lum = atomic_read(&sd->avg_lum); - if (sd->sensor == SENSOR_SOI968) - do_autogain(gspca_dev, avg_lum); - else - do_autoexposure(gspca_dev, avg_lum); -} - -/* JPEG quality update */ -/* This function is executed from a work queue. */ -static void qual_upd(struct work_struct *work) -{ - struct sd *sd = container_of(work, struct sd, work); - struct gspca_dev *gspca_dev = &sd->gspca_dev; - s32 qual = v4l2_ctrl_g_ctrl(sd->jpegqual); - - mutex_lock(&gspca_dev->usb_lock); - PDEBUG(D_STREAM, "qual_upd %d%%", qual); - set_quality(gspca_dev, qual); - mutex_unlock(&gspca_dev->usb_lock); -} - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) -static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* interrupt packet */ - int len) /* interrupt packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (!(sd->flags & HAS_NO_BUTTON) && len == 1) { - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); - input_sync(gspca_dev->input_dev); - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); - input_sync(gspca_dev->input_dev); - return 0; - } - return -EINVAL; -} -#endif - -/* check the JPEG compression */ -static void transfer_check(struct gspca_dev *gspca_dev, - u8 *data) -{ - struct sd *sd = (struct sd *) gspca_dev; - int new_qual, r; - - new_qual = 0; - - /* if USB error, discard the frame and decrease the quality */ - if (data[6] & 0x08) { /* USB FIFO full */ - gspca_dev->last_packet_type = DISCARD_PACKET; - new_qual = -5; - } else { - - /* else, compute the filling rate and a new JPEG quality */ - r = (sd->pktsz * 100) / - (sd->npkt * - gspca_dev->urb[0]->iso_frame_desc[0].length); - if (r >= 85) - new_qual = -3; - else if (r < 75) - new_qual = 2; - } - if (new_qual != 0) { - sd->nchg += new_qual; - if (sd->nchg < -6 || sd->nchg >= 12) { - /* Note: we are in interrupt context, so we can't - use v4l2_ctrl_g/s_ctrl here. Access the value - directly instead. */ - s32 curqual = sd->jpegqual->cur.val; - sd->nchg = 0; - new_qual += curqual; - if (new_qual < sd->jpegqual->minimum) - new_qual = sd->jpegqual->minimum; - else if (new_qual > sd->jpegqual->maximum) - new_qual = sd->jpegqual->maximum; - if (new_qual != curqual) { - sd->jpegqual->cur.val = new_qual; - queue_work(sd->work_thread, &sd->work); - } - } - } else { - sd->nchg = 0; - } - sd->pktsz = sd->npkt = 0; -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - int avg_lum, is_jpeg; - static const u8 frame_header[] = - {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; - - is_jpeg = (sd->fmt & 0x03) == 0; - if (len >= 64 && memcmp(data, frame_header, 6) == 0) { - avg_lum = ((data[35] >> 2) & 3) | - (data[20] << 2) | - (data[19] << 10); - avg_lum += ((data[35] >> 4) & 3) | - (data[22] << 2) | - (data[21] << 10); - avg_lum += ((data[35] >> 6) & 3) | - (data[24] << 2) | - (data[23] << 10); - avg_lum += (data[36] & 3) | - (data[26] << 2) | - (data[25] << 10); - avg_lum += ((data[36] >> 2) & 3) | - (data[28] << 2) | - (data[27] << 10); - avg_lum += ((data[36] >> 4) & 3) | - (data[30] << 2) | - (data[29] << 10); - avg_lum += ((data[36] >> 6) & 3) | - (data[32] << 2) | - (data[31] << 10); - avg_lum += ((data[44] >> 4) & 3) | - (data[34] << 2) | - (data[33] << 10); - avg_lum >>= 9; - atomic_set(&sd->avg_lum, avg_lum); - - if (is_jpeg) - transfer_check(gspca_dev, data); - - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - len -= 64; - if (len == 0) - return; - data += 64; - } - if (gspca_dev->last_packet_type == LAST_PACKET) { - if (is_jpeg) { - gspca_frame_add(gspca_dev, FIRST_PACKET, - sd->jpeg_hdr, JPEG_HDR_SZ); - gspca_frame_add(gspca_dev, INTER_PACKET, - data, len); - } else { - gspca_frame_add(gspca_dev, FIRST_PACKET, - data, len); - } - } else { - /* if JPEG, count the packets and their size */ - if (is_jpeg) { - sd->npkt++; - sd->pktsz += len; - } - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); - } -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = KBUILD_MODNAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .isoc_init = sd_isoc_init, - .start = sd_start, - .stopN = sd_stopN, - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .int_pkt_scan = sd_int_pkt_scan, -#endif - .dq_callback = sd_dqcallback, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .set_register = sd_dbg_s_register, - .get_register = sd_dbg_g_register, -#endif - .get_chip_ident = sd_chip_ident, -}; - -#define SN9C20X(sensor, i2c_addr, flags) \ - .driver_info = ((flags & 0xff) << 16) \ - | (SENSOR_ ## sensor << 8) \ - | (i2c_addr) - -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)}, - {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)}, - {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)}, - {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)}, - {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)}, - {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, - (FLIP_DETECT | HAS_NO_BUTTON))}, - {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)}, - {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)}, - {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)}, - {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)}, - {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)}, - {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)}, - {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)}, - {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)}, - {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)}, - {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)}, - {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)}, - {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)}, - {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)}, - {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)}, - {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)}, - {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)}, - {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)}, - {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)}, - {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)}, - {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)}, - {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)}, - {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)}, - {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)}, - {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)}, - {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)}, - {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)}, - {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)}, - {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)}, - {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)}, - {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = KBUILD_MODNAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c deleted file mode 100644 index fd1f8d2d3b0b..000000000000 --- a/drivers/media/video/gspca/sonixb.c +++ /dev/null @@ -1,1493 +0,0 @@ -/* - * sonix sn9c102 (bayer) library - * - * Copyright (C) 2009-2011 Jean-François Moine <http://moinejf.free.fr> - * Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr - * Add Pas106 Stefano Mozzi (C) 2004 - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Some documentation on known sonixb registers: - -Reg Use -sn9c101 / sn9c102: -0x10 high nibble red gain low nibble blue gain -0x11 low nibble green gain -sn9c103: -0x05 red gain 0-127 -0x06 blue gain 0-127 -0x07 green gain 0-127 -all: -0x08-0x0f i2c / 3wire registers -0x12 hstart -0x13 vstart -0x15 hsize (hsize = register-value * 16) -0x16 vsize (vsize = register-value * 16) -0x17 bit 0 toggle compression quality (according to sn9c102 driver) -0x18 bit 7 enables compression, bit 4-5 set image down scaling: - 00 scale 1, 01 scale 1/2, 10, scale 1/4 -0x19 high-nibble is sensor clock divider, changes exposure on sensors which - use a clock generated by the bridge. Some sensors have their own clock. -0x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32) -0x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32) -0x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32) -0x1f auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32) -*/ - -#define MODULE_NAME "sonixb" - -#include <linux/input.h> -#include "gspca.h" - -MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); -MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - struct v4l2_ctrl *brightness; - struct v4l2_ctrl *plfreq; - - atomic_t avg_lum; - int prev_avg_lum; - int exposure_knee; - int header_read; - u8 header[12]; /* Header without sof marker */ - - unsigned char autogain_ignore_frames; - unsigned char frames_to_drop; - - __u8 bridge; /* Type of bridge */ -#define BRIDGE_101 0 -#define BRIDGE_102 0 /* We make no difference between 101 and 102 */ -#define BRIDGE_103 1 - - __u8 sensor; /* Type of image sensor chip */ -#define SENSOR_HV7131D 0 -#define SENSOR_HV7131R 1 -#define SENSOR_OV6650 2 -#define SENSOR_OV7630 3 -#define SENSOR_PAS106 4 -#define SENSOR_PAS202 5 -#define SENSOR_TAS5110C 6 -#define SENSOR_TAS5110D 7 -#define SENSOR_TAS5130CXX 8 - __u8 reg11; -}; - -typedef const __u8 sensor_init_t[8]; - -struct sensor_data { - const __u8 *bridge_init; - sensor_init_t *sensor_init; - int sensor_init_size; - int flags; - __u8 sensor_addr; -}; - -/* sensor_data flags */ -#define F_SIF 0x01 /* sif or vga */ - -/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ -#define MODE_RAW 0x10 /* raw bayer mode */ -#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */ - -#define COMP 0xc7 /* 0x87 //0x07 */ -#define COMP1 0xc9 /* 0x89 //0x09 */ - -#define MCK_INIT 0x63 -#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/ - -#define SYS_CLK 0x04 - -#define SENS(bridge, sensor, _flags, _sensor_addr) \ -{ \ - .bridge_init = bridge, \ - .sensor_init = sensor, \ - .sensor_init_size = sizeof(sensor), \ - .flags = _flags, .sensor_addr = _sensor_addr \ -} - -/* We calculate the autogain at the end of the transfer of a frame, at this - moment a frame with the old settings is being captured and transmitted. So - if we adjust the gain or exposure we must ignore atleast the next frame for - the new settings to come into effect before doing any other adjustments. */ -#define AUTOGAIN_IGNORE_FRAMES 1 - -static const struct v4l2_pix_format vga_mode[] = { - {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2 | MODE_RAW}, - {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120 * 5 / 4, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, - {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 5 / 4, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 5 / 4, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; -static const struct v4l2_pix_format sif_mode[] = { - {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 | MODE_RAW | MODE_REDUCED_SIF}, - {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120 * 5 / 4, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 | MODE_REDUCED_SIF}, - {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 | MODE_RAW}, - {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144 * 5 / 4, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 5 / 4, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 | MODE_REDUCED_SIF}, - {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 5 / 4, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; - -static const __u8 initHv7131d[] = { - 0x04, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, - 0x28, 0x1e, 0x60, 0x8e, 0x42, -}; -static const __u8 hv7131d_sensor_init[][8] = { - {0xa0, 0x11, 0x01, 0x04, 0x00, 0x00, 0x00, 0x17}, - {0xa0, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x17}, - {0xa0, 0x11, 0x28, 0x00, 0x00, 0x00, 0x00, 0x17}, - {0xa0, 0x11, 0x30, 0x30, 0x00, 0x00, 0x00, 0x17}, /* reset level */ - {0xa0, 0x11, 0x34, 0x02, 0x00, 0x00, 0x00, 0x17}, /* pixel bias volt */ -}; - -static const __u8 initHv7131r[] = { - 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, - 0x28, 0x1e, 0x60, 0x8a, 0x20, -}; -static const __u8 hv7131r_sensor_init[][8] = { - {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10}, - {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10}, - {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10}, - {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16}, - {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15}, -}; -static const __u8 initOv6650[] = { - 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b, - 0x10, -}; -static const __u8 ov6650_sensor_init[][8] = { - /* Bright, contrast, etc are set through SCBB interface. - * AVCAP on win2 do not send any data on this controls. */ - /* Anyway, some registers appears to alter bright and constrat */ - - /* Reset sensor */ - {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, - /* Set clock register 0x11 low nibble is clock divider */ - {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10}, - /* Next some unknown stuff */ - {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10}, -/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10}, - * THIS SET GREEN SCREEN - * (pixels could be innverted in decode kind of "brg", - * but blue wont be there. Avoid this data ... */ - {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */ - {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, - {0xa0, 0x60, 0x30, 0x3d, 0x0a, 0xd8, 0xa4, 0x10}, - /* Enable rgb brightness control */ - {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10}, - /* HDG: Note windows uses the line below, which sets both register 0x60 - and 0x61 I believe these registers of the ov6650 are identical as - those of the ov7630, because if this is true the windows settings - add a bit additional red gain and a lot additional blue gain, which - matches my findings that the windows settings make blue much too - blue and red a little too red. - {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */ - /* Some more unknown stuff */ - {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10}, - {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */ -}; - -static const __u8 initOv7630[] = { - 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */ - 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */ - 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */ - 0x28, 0x1e, /* H & V sizes r15 .. r16 */ - 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */ -}; -static const __u8 ov7630_sensor_init[][8] = { - {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, - {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10}, -/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */ - {0xd0, 0x21, 0x12, 0x5c, 0x00, 0x80, 0x34, 0x10}, /* jfm */ - {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10}, - {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10}, - {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10}, - {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10}, - {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10}, - {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10}, - {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10}, - {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10}, -/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */ - {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10}, - {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10}, - {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10}, - {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10}, - {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10}, - {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10}, -}; - -static const __u8 initPas106[] = { - 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, - 0x16, 0x12, 0x24, COMP1, MCK_INIT1, -}; -/* compression 0x86 mckinit1 0x2b */ - -/* "Known" PAS106B registers: - 0x02 clock divider - 0x03 Variable framerate bits 4-11 - 0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !! - The variable framerate control must never be set lower then 300, - which sets the framerate at 90 / reg02, otherwise vsync is lost. - 0x05 Shutter Time Line Offset, this can be used as an exposure control: - 0 = use full frame time, 255 = no exposure at all - Note this may never be larger then "var-framerate control" / 2 - 2. - When var-framerate control is < 514, no exposure is reached at the max - allowed value for the framerate control value, rather then at 255. - 0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but - only a very little bit, leave at 0xcd - 0x07 offset sign bit (bit0 1 > negative offset) - 0x08 offset - 0x09 Blue Gain - 0x0a Green1 Gain - 0x0b Green2 Gain - 0x0c Red Gain - 0x0e Global gain - 0x13 Write 1 to commit settings to sensor -*/ - -static const __u8 pas106_sensor_init[][8] = { - /* Pixel Clock Divider 6 */ - { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 }, - /* Frame Time MSB (also seen as 0x12) */ - { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 }, - /* Frame Time LSB (also seen as 0x05) */ - { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 }, - /* Shutter Time Line Offset (also seen as 0x6d) */ - { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 }, - /* Shutter Time Pixel Offset (also seen as 0xb1) */ - { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 }, - /* Black Level Subtract Sign (also seen 0x00) */ - { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 }, - /* Black Level Subtract Level (also seen 0x01) */ - { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 }, - { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 }, - /* Color Gain B Pixel 5 a */ - { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 }, - /* Color Gain G1 Pixel 1 5 */ - { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 }, - /* Color Gain G2 Pixel 1 0 5 */ - { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 }, - /* Color Gain R Pixel 3 1 */ - { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 }, - /* Color GainH Pixel */ - { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 }, - /* Global Gain */ - { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 }, - /* Contrast */ - { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 }, - /* H&V synchro polarity */ - { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 }, - /* ?default */ - { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 }, - /* DAC scale */ - { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 }, - /* ?default */ - { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 }, - /* Validate Settings */ - { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 }, -}; - -static const __u8 initPas202[] = { - 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a, - 0x28, 0x1e, 0x20, 0x89, 0x20, -}; - -/* "Known" PAS202BCB registers: - 0x02 clock divider - 0x04 Variable framerate bits 6-11 (*) - 0x05 Var framerate bits 0-5, one must leave the 2 msb's at 0 !! - 0x07 Blue Gain - 0x08 Green Gain - 0x09 Red Gain - 0x0b offset sign bit (bit0 1 > negative offset) - 0x0c offset - 0x0e Unknown image is slightly brighter when bit 0 is 0, if reg0f is 0 too, - leave at 1 otherwise we get a jump in our exposure control - 0x0f Exposure 0-255, 0 = use full frame time, 255 = no exposure at all - 0x10 Master gain 0 - 31 - 0x11 write 1 to apply changes - (*) The variable framerate control must never be set lower then 500 - which sets the framerate at 30 / reg02, otherwise vsync is lost. -*/ -static const __u8 pas202_sensor_init[][8] = { - /* Set the clock divider to 4 -> 30 / 4 = 7.5 fps, we would like - to set it lower, but for some reason the bridge starts missing - vsync's then */ - {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10}, - {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10}, - {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10}, - {0xd0, 0x40, 0x0c, 0x00, 0x0c, 0x01, 0x32, 0x10}, - {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10}, - {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10}, - {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10}, - {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10}, - {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10}, - {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10}, -}; - -static const __u8 initTas5110c[] = { - 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, 0x00, 0x45, 0x09, 0x0a, - 0x16, 0x12, 0x60, 0x86, 0x2b, -}; -/* Same as above, except a different hstart */ -static const __u8 initTas5110d[] = { - 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, 0x00, 0x41, 0x09, 0x0a, - 0x16, 0x12, 0x60, 0x86, 0x2b, -}; -/* tas5110c is 3 wire, tas5110d is 2 wire (regular i2c) */ -static const __u8 tas5110c_sensor_init[][8] = { - {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10}, - {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10}, -}; -/* Known TAS5110D registers - * reg02: gain, bit order reversed!! 0 == max gain, 255 == min gain - * reg03: bit3: vflip, bit4: ~hflip, bit7: ~gainboost (~ == inverted) - * Note: writing reg03 seems to only work when written together with 02 - */ -static const __u8 tas5110d_sensor_init[][8] = { - {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17}, /* reset */ -}; - -static const __u8 initTas5130[] = { - 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, 0x00, 0x68, 0x0c, 0x0a, - 0x28, 0x1e, 0x60, COMP, MCK_INIT, -}; -static const __u8 tas5130_sensor_init[][8] = { -/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10}, - * shutter 0x47 short exposure? */ - {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10}, - /* shutter 0x01 long exposure */ - {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}, -}; - -static const struct sensor_data sensor_data[] = { - SENS(initHv7131d, hv7131d_sensor_init, 0, 0), - SENS(initHv7131r, hv7131r_sensor_init, 0, 0), - SENS(initOv6650, ov6650_sensor_init, F_SIF, 0x60), - SENS(initOv7630, ov7630_sensor_init, 0, 0x21), - SENS(initPas106, pas106_sensor_init, F_SIF, 0), - SENS(initPas202, pas202_sensor_init, 0, 0), - SENS(initTas5110c, tas5110c_sensor_init, F_SIF, 0), - SENS(initTas5110d, tas5110d_sensor_init, F_SIF, 0), - SENS(initTas5130, tas5130_sensor_init, 0, 0), -}; - -/* get one byte in gspca_dev->usb_buf */ -static void reg_r(struct gspca_dev *gspca_dev, - __u16 value) -{ - int res; - - if (gspca_dev->usb_err < 0) - return; - - res = usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - 0, /* request */ - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - value, - 0, /* index */ - gspca_dev->usb_buf, 1, - 500); - - if (res < 0) { - dev_err(gspca_dev->v4l2_dev.dev, - "Error reading register %02x: %d\n", value, res); - gspca_dev->usb_err = res; - } -} - -static void reg_w(struct gspca_dev *gspca_dev, - __u16 value, - const __u8 *buffer, - int len) -{ - int res; - - if (gspca_dev->usb_err < 0) - return; - - memcpy(gspca_dev->usb_buf, buffer, len); - res = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x08, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - value, - 0, /* index */ - gspca_dev->usb_buf, len, - 500); - - if (res < 0) { - dev_err(gspca_dev->v4l2_dev.dev, - "Error writing register %02x: %d\n", value, res); - gspca_dev->usb_err = res; - } -} - -static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer) -{ - int retry = 60; - - if (gspca_dev->usb_err < 0) - return; - - /* is i2c ready */ - reg_w(gspca_dev, 0x08, buffer, 8); - while (retry--) { - if (gspca_dev->usb_err < 0) - return; - msleep(10); - reg_r(gspca_dev, 0x08); - if (gspca_dev->usb_buf[0] & 0x04) { - if (gspca_dev->usb_buf[0] & 0x08) { - dev_err(gspca_dev->v4l2_dev.dev, - "i2c write error\n"); - gspca_dev->usb_err = -EIO; - } - return; - } - } - - dev_err(gspca_dev->v4l2_dev.dev, "i2c write timeout\n"); - gspca_dev->usb_err = -EIO; -} - -static void i2c_w_vector(struct gspca_dev *gspca_dev, - const __u8 buffer[][8], int len) -{ - for (;;) { - if (gspca_dev->usb_err < 0) - return; - reg_w(gspca_dev, 0x08, *buffer, 8); - len -= 8; - if (len <= 0) - break; - buffer++; - } -} - -static void setbrightness(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->sensor) { - case SENSOR_OV6650: - case SENSOR_OV7630: { - __u8 i2cOV[] = - {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}; - - /* change reg 0x06 */ - i2cOV[1] = sensor_data[sd->sensor].sensor_addr; - i2cOV[3] = sd->brightness->val; - i2c_w(gspca_dev, i2cOV); - break; - } - case SENSOR_PAS106: - case SENSOR_PAS202: { - __u8 i2cpbright[] = - {0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16}; - __u8 i2cpdoit[] = - {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; - - /* PAS106 uses reg 7 and 8 instead of b and c */ - if (sd->sensor == SENSOR_PAS106) { - i2cpbright[2] = 7; - i2cpdoit[2] = 0x13; - } - - if (sd->brightness->val < 127) { - /* change reg 0x0b, signreg */ - i2cpbright[3] = 0x01; - /* set reg 0x0c, offset */ - i2cpbright[4] = 127 - sd->brightness->val; - } else - i2cpbright[4] = sd->brightness->val - 127; - - i2c_w(gspca_dev, i2cpbright); - i2c_w(gspca_dev, i2cpdoit); - break; - } - default: - break; - } -} - -static void setgain(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 gain = gspca_dev->gain->val; - - switch (sd->sensor) { - case SENSOR_HV7131D: { - __u8 i2c[] = - {0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17}; - - i2c[3] = 0x3f - gain; - i2c[4] = 0x3f - gain; - i2c[5] = 0x3f - gain; - - i2c_w(gspca_dev, i2c); - break; - } - case SENSOR_TAS5110C: - case SENSOR_TAS5130CXX: { - __u8 i2c[] = - {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}; - - i2c[4] = 255 - gain; - i2c_w(gspca_dev, i2c); - break; - } - case SENSOR_TAS5110D: { - __u8 i2c[] = { - 0xb0, 0x61, 0x02, 0x00, 0x10, 0x00, 0x00, 0x17 }; - gain = 255 - gain; - /* The bits in the register are the wrong way around!! */ - i2c[3] |= (gain & 0x80) >> 7; - i2c[3] |= (gain & 0x40) >> 5; - i2c[3] |= (gain & 0x20) >> 3; - i2c[3] |= (gain & 0x10) >> 1; - i2c[3] |= (gain & 0x08) << 1; - i2c[3] |= (gain & 0x04) << 3; - i2c[3] |= (gain & 0x02) << 5; - i2c[3] |= (gain & 0x01) << 7; - i2c_w(gspca_dev, i2c); - break; - } - case SENSOR_OV6650: - case SENSOR_OV7630: { - __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; - - /* - * The ov7630's gain is weird, at 32 the gain drops to the - * same level as at 16, so skip 32-47 (of the 0-63 scale). - */ - if (sd->sensor == SENSOR_OV7630 && gain >= 32) - gain += 16; - - i2c[1] = sensor_data[sd->sensor].sensor_addr; - i2c[3] = gain; - i2c_w(gspca_dev, i2c); - break; - } - case SENSOR_PAS106: - case SENSOR_PAS202: { - __u8 i2cpgain[] = - {0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15}; - __u8 i2cpcolorgain[] = - {0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15}; - __u8 i2cpdoit[] = - {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; - - /* PAS106 uses different regs (and has split green gains) */ - if (sd->sensor == SENSOR_PAS106) { - i2cpgain[2] = 0x0e; - i2cpcolorgain[0] = 0xd0; - i2cpcolorgain[2] = 0x09; - i2cpdoit[2] = 0x13; - } - - i2cpgain[3] = gain; - i2cpcolorgain[3] = gain >> 1; - i2cpcolorgain[4] = gain >> 1; - i2cpcolorgain[5] = gain >> 1; - i2cpcolorgain[6] = gain >> 1; - - i2c_w(gspca_dev, i2cpgain); - i2c_w(gspca_dev, i2cpcolorgain); - i2c_w(gspca_dev, i2cpdoit); - break; - } - default: - if (sd->bridge == BRIDGE_103) { - u8 buf[3] = { gain, gain, gain }; /* R, G, B */ - reg_w(gspca_dev, 0x05, buf, 3); - } else { - u8 buf[2]; - buf[0] = gain << 4 | gain; /* Red and blue */ - buf[1] = gain; /* Green */ - reg_w(gspca_dev, 0x10, buf, 2); - } - } -} - -static void setexposure(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->sensor) { - case SENSOR_HV7131D: { - /* Note the datasheet wrongly says line mode exposure uses reg - 0x26 and 0x27, testing has shown 0x25 + 0x26 */ - __u8 i2c[] = {0xc0, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x17}; - u16 reg = gspca_dev->exposure->val; - - i2c[3] = reg >> 8; - i2c[4] = reg & 0xff; - i2c_w(gspca_dev, i2c); - break; - } - case SENSOR_TAS5110C: - case SENSOR_TAS5110D: { - /* register 19's high nibble contains the sn9c10x clock divider - The high nibble configures the no fps according to the - formula: 60 / high_nibble. With a maximum of 30 fps */ - u8 reg = gspca_dev->exposure->val; - - reg = (reg << 4) | 0x0b; - reg_w(gspca_dev, 0x19, ®, 1); - break; - } - case SENSOR_OV6650: - case SENSOR_OV7630: { - /* The ov6650 / ov7630 have 2 registers which both influence - exposure, register 11, whose low nibble sets the nr off fps - according to: fps = 30 / (low_nibble + 1) - - The fps configures the maximum exposure setting, but it is - possible to use less exposure then what the fps maximum - allows by setting register 10. register 10 configures the - actual exposure as quotient of the full exposure, with 0 - being no exposure at all (not very useful) and reg10_max - being max exposure possible at that framerate. - - The code maps our 0 - 510 ms exposure ctrl to these 2 - registers, trying to keep fps as high as possible. - */ - __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10}; - int reg10, reg11, reg10_max; - - /* ov6645 datasheet says reg10_max is 9a, but that uses - tline * 2 * reg10 as formula for calculating texpo, the - ov6650 probably uses the same formula as the 7730 which uses - tline * 4 * reg10, which explains why the reg10max we've - found experimentally for the ov6650 is exactly half that of - the ov6645. The ov7630 datasheet says the max is 0x41. */ - if (sd->sensor == SENSOR_OV6650) { - reg10_max = 0x4d; - i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */ - } else - reg10_max = 0x41; - - reg11 = (15 * gspca_dev->exposure->val + 999) / 1000; - if (reg11 < 1) - reg11 = 1; - else if (reg11 > 16) - reg11 = 16; - - /* In 640x480, if the reg11 has less than 4, the image is - unstable (the bridge goes into a higher compression mode - which we have not reverse engineered yet). */ - if (gspca_dev->width == 640 && reg11 < 4) - reg11 = 4; - - /* frame exposure time in ms = 1000 * reg11 / 30 -> - reg10 = (gspca_dev->exposure->val / 2) * reg10_max - / (1000 * reg11 / 30) */ - reg10 = (gspca_dev->exposure->val * 15 * reg10_max) - / (1000 * reg11); - - /* Don't allow this to get below 10 when using autogain, the - steps become very large (relatively) when below 10 causing - the image to oscilate from much too dark, to much too bright - and back again. */ - if (gspca_dev->autogain->val && reg10 < 10) - reg10 = 10; - else if (reg10 > reg10_max) - reg10 = reg10_max; - - /* Write reg 10 and reg11 low nibble */ - i2c[1] = sensor_data[sd->sensor].sensor_addr; - i2c[3] = reg10; - i2c[4] |= reg11 - 1; - - /* If register 11 didn't change, don't change it */ - if (sd->reg11 == reg11) - i2c[0] = 0xa0; - - i2c_w(gspca_dev, i2c); - if (gspca_dev->usb_err == 0) - sd->reg11 = reg11; - break; - } - case SENSOR_PAS202: { - __u8 i2cpframerate[] = - {0xb0, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x16}; - __u8 i2cpexpo[] = - {0xa0, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x16}; - const __u8 i2cpdoit[] = - {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; - int framerate_ctrl; - - /* The exposure knee for the autogain algorithm is 200 - (100 ms / 10 fps on other sensors), for values below this - use the control for setting the partial frame expose time, - above that use variable framerate. This way we run at max - framerate (640x480@7.5 fps, 320x240@10fps) until the knee - is reached. Using the variable framerate control above 200 - is better then playing around with both clockdiv + partial - frame exposure times (like we are doing with the ov chips), - as that sometimes leads to jumps in the exposure control, - which are bad for auto exposure. */ - if (gspca_dev->exposure->val < 200) { - i2cpexpo[3] = 255 - (gspca_dev->exposure->val * 255) - / 200; - framerate_ctrl = 500; - } else { - /* The PAS202's exposure control goes from 0 - 4095, - but anything below 500 causes vsync issues, so scale - our 200-1023 to 500-4095 */ - framerate_ctrl = (gspca_dev->exposure->val - 200) - * 1000 / 229 + 500; - } - - i2cpframerate[3] = framerate_ctrl >> 6; - i2cpframerate[4] = framerate_ctrl & 0x3f; - i2c_w(gspca_dev, i2cpframerate); - i2c_w(gspca_dev, i2cpexpo); - i2c_w(gspca_dev, i2cpdoit); - break; - } - case SENSOR_PAS106: { - __u8 i2cpframerate[] = - {0xb1, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14}; - __u8 i2cpexpo[] = - {0xa1, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x14}; - const __u8 i2cpdoit[] = - {0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14}; - int framerate_ctrl; - - /* For values below 150 use partial frame exposure, above - that use framerate ctrl */ - if (gspca_dev->exposure->val < 150) { - i2cpexpo[3] = 150 - gspca_dev->exposure->val; - framerate_ctrl = 300; - } else { - /* The PAS106's exposure control goes from 0 - 4095, - but anything below 300 causes vsync issues, so scale - our 150-1023 to 300-4095 */ - framerate_ctrl = (gspca_dev->exposure->val - 150) - * 1000 / 230 + 300; - } - - i2cpframerate[3] = framerate_ctrl >> 4; - i2cpframerate[4] = framerate_ctrl & 0x0f; - i2c_w(gspca_dev, i2cpframerate); - i2c_w(gspca_dev, i2cpexpo); - i2c_w(gspca_dev, i2cpdoit); - break; - } - default: - break; - } -} - -static void setfreq(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630) { - /* Framerate adjust register for artificial light 50 hz flicker - compensation, for the ov6650 this is identical to ov6630 - 0x2b register, see ov6630 datasheet. - 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */ - __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}; - switch (sd->plfreq->val) { - default: -/* case 0: * no filter*/ -/* case 2: * 60 hz */ - i2c[3] = 0; - break; - case 1: /* 50 hz */ - i2c[3] = (sd->sensor == SENSOR_OV6650) - ? 0x4f : 0x8a; - break; - } - i2c[1] = sensor_data[sd->sensor].sensor_addr; - i2c_w(gspca_dev, i2c); - } -} - -static void do_autogain(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int deadzone, desired_avg_lum, avg_lum; - - avg_lum = atomic_read(&sd->avg_lum); - if (avg_lum == -1) - return; - - if (sd->autogain_ignore_frames > 0) { - sd->autogain_ignore_frames--; - return; - } - - /* SIF / VGA sensors have a different autoexposure area and thus - different avg_lum values for the same picture brightness */ - if (sensor_data[sd->sensor].flags & F_SIF) { - deadzone = 500; - /* SIF sensors tend to overexpose, so keep this small */ - desired_avg_lum = 5000; - } else { - deadzone = 1500; - desired_avg_lum = 13000; - } - - if (sd->brightness) - desired_avg_lum = sd->brightness->val * desired_avg_lum / 127; - - if (gspca_dev->exposure->maximum < 500) { - if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum, - desired_avg_lum, deadzone)) - sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; - } else { - int gain_knee = gspca_dev->gain->maximum * 9 / 10; - if (gspca_expo_autogain(gspca_dev, avg_lum, desired_avg_lum, - deadzone, gain_knee, sd->exposure_knee)) - sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; - } -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - - reg_r(gspca_dev, 0x00); - if (gspca_dev->usb_buf[0] != 0x10) - return -ENODEV; - - /* copy the webcam info from the device id */ - sd->sensor = id->driver_info >> 8; - sd->bridge = id->driver_info & 0xff; - - cam = &gspca_dev->cam; - if (!(sensor_data[sd->sensor].flags & F_SIF)) { - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - } else { - cam->cam_mode = sif_mode; - cam->nmodes = ARRAY_SIZE(sif_mode); - } - cam->npkt = 36; /* 36 packets per ISOC message */ - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - const __u8 stop = 0x09; /* Disable stream turn of LED */ - - reg_w(gspca_dev, 0x01, &stop, 1); - - return gspca_dev->usb_err; -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) { - /* when switching to autogain set defaults to make sure - we are on a valid point of the autogain gain / - exposure knee graph, and give this change time to - take effect before doing autogain. */ - gspca_dev->gain->val = gspca_dev->gain->default_value; - gspca_dev->exposure->val = gspca_dev->exposure->default_value; - sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; - } - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev); - break; - case V4L2_CID_AUTOGAIN: - if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val)) - setexposure(gspca_dev); - if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val)) - setgain(gspca_dev); - break; - case V4L2_CID_POWER_LINE_FREQUENCY: - setfreq(gspca_dev); - break; - default: - return -EINVAL; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -/* this function is called at probe time */ -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 5); - - if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630 || - sd->sensor == SENSOR_PAS106 || sd->sensor == SENSOR_PAS202) - sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); - - /* Gain range is sensor dependent */ - switch (sd->sensor) { - case SENSOR_OV6650: - case SENSOR_PAS106: - case SENSOR_PAS202: - gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 31, 1, 15); - break; - case SENSOR_OV7630: - gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 47, 1, 31); - break; - case SENSOR_HV7131D: - gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 63, 1, 31); - break; - case SENSOR_TAS5110C: - case SENSOR_TAS5110D: - case SENSOR_TAS5130CXX: - gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 255, 1, 127); - break; - default: - if (sd->bridge == BRIDGE_103) { - gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 127, 1, 63); - } else { - gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 15, 1, 7); - } - } - - /* Exposure range is sensor dependent, and not all have exposure */ - switch (sd->sensor) { - case SENSOR_HV7131D: - gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 8191, 1, 482); - sd->exposure_knee = 964; - break; - case SENSOR_OV6650: - case SENSOR_OV7630: - case SENSOR_PAS106: - case SENSOR_PAS202: - gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 1023, 1, 66); - sd->exposure_knee = 200; - break; - case SENSOR_TAS5110C: - case SENSOR_TAS5110D: - gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, 2, 15, 1, 2); - break; - } - - if (gspca_dev->exposure) { - gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - } - - if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630) - sd->plfreq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, - V4L2_CID_POWER_LINE_FREQUENCY, - V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, - V4L2_CID_POWER_LINE_FREQUENCY_DISABLED); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - - if (gspca_dev->autogain) - v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false); - - return 0; -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam = &gspca_dev->cam; - int i, mode; - __u8 regs[0x31]; - - mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07; - /* Copy registers 0x01 - 0x19 from the template */ - memcpy(®s[0x01], sensor_data[sd->sensor].bridge_init, 0x19); - /* Set the mode */ - regs[0x18] |= mode << 4; - - /* Set bridge gain to 1.0 */ - if (sd->bridge == BRIDGE_103) { - regs[0x05] = 0x20; /* Red */ - regs[0x06] = 0x20; /* Green */ - regs[0x07] = 0x20; /* Blue */ - } else { - regs[0x10] = 0x00; /* Red and blue */ - regs[0x11] = 0x00; /* Green */ - } - - /* Setup pixel numbers and auto exposure window */ - if (sensor_data[sd->sensor].flags & F_SIF) { - regs[0x1a] = 0x14; /* HO_SIZE 640, makes no sense */ - regs[0x1b] = 0x0a; /* VO_SIZE 320, makes no sense */ - regs[0x1c] = 0x02; /* AE H-start 64 */ - regs[0x1d] = 0x02; /* AE V-start 64 */ - regs[0x1e] = 0x09; /* AE H-end 288 */ - regs[0x1f] = 0x07; /* AE V-end 224 */ - } else { - regs[0x1a] = 0x1d; /* HO_SIZE 960, makes no sense */ - regs[0x1b] = 0x10; /* VO_SIZE 512, makes no sense */ - regs[0x1c] = 0x05; /* AE H-start 160 */ - regs[0x1d] = 0x03; /* AE V-start 96 */ - regs[0x1e] = 0x0f; /* AE H-end 480 */ - regs[0x1f] = 0x0c; /* AE V-end 384 */ - } - - /* Setup the gamma table (only used with the sn9c103 bridge) */ - for (i = 0; i < 16; i++) - regs[0x20 + i] = i * 16; - regs[0x20 + i] = 255; - - /* Special cases where some regs depend on mode or bridge */ - switch (sd->sensor) { - case SENSOR_TAS5130CXX: - /* FIXME / TESTME - probably not mode specific at all most likely the upper - nibble of 0x19 is exposure (clock divider) just as with - the tas5110, we need someone to test this. */ - regs[0x19] = mode ? 0x23 : 0x43; - break; - case SENSOR_OV7630: - /* FIXME / TESTME for some reason with the 101/102 bridge the - clock is set to 12 Mhz (reg1 == 0x04), rather then 24. - Also the hstart needs to go from 1 to 2 when using a 103, - which is likely related. This does not seem right. */ - if (sd->bridge == BRIDGE_103) { - regs[0x01] = 0x44; /* Select 24 Mhz clock */ - regs[0x12] = 0x02; /* Set hstart to 2 */ - } - } - /* Disable compression when the raw bayer format has been selected */ - if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) - regs[0x18] &= ~0x80; - - /* Vga mode emulation on SIF sensor? */ - if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) { - regs[0x12] += 16; /* hstart adjust */ - regs[0x13] += 24; /* vstart adjust */ - regs[0x15] = 320 / 16; /* hsize */ - regs[0x16] = 240 / 16; /* vsize */ - } - - /* reg 0x01 bit 2 video transfert on */ - reg_w(gspca_dev, 0x01, ®s[0x01], 1); - /* reg 0x17 SensorClk enable inv Clk 0x60 */ - reg_w(gspca_dev, 0x17, ®s[0x17], 1); - /* Set the registers from the template */ - reg_w(gspca_dev, 0x01, ®s[0x01], - (sd->bridge == BRIDGE_103) ? 0x30 : 0x1f); - - /* Init the sensor */ - i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init, - sensor_data[sd->sensor].sensor_init_size); - - /* Mode / bridge specific sensor setup */ - switch (sd->sensor) { - case SENSOR_PAS202: { - const __u8 i2cpclockdiv[] = - {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10}; - /* clockdiv from 4 to 3 (7.5 -> 10 fps) when in low res mode */ - if (mode) - i2c_w(gspca_dev, i2cpclockdiv); - break; - } - case SENSOR_OV7630: - /* FIXME / TESTME We should be able to handle this identical - for the 101/102 and the 103 case */ - if (sd->bridge == BRIDGE_103) { - const __u8 i2c[] = { 0xa0, 0x21, 0x13, - 0x80, 0x00, 0x00, 0x00, 0x10 }; - i2c_w(gspca_dev, i2c); - } - break; - } - /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ - reg_w(gspca_dev, 0x15, ®s[0x15], 2); - /* compression register */ - reg_w(gspca_dev, 0x18, ®s[0x18], 1); - /* H_start */ - reg_w(gspca_dev, 0x12, ®s[0x12], 1); - /* V_START */ - reg_w(gspca_dev, 0x13, ®s[0x13], 1); - /* reset 0x17 SensorClk enable inv Clk 0x60 */ - /*fixme: ov7630 [17]=68 8f (+20 if 102)*/ - reg_w(gspca_dev, 0x17, ®s[0x17], 1); - /*MCKSIZE ->3 */ /*fixme: not ov7630*/ - reg_w(gspca_dev, 0x19, ®s[0x19], 1); - /* AE_STRX AE_STRY AE_ENDX AE_ENDY */ - reg_w(gspca_dev, 0x1c, ®s[0x1c], 4); - /* Enable video transfert */ - reg_w(gspca_dev, 0x01, ®s[0x01], 1); - /* Compression */ - reg_w(gspca_dev, 0x18, ®s[0x18], 2); - msleep(20); - - sd->reg11 = -1; - - setgain(gspca_dev); - setbrightness(gspca_dev); - setexposure(gspca_dev); - setfreq(gspca_dev); - - sd->frames_to_drop = 0; - sd->autogain_ignore_frames = 0; - gspca_dev->exp_too_high_cnt = 0; - gspca_dev->exp_too_low_cnt = 0; - atomic_set(&sd->avg_lum, -1); - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - sd_init(gspca_dev); -} - -static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i, header_size = (sd->bridge == BRIDGE_103) ? 18 : 12; - - /* frames start with: - * ff ff 00 c4 c4 96 synchro - * 00 (unknown) - * xx (frame sequence / size / compression) - * (xx) (idem - extra byte for sn9c103) - * ll mm brightness sum inside auto exposure - * ll mm brightness sum outside auto exposure - * (xx xx xx xx xx) audio values for snc103 - */ - for (i = 0; i < len; i++) { - switch (sd->header_read) { - case 0: - if (data[i] == 0xff) - sd->header_read++; - break; - case 1: - if (data[i] == 0xff) - sd->header_read++; - else - sd->header_read = 0; - break; - case 2: - if (data[i] == 0x00) - sd->header_read++; - else if (data[i] != 0xff) - sd->header_read = 0; - break; - case 3: - if (data[i] == 0xc4) - sd->header_read++; - else if (data[i] == 0xff) - sd->header_read = 1; - else - sd->header_read = 0; - break; - case 4: - if (data[i] == 0xc4) - sd->header_read++; - else if (data[i] == 0xff) - sd->header_read = 1; - else - sd->header_read = 0; - break; - case 5: - if (data[i] == 0x96) - sd->header_read++; - else if (data[i] == 0xff) - sd->header_read = 1; - else - sd->header_read = 0; - break; - default: - sd->header[sd->header_read - 6] = data[i]; - sd->header_read++; - if (sd->header_read == header_size) { - sd->header_read = 0; - return data + i + 1; - } - } - } - return NULL; -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0; - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam = &gspca_dev->cam; - u8 *sof; - - sof = find_sof(gspca_dev, data, len); - if (sof) { - if (sd->bridge == BRIDGE_103) { - fr_h_sz = 18; - lum_offset = 3; - } else { - fr_h_sz = 12; - lum_offset = 2; - } - - len_after_sof = len - (sof - data); - len = (sof - data) - fr_h_sz; - if (len < 0) - len = 0; - } - - if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) { - /* In raw mode we sometimes get some garbage after the frame - ignore this */ - int used; - int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage; - - used = gspca_dev->image_len; - if (used + len > size) - len = size - used; - } - - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); - - if (sof) { - int lum = sd->header[lum_offset] + - (sd->header[lum_offset + 1] << 8); - - /* When exposure changes midway a frame we - get a lum of 0 in this case drop 2 frames - as the frames directly after an exposure - change have an unstable image. Sometimes lum - *really* is 0 (cam used in low light with - low exposure setting), so do not drop frames - if the previous lum was 0 too. */ - if (lum == 0 && sd->prev_avg_lum != 0) { - lum = -1; - sd->frames_to_drop = 2; - sd->prev_avg_lum = 0; - } else - sd->prev_avg_lum = lum; - atomic_set(&sd->avg_lum, lum); - - if (sd->frames_to_drop) - sd->frames_to_drop--; - else - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - - gspca_frame_add(gspca_dev, FIRST_PACKET, sof, len_after_sof); - } -} - -static int sd_querymenu(struct gspca_dev *gspca_dev, - struct v4l2_querymenu *menu) -{ - switch (menu->id) { - case V4L2_CID_POWER_LINE_FREQUENCY: - switch (menu->index) { - case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ - strcpy((char *) menu->name, "NoFliker"); - return 0; - case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ - strcpy((char *) menu->name, "50 Hz"); - return 0; - case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ - strcpy((char *) menu->name, "60 Hz"); - return 0; - } - break; - } - return -EINVAL; -} - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) -static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* interrupt packet data */ - int len) /* interrupt packet length */ -{ - int ret = -EINVAL; - - if (len == 1 && data[0] == 1) { - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); - input_sync(gspca_dev->input_dev); - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); - input_sync(gspca_dev->input_dev); - ret = 0; - } - - return ret; -} -#endif - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, - .querymenu = sd_querymenu, - .dq_callback = do_autogain, -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .int_pkt_scan = sd_int_pkt_scan, -#endif -}; - -/* -- module initialisation -- */ -#define SB(sensor, bridge) \ - .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge - - -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */ - {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */ - {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */ - {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, - {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, - {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)}, - {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)}, -#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE - {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)}, - {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)}, -#endif - {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)}, - {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, - {USB_DEVICE(0x0c45, 0x602a), SB(HV7131D, 102)}, - /* {USB_DEVICE(0x0c45, 0x602b), SB(MI0343, 102)}, */ - {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, - {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, - {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)}, - /* {USB_DEVICE(0x0c45, 0x6030), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */ - /* {USB_DEVICE(0x0c45, 0x6082), SB(MI03XX, 103)}, */ /* MI0343 MI0360 */ - {USB_DEVICE(0x0c45, 0x6083), SB(HV7131D, 103)}, - {USB_DEVICE(0x0c45, 0x608c), SB(HV7131R, 103)}, - /* {USB_DEVICE(0x0c45, 0x608e), SB(CISVF10, 103)}, */ - {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)}, - {USB_DEVICE(0x0c45, 0x60a8), SB(PAS106, 103)}, - {USB_DEVICE(0x0c45, 0x60aa), SB(TAS5130CXX, 103)}, - {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)}, - {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c deleted file mode 100644 index 150b2df40f7f..000000000000 --- a/drivers/media/video/gspca/sonixj.c +++ /dev/null @@ -1,3206 +0,0 @@ -/* - * Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver - * - * Copyright (C) 2009-2011 Jean-François Moine <http://moinejf.free.fr> - * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "sonixj" - -#include <linux/input.h> -#include "gspca.h" -#include "jpeg.h" - -MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); -MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* controls */ -enum e_ctrl { - BRIGHTNESS, - CONTRAST, - COLORS, - BLUE, - RED, - GAMMA, - EXPOSURE, - AUTOGAIN, - GAIN, - HFLIP, - VFLIP, - SHARPNESS, - ILLUM, - FREQ, - NCTRLS /* number of controls */ -}; - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - struct gspca_ctrl ctrls[NCTRLS]; - - atomic_t avg_lum; - u32 exposure; - - struct work_struct work; - struct workqueue_struct *work_thread; - - u32 pktsz; /* (used by pkt_scan) */ - u16 npkt; - s8 nchg; - s8 short_mark; - - u8 quality; /* image quality */ -#define QUALITY_MIN 25 -#define QUALITY_MAX 90 -#define QUALITY_DEF 70 - - u8 reg01; - u8 reg17; - u8 reg18; - u8 flags; - - s8 ag_cnt; -#define AG_CNT_START 13 - - u8 bridge; -#define BRIDGE_SN9C102P 0 -#define BRIDGE_SN9C105 1 -#define BRIDGE_SN9C110 2 -#define BRIDGE_SN9C120 3 - u8 sensor; /* Type of image sensor chip */ - u8 i2c_addr; - - u8 jpeg_hdr[JPEG_HDR_SZ]; -}; -enum sensors { - SENSOR_ADCM1700, - SENSOR_GC0307, - SENSOR_HV7131R, - SENSOR_MI0360, - SENSOR_MI0360B, - SENSOR_MO4000, - SENSOR_MT9V111, - SENSOR_OM6802, - SENSOR_OV7630, - SENSOR_OV7648, - SENSOR_OV7660, - SENSOR_PO1030, - SENSOR_PO2030N, - SENSOR_SOI768, - SENSOR_SP80708, -}; - -static void qual_upd(struct work_struct *work); - -/* device flags */ -#define F_PDN_INV 0x01 /* inverse pin S_PWR_DN / sn_xxx tables */ -#define F_ILLUM 0x02 /* presence of illuminator */ - -/* sn9c1xx definitions */ -/* register 0x01 */ -#define S_PWR_DN 0x01 /* sensor power down */ -#define S_PDN_INV 0x02 /* inverse pin S_PWR_DN */ -#define V_TX_EN 0x04 /* video transfer enable */ -#define LED 0x08 /* output to pin LED */ -#define SCL_SEL_OD 0x20 /* open-drain mode */ -#define SYS_SEL_48M 0x40 /* system clock 0: 24MHz, 1: 48MHz */ -/* register 0x17 */ -#define MCK_SIZE_MASK 0x1f /* sensor master clock */ -#define SEN_CLK_EN 0x20 /* enable sensor clock */ -#define DEF_EN 0x80 /* defect pixel by 0: soft, 1: hard */ - -/* V4L2 controls supported by the driver */ -static void setbrightness(struct gspca_dev *gspca_dev); -static void setcontrast(struct gspca_dev *gspca_dev); -static void setcolors(struct gspca_dev *gspca_dev); -static void setredblue(struct gspca_dev *gspca_dev); -static void setgamma(struct gspca_dev *gspca_dev); -static void setexposure(struct gspca_dev *gspca_dev); -static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); -static void setgain(struct gspca_dev *gspca_dev); -static void sethvflip(struct gspca_dev *gspca_dev); -static void setsharpness(struct gspca_dev *gspca_dev); -static void setillum(struct gspca_dev *gspca_dev); -static void setfreq(struct gspca_dev *gspca_dev); - -static const struct ctrl sd_ctrls[NCTRLS] = { -[BRIGHTNESS] = { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0x80, - }, - .set_control = setbrightness - }, -[CONTRAST] = { - { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0, -#define CONTRAST_MAX 127 - .maximum = CONTRAST_MAX, - .step = 1, - .default_value = 20, - }, - .set_control = setcontrast - }, -[COLORS] = { - { - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Saturation", - .minimum = 0, - .maximum = 40, - .step = 1, -#define COLORS_DEF 25 - .default_value = COLORS_DEF, - }, - .set_control = setcolors - }, -[BLUE] = { - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Blue Balance", - .minimum = 24, - .maximum = 40, - .step = 1, - .default_value = 32, - }, - .set_control = setredblue - }, -[RED] = { - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Red Balance", - .minimum = 24, - .maximum = 40, - .step = 1, - .default_value = 32, - }, - .set_control = setredblue - }, -[GAMMA] = { - { - .id = V4L2_CID_GAMMA, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Gamma", - .minimum = 0, - .maximum = 40, - .step = 1, -#define GAMMA_DEF 20 - .default_value = GAMMA_DEF, - }, - .set_control = setgamma - }, -[EXPOSURE] = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Exposure", - .minimum = 500, - .maximum = 1500, - .step = 1, - .default_value = 1024 - }, - .set_control = setexposure - }, -[AUTOGAIN] = { - { - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Auto Gain", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1 - }, - .set = sd_setautogain, - }, -[GAIN] = { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Gain", - .minimum = 4, - .maximum = 49, - .step = 1, - .default_value = 15 - }, - .set_control = setgain - }, -[HFLIP] = { - { - .id = V4L2_CID_HFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Mirror", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - .set_control = sethvflip - }, -[VFLIP] = { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Vflip", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - .set_control = sethvflip - }, -[SHARPNESS] = { - { - .id = V4L2_CID_SHARPNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Sharpness", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = 90, - }, - .set_control = setsharpness - }, -[ILLUM] = { - { - .id = V4L2_CID_ILLUMINATORS_1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Illuminator / infrared", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - }, - .set_control = setillum - }, -/* ov7630/ov7648/ov7660 only */ -[FREQ] = { - { - .id = V4L2_CID_POWER_LINE_FREQUENCY, - .type = V4L2_CTRL_TYPE_MENU, - .name = "Light frequency filter", - .minimum = 0, - .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ - .step = 1, - .default_value = 1, - }, - .set_control = setfreq - }, -}; - -/* table of the disabled controls */ -static const __u32 ctrl_dis[] = { -[SENSOR_ADCM1700] = (1 << EXPOSURE) | - (1 << AUTOGAIN) | - (1 << GAIN) | - (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - -[SENSOR_GC0307] = (1 << EXPOSURE) | - (1 << GAIN) | - (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - -[SENSOR_HV7131R] = (1 << EXPOSURE) | - (1 << GAIN) | - (1 << HFLIP) | - (1 << FREQ), - -[SENSOR_MI0360] = (1 << EXPOSURE) | - (1 << GAIN) | - (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - -[SENSOR_MI0360B] = (1 << EXPOSURE) | - (1 << GAIN) | - (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - -[SENSOR_MO4000] = (1 << EXPOSURE) | - (1 << GAIN) | - (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - -[SENSOR_MT9V111] = (1 << EXPOSURE) | - (1 << GAIN) | - (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - -[SENSOR_OM6802] = (1 << EXPOSURE) | - (1 << GAIN) | - (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - -[SENSOR_OV7630] = (1 << EXPOSURE) | - (1 << GAIN) | - (1 << HFLIP), - -[SENSOR_OV7648] = (1 << EXPOSURE) | - (1 << GAIN) | - (1 << HFLIP), - -[SENSOR_OV7660] = (1 << EXPOSURE) | - (1 << AUTOGAIN) | - (1 << GAIN) | - (1 << HFLIP) | - (1 << VFLIP), - -[SENSOR_PO1030] = (1 << EXPOSURE) | - (1 << AUTOGAIN) | - (1 << GAIN) | - (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - -[SENSOR_PO2030N] = (1 << FREQ), - -[SENSOR_SOI768] = (1 << EXPOSURE) | - (1 << AUTOGAIN) | - (1 << GAIN) | - (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), - -[SENSOR_SP80708] = (1 << EXPOSURE) | - (1 << AUTOGAIN) | - (1 << GAIN) | - (1 << HFLIP) | - (1 << VFLIP) | - (1 << FREQ), -}; - -static const struct v4l2_pix_format cif_mode[] = { - {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 4 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; -static const struct v4l2_pix_format vga_mode[] = { - {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120 * 4 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2}, - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - /* Note 3 / 8 is not large enough, not even 5 / 8 is ?! */ - .sizeimage = 640 * 480 * 3 / 4 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; - -static const u8 sn_adcm1700[0x1c] = { -/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x43, 0x60, 0x00, 0x1a, 0x00, 0x00, 0x00, -/* reg8 reg9 rega regb regc regd rege regf */ - 0x80, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ - 0x03, 0x00, 0x05, 0x01, 0x05, 0x16, 0x12, 0x42, -/* reg18 reg19 reg1a reg1b */ - 0x06, 0x00, 0x00, 0x00 -}; - -static const u8 sn_gc0307[0x1c] = { -/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x61, 0x62, 0x00, 0x1a, 0x00, 0x00, 0x00, -/* reg8 reg9 rega regb regc regd rege regf */ - 0x80, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ - 0x03, 0x00, 0x03, 0x01, 0x08, 0x28, 0x1e, 0x02, -/* reg18 reg19 reg1a reg1b */ - 0x06, 0x00, 0x00, 0x00 -}; - -static const u8 sn_hv7131[0x1c] = { -/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x03, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20, -/* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ - 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, -/* reg18 reg19 reg1a reg1b */ - 0x0a, 0x00, 0x00, 0x00 -}; - -static const u8 sn_mi0360[0x1c] = { -/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20, -/* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ - 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, -/* reg18 reg19 reg1a reg1b */ - 0x06, 0x00, 0x00, 0x00 -}; - -static const u8 sn_mi0360b[0x1c] = { -/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, -/* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ - 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x40, -/* reg18 reg19 reg1a reg1b */ - 0x06, 0x00, 0x00, 0x00 -}; - -static const u8 sn_mo4000[0x1c] = { -/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18, -/* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ - 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40, -/* reg18 reg19 reg1a reg1b */ - 0x08, 0x00, 0x00, 0x00 -}; - -static const u8 sn_mt9v111[0x1c] = { -/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20, -/* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ - 0x03, 0x00, 0x00, 0x02, 0x1c, 0x28, 0x1e, 0x40, -/* reg18 reg19 reg1a reg1b */ - 0x06, 0x00, 0x00, 0x00 -}; - -static const u8 sn_om6802[0x1c] = { -/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x23, 0x72, 0x00, 0x1a, 0x20, 0x20, 0x19, -/* reg8 reg9 rega regb regc regd rege regf */ - 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ - 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40, -/* reg18 reg19 reg1a reg1b */ - 0x05, 0x00, 0x00, 0x00 -}; - -static const u8 sn_ov7630[0x1c] = { -/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x21, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, -/* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ - 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2, -/* reg18 reg19 reg1a reg1b */ - 0x0b, 0x00, 0x00, 0x00 -}; - -static const u8 sn_ov7648[0x1c] = { -/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20, -/* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ - 0x03, 0x00, 0x00, 0x01, 0x00, 0x28, 0x1e, 0x00, -/* reg18 reg19 reg1a reg1b */ - 0x0b, 0x00, 0x00, 0x00 -}; - -static const u8 sn_ov7660[0x1c] = { -/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, -/* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ - 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20, -/* reg18 reg19 reg1a reg1b */ - 0x07, 0x00, 0x00, 0x00 -}; - -static const u8 sn_po1030[0x1c] = { -/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, -/* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ - 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1e, 0x00, -/* reg18 reg19 reg1a reg1b */ - 0x07, 0x00, 0x00, 0x00 -}; - -static const u8 sn_po2030n[0x1c] = { -/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x63, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, -/* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ - 0x03, 0x00, 0x00, 0x01, 0x14, 0x28, 0x1e, 0x00, -/* reg18 reg19 reg1a reg1b */ - 0x07, 0x00, 0x00, 0x00 -}; - -static const u8 sn_soi768[0x1c] = { -/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x21, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, -/* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ - 0x03, 0x00, 0x00, 0x01, 0x08, 0x28, 0x1e, 0x00, -/* reg18 reg19 reg1a reg1b */ - 0x07, 0x00, 0x00, 0x00 -}; - -static const u8 sn_sp80708[0x1c] = { -/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ - 0x00, 0x63, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20, -/* reg8 reg9 rega regb regc regd rege regf */ - 0x81, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ - 0x03, 0x00, 0x00, 0x03, 0x04, 0x28, 0x1e, 0x00, -/* reg18 reg19 reg1a reg1b */ - 0x07, 0x00, 0x00, 0x00 -}; - -/* sequence specific to the sensors - !! index = SENSOR_xxx */ -static const u8 *sn_tb[] = { -[SENSOR_ADCM1700] = sn_adcm1700, -[SENSOR_GC0307] = sn_gc0307, -[SENSOR_HV7131R] = sn_hv7131, -[SENSOR_MI0360] = sn_mi0360, -[SENSOR_MI0360B] = sn_mi0360b, -[SENSOR_MO4000] = sn_mo4000, -[SENSOR_MT9V111] = sn_mt9v111, -[SENSOR_OM6802] = sn_om6802, -[SENSOR_OV7630] = sn_ov7630, -[SENSOR_OV7648] = sn_ov7648, -[SENSOR_OV7660] = sn_ov7660, -[SENSOR_PO1030] = sn_po1030, -[SENSOR_PO2030N] = sn_po2030n, -[SENSOR_SOI768] = sn_soi768, -[SENSOR_SP80708] = sn_sp80708, -}; - -/* default gamma table */ -static const u8 gamma_def[17] = { - 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99, - 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff -}; -/* gamma for sensor ADCM1700 */ -static const u8 gamma_spec_0[17] = { - 0x0f, 0x39, 0x5a, 0x74, 0x86, 0x95, 0xa6, 0xb4, - 0xbd, 0xc4, 0xcc, 0xd4, 0xd5, 0xde, 0xe4, 0xed, 0xf5 -}; -/* gamma for sensors HV7131R and MT9V111 */ -static const u8 gamma_spec_1[17] = { - 0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d, - 0xa9, 0xb4, 0xbe, 0xc8, 0xd2, 0xdb, 0xe4, 0xed, 0xf5 -}; -/* gamma for sensor GC0307 */ -static const u8 gamma_spec_2[17] = { - 0x14, 0x37, 0x50, 0x6a, 0x7c, 0x8d, 0x9d, 0xab, - 0xb5, 0xbf, 0xc2, 0xcb, 0xd1, 0xd6, 0xdb, 0xe1, 0xeb -}; -/* gamma for sensor SP80708 */ -static const u8 gamma_spec_3[17] = { - 0x0a, 0x2d, 0x4e, 0x68, 0x7d, 0x8f, 0x9f, 0xab, - 0xb7, 0xc2, 0xcc, 0xd3, 0xd8, 0xde, 0xe2, 0xe5, 0xe6 -}; - -/* color matrix and offsets */ -static const u8 reg84[] = { - 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, /* YR YG YB gains */ - 0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00, /* UR UG UB */ - 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */ - 0x00, 0x00, 0x00 /* YUV offsets */ -}; - -#define DELAY 0xdd - -static const u8 adcm1700_sensor_init[][8] = { - {0xa0, 0x51, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xb0, 0x51, 0x04, 0x08, 0x00, 0x00, 0x00, 0x10}, /* reset */ - {DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xb0, 0x51, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10}, - {DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xb0, 0x51, 0x0c, 0xe0, 0x2e, 0x00, 0x00, 0x10}, - {0xb0, 0x51, 0x10, 0x02, 0x02, 0x00, 0x00, 0x10}, - {0xb0, 0x51, 0x14, 0x0e, 0x0e, 0x00, 0x00, 0x10}, - {0xb0, 0x51, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x10}, - {0xb0, 0x51, 0x20, 0x01, 0x00, 0x00, 0x00, 0x10}, - {DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xb0, 0x51, 0x04, 0x04, 0x00, 0x00, 0x00, 0x10}, - {DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xb0, 0x51, 0x04, 0x01, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10}, - {0xb0, 0x51, 0x14, 0x01, 0x00, 0x00, 0x00, 0x10}, - {0xb0, 0x51, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10}, - {} -}; -static const u8 adcm1700_sensor_param1[][8] = { - {0xb0, 0x51, 0x26, 0xf9, 0x01, 0x00, 0x00, 0x10}, /* exposure? */ - {0xd0, 0x51, 0x1e, 0x8e, 0x8e, 0x8e, 0x8e, 0x10}, - - {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10}, - {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10}, - {0xb0, 0x51, 0x32, 0x00, 0x72, 0x00, 0x00, 0x10}, - {0xd0, 0x51, 0x1e, 0xbe, 0xd7, 0xe8, 0xbe, 0x10}, /* exposure? */ - - {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10}, - {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10}, - {0xb0, 0x51, 0x32, 0x00, 0xa2, 0x00, 0x00, 0x10}, - {} -}; -static const u8 gc0307_sensor_init[][8] = { - {0xa0, 0x21, 0x43, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x44, 0xa2, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x01, 0x6a, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x02, 0x70, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x11, 0x05, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x08, 0x02, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x09, 0x01, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x0a, 0xe8, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x0b, 0x02, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x0c, 0x80, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x0d, 0x22, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x0f, 0xb2, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x12, 0x70, 0x00, 0x00, 0x00, 0x10}, - {DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 10ms*/ - {0xa0, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x15, 0xb8, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x16, 0x13, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x17, 0x52, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x18, 0x50, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x1e, 0x0d, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x1f, 0x32, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x61, 0x90, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x63, 0x70, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x65, 0x98, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x67, 0x90, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x04, 0x96, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x45, 0x27, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x47, 0x2c, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x43, 0x47, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x44, 0xd8, 0x00, 0x00, 0x00, 0x10}, - {} -}; -static const u8 gc0307_sensor_param1[][8] = { - {0xa0, 0x21, 0x68, 0x13, 0x00, 0x00, 0x00, 0x10}, - {0xd0, 0x21, 0x61, 0x80, 0x00, 0x80, 0x00, 0x10}, - {0xc0, 0x21, 0x65, 0x80, 0x00, 0x80, 0x00, 0x10}, - {0xc0, 0x21, 0x63, 0xa0, 0x00, 0xa6, 0x00, 0x10}, -/*param3*/ - {0xa0, 0x21, 0x01, 0x6e, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x21, 0x02, 0x88, 0x00, 0x00, 0x00, 0x10}, - {} -}; - -static const u8 hv7131r_sensor_init[][8] = { - {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, - {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10}, - {0xd1, 0x11, 0x40, 0xff, 0x7f, 0x7f, 0x7f, 0x10}, -/* {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10}, */ - {0xd1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x11, 0x14, 0x01, 0xe2, 0x02, 0x82, 0x10}, -/* {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, */ - - {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10}, - {0xc1, 0x11, 0x25, 0x00, 0x61, 0xa8, 0x00, 0x10}, - {0xa1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10}, - {0xc1, 0x11, 0x31, 0x20, 0x2e, 0x20, 0x00, 0x10}, - {0xc1, 0x11, 0x25, 0x00, 0xc3, 0x50, 0x00, 0x10}, - {0xa1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */ - {0xc1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */ - - {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10}, - - {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10}, - /* set sensor clock */ - {} -}; -static const u8 mi0360_sensor_init[][8] = { - {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10}, - {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10}, - {0xd1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10}, - {0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10}, - {0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10}, - {0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10}, - {0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10}, - {0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10}, - {0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10}, - {0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10}, - - {0xb1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x2b, 0x00, 0xa0, 0x00, 0xb0, 0x10}, - {0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0xa0, 0x10}, - - {0xb1, 0x5d, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */ - {0xb1, 0x5d, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */ - - {0xd1, 0x5d, 0x2b, 0x00, 0xb9, 0x00, 0xe3, 0x10}, - {0xd1, 0x5d, 0x2d, 0x00, 0x5f, 0x00, 0xb9, 0x10}, /* 42 */ -/* {0xb1, 0x5d, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */ -/* {0xb1, 0x5d, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */ - {0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */ - {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */ - {} -}; -static const u8 mi0360b_sensor_init[][8] = { - {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, - {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/ - {0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10}, - {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/ - {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10}, - {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10}, - {0xd1, 0x5d, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10}, - {0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10}, - {0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10}, - {0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10}, - {0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10}, - {0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10}, - {0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10}, - - {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10}, - {0xd1, 0x5d, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10}, - {0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10}, - {} -}; -static const u8 mi0360b_sensor_param1[][8] = { - {0xb1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x06, 0x00, 0x53, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */ - - {0xd1, 0x5d, 0x2b, 0x00, 0xd1, 0x01, 0xc9, 0x10}, - {0xd1, 0x5d, 0x2d, 0x00, 0xed, 0x00, 0xd1, 0x10}, - {0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */ - {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */ - {} -}; -static const u8 mo4000_sensor_init[][8] = { - {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10}, - {} -}; -static const u8 mt9v111_sensor_init[][8] = { - {0xb1, 0x5c, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, /* reset? */ - {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ - {0xb1, 0x5c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */ - {0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */ - {0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, /* op mode ctrl */ - {0xb1, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, /* sensor select */ - {0xb1, 0x5c, 0x08, 0x00, 0x08, 0x00, 0x00, 0x10}, /* row start */ - {0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, /* col start */ - {0xb1, 0x5c, 0x03, 0x01, 0xe7, 0x00, 0x00, 0x10}, /* window height */ - {0xb1, 0x5c, 0x04, 0x02, 0x87, 0x00, 0x00, 0x10}, /* window width */ - {0xb1, 0x5c, 0x07, 0x30, 0x02, 0x00, 0x00, 0x10}, /* output ctrl */ - {0xb1, 0x5c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10}, /* shutter delay */ - {0xb1, 0x5c, 0x12, 0x00, 0xb0, 0x00, 0x00, 0x10}, /* zoom col start */ - {0xb1, 0x5c, 0x13, 0x00, 0x7c, 0x00, 0x00, 0x10}, /* zoom row start */ - {0xb1, 0x5c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* digital zoom */ - {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, /* read mode */ - {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, - {} -}; -static const u8 mt9v111_sensor_param1[][8] = { - {0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xad, 0x10}, /* G1 and B gains */ - {0xd1, 0x5c, 0x2d, 0x00, 0xad, 0x00, 0x33, 0x10}, /* R and G2 gains */ - {0xb1, 0x5c, 0x06, 0x00, 0x40, 0x00, 0x00, 0x10}, /* vert blanking */ - {0xb1, 0x5c, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10}, /* horiz blanking */ - {0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */ - {} -}; -static const u8 om6802_init0[2][8] = { -/*fixme: variable*/ - {0xa0, 0x34, 0x29, 0x0e, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x34, 0x23, 0xb0, 0x00, 0x00, 0x00, 0x10}, -}; -static const u8 om6802_sensor_init[][8] = { - {0xa0, 0x34, 0xdf, 0x6d, 0x00, 0x00, 0x00, 0x10}, - /* factory mode */ - {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10}, - /* output raw RGB */ - {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10}, -/* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */ - {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10}, - /* auto-exposure speed (0) / white balance mode (auto RGB) */ -/* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10}, - * set color mode */ -/* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10}, - * max AGC value in AE */ -/* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10}, - * preset AGC */ -/* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10}, - * preset brightness */ -/* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10}, - * preset contrast */ -/* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10}, - * preset gamma */ - {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10}, - /* luminance mode (0x4f -> AutoExpo on) */ - {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10}, - /* preset shutter */ -/* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10}, - * auto frame rate */ -/* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */ - {0xa0, 0x34, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10}, - {} -}; -static const u8 om6802_sensor_param1[][8] = { - {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, - {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, - {} -}; -static const u8 ov7630_sensor_init[][8] = { - {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10}, - {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ - {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10}, - {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ - {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, -/* win: i2c_r from 00 to 80 */ - {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10}, - {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10}, -/* HDG: 0x11 was 0x00 change to 0x01 for better exposure (15 fps instead of 30) - 0x13 was 0xc0 change to 0xc3 for auto gain and exposure */ - {0xd1, 0x21, 0x11, 0x01, 0x48, 0xc3, 0x00, 0x10}, - {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10}, - {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10}, - {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10}, - {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10}, - {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10}, - {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10}, - {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10}, - {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10}, - {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10}, - {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10}, - {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10}, - {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10}, - {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10}, - {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10}, - {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10}, - {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10}, - {} -}; -static const u8 ov7630_sensor_param1[][8] = { - {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, -/*fixme: + 0x12, 0x04*/ -/* {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, * COMN - * set by setvflip */ - {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10}, -/* */ -/* {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */ -/* {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */ -/* */ - {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10}, -/* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */ - {} -}; - -static const u8 ov7648_sensor_init[][8] = { - {0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */ - {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ - {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10}, - {0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10}, - {0xc1, 0x21, 0x13, 0xa0, 0x04, 0x84, 0x00, 0x10}, - {0xd1, 0x21, 0x17, 0x1a, 0x02, 0xba, 0xf4, 0x10}, - {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x21, 0x1f, 0x41, 0xc0, 0x80, 0x80, 0x10}, - {0xd1, 0x21, 0x23, 0xde, 0xa0, 0x80, 0x32, 0x10}, - {0xd1, 0x21, 0x27, 0xfe, 0xa0, 0x00, 0x91, 0x10}, - {0xd1, 0x21, 0x2b, 0x00, 0x88, 0x85, 0x80, 0x10}, - {0xc1, 0x21, 0x2f, 0x9c, 0x00, 0xc4, 0x00, 0x10}, - {0xd1, 0x21, 0x60, 0xa6, 0x60, 0x88, 0x12, 0x10}, - {0xd1, 0x21, 0x64, 0x88, 0x00, 0x00, 0x94, 0x10}, - {0xd1, 0x21, 0x68, 0x7a, 0x0c, 0x00, 0x00, 0x10}, - {0xd1, 0x21, 0x6c, 0x11, 0x33, 0x22, 0x00, 0x10}, - {0xd1, 0x21, 0x70, 0x11, 0x00, 0x10, 0x50, 0x10}, - {0xd1, 0x21, 0x74, 0x20, 0x06, 0x00, 0xb5, 0x10}, - {0xd1, 0x21, 0x78, 0x8a, 0x00, 0x00, 0x00, 0x10}, - {0xb1, 0x21, 0x7c, 0x00, 0x43, 0x00, 0x00, 0x10}, - - {0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10}, -/* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */ -/* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */ -/* {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, set by setfreq */ - {} -}; -static const u8 ov7648_sensor_param1[][8] = { -/* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */ -/* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, * COMN - * set by setvflip */ - {0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10}, -/* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */ -/* {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, * GAIN - def */ -/* {0xb1, 0x21, 0x01, 0x6c, 0x6c, 0x00, 0x00, 0x10}, * B R - def: 80 */ -/*...*/ - {0xa1, 0x21, 0x11, 0x81, 0x00, 0x00, 0x00, 0x10}, /* CLKRC */ -/* {0xa1, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */ -/* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */ -/* {0xa1, 0x21, 0x2a, 0x91, 0x00, 0x00, 0x00, 0x10}, jfm done */ -/* {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */ -/* {0xb1, 0x21, 0x01, 0x64, 0x84, 0x00, 0x00, 0x10}, * B R - def: 80 */ - - {} -}; - -static const u8 ov7660_sensor_init[][8] = { - {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */ - {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ - {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10}, - /* Outformat = rawRGB */ - {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */ - {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10}, - /* GAIN BLUE RED VREF */ - {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10}, - /* COM 1 BAVE GEAVE AECHH */ - {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */ - {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */ - {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10}, - /* AECH CLKRC COM7 COM8 */ - {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */ - {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10}, - /* HSTART HSTOP VSTRT VSTOP */ - {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */ - {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */ - {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10}, - /* BOS GBOS GROS ROS (BGGR offset) */ -/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */ - {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10}, - /* AEW AEB VPT BBIAS */ - {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10}, - /* GbBIAS RSVD EXHCH EXHCL */ - {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10}, - /* RBIAS ADVFL ASDVFH YAVE */ - {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10}, - /* HSYST HSYEN HREF */ - {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */ - {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10}, - /* ADC ACOM OFON TSLB */ - {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10}, - /* COM11 COM12 COM13 COM14 */ - {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10}, - /* EDGE COM15 COM16 COM17 */ - {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */ - {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */ - {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */ - {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */ - {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */ - {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */ - {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */ - {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */ - {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */ - {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10}, - /* LCC1 LCC2 LCC3 LCC4 */ - {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */ - {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */ - {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10}, - /* band gap reference [0:3] DBLV */ - {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */ - {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */ - {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */ - {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */ - {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */ - {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */ - {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */ - {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */ - {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */ - {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */ -/* not in all ms-win traces*/ - {0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10}, - {} -}; -static const u8 ov7660_sensor_param1[][8] = { - {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */ - /* bits[3..0]reserved */ - {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10}, - /* VREF vertical frame ctrl */ - {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */ - {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */ - {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */ - {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */ -/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */ -/****** (some exchanges in the win trace) ******/ -/*fixme:param2*/ - {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */ - {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */ - {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */ - {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */ -/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */ -/****** (some exchanges in the win trace) ******/ -/******!! startsensor KO if changed !!****/ -/*fixme: param3*/ - {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10}, - {} -}; - -static const u8 po1030_sensor_init[][8] = { -/* the sensor registers are described in m5602/m5602_po1030.h */ - {0xa1, 0x6e, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x10}, /* sensor reset */ - {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */ - {0xa1, 0x6e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x6e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x04, 0x02, 0xb1, 0x02, 0x39, 0x10}, - {0xd1, 0x6e, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x0c, 0x02, 0x7f, 0x01, 0xe0, 0x10}, - {0xd1, 0x6e, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10}, - {0xd1, 0x6e, 0x16, 0x85, 0x40, 0x4a, 0x40, 0x10}, /* r/g1/b/g2 gains */ - {0xc1, 0x6e, 0x1a, 0x00, 0x80, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x1d, 0x08, 0x03, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x23, 0x00, 0xb0, 0x00, 0x94, 0x10}, - {0xd1, 0x6e, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10}, - {0xb1, 0x6e, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x2d, 0x14, 0x35, 0x61, 0x84, 0x10}, /* gamma corr */ - {0xd1, 0x6e, 0x31, 0xa2, 0xbd, 0xd8, 0xff, 0x10}, - {0xd1, 0x6e, 0x35, 0x06, 0x1e, 0x12, 0x02, 0x10}, /* color matrix */ - {0xd1, 0x6e, 0x39, 0xaa, 0x53, 0x37, 0xd5, 0x10}, - {0xa1, 0x6e, 0x3d, 0xf2, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x3e, 0x00, 0x00, 0x80, 0x03, 0x10}, - {0xd1, 0x6e, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10}, - {0xc1, 0x6e, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10}, - {0xd1, 0x6e, 0x4b, 0x02, 0xef, 0x08, 0xcd, 0x10}, - {0xd1, 0x6e, 0x4f, 0x00, 0xd0, 0x00, 0xa0, 0x10}, - {0xd1, 0x6e, 0x53, 0x01, 0xaa, 0x01, 0x40, 0x10}, - {0xd1, 0x6e, 0x5a, 0x50, 0x04, 0x30, 0x03, 0x10}, /* raw rgb bayer */ - {0xa1, 0x6e, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x5f, 0x10, 0x40, 0xff, 0x00, 0x10}, - - {0xd1, 0x6e, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xc1, 0x6e, 0x73, 0x10, 0x80, 0xeb, 0x00, 0x10}, - {} -}; -static const u8 po1030_sensor_param1[][8] = { -/* from ms-win traces - these values change with auto gain/expo/wb.. */ - {0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10}, -/* mean values */ - {0xc1, 0x6e, 0x1a, 0x02, 0xd4, 0xa4, 0x00, 0x10}, /* integlines */ - {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, /* global gain */ - {0xc1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10}, /* r/g1/b gains */ - - {0xa1, 0x6e, 0x1d, 0x08, 0x00, 0x00, 0x00, 0x10}, /* control1 */ - {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, /* frameheight */ - {0xa1, 0x6e, 0x07, 0xd5, 0x00, 0x00, 0x00, 0x10}, -/* {0xc1, 0x6e, 0x16, 0x49, 0x40, 0x45, 0x00, 0x10}, */ - {} -}; - -static const u8 po2030n_sensor_init[][8] = { - {0xa1, 0x6e, 0x1e, 0x1a, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x6e, 0x1f, 0x99, 0x00, 0x00, 0x00, 0x10}, - {DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */ - {0xa1, 0x6e, 0x1e, 0x0a, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x6e, 0x1f, 0x19, 0x00, 0x00, 0x00, 0x10}, - {DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */ - {0xa1, 0x6e, 0x20, 0x44, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x6e, 0x05, 0x70, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x08, 0x00, 0xd0, 0x00, 0x08, 0x10}, - {0xd1, 0x6e, 0x0c, 0x03, 0x50, 0x01, 0xe8, 0x10}, - {0xd1, 0x6e, 0x1d, 0x20, 0x0a, 0x19, 0x44, 0x10}, - {0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x29, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x35, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x39, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x45, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x49, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x4d, 0x00, 0x00, 0x00, 0xed, 0x10}, - {0xd1, 0x6e, 0x51, 0x17, 0x4a, 0x2f, 0xc0, 0x10}, - {0xd1, 0x6e, 0x55, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x59, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x61, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x69, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x71, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x79, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x85, 0x00, 0x00, 0x00, 0x08, 0x10}, - {0xd1, 0x6e, 0x89, 0x01, 0xe8, 0x00, 0x01, 0x10}, - {0xa1, 0x6e, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x01, 0x10}, - {0xd1, 0x6e, 0x29, 0xe6, 0x00, 0xbd, 0x03, 0x10}, - {0xd1, 0x6e, 0x2d, 0x41, 0x38, 0x68, 0x40, 0x10}, - {0xd1, 0x6e, 0x31, 0x2b, 0x00, 0x36, 0x00, 0x10}, - {0xd1, 0x6e, 0x35, 0x30, 0x30, 0x08, 0x00, 0x10}, - {0xd1, 0x6e, 0x39, 0x00, 0x00, 0x33, 0x06, 0x10}, - {0xb1, 0x6e, 0x3d, 0x06, 0x02, 0x00, 0x00, 0x10}, - {} -}; -static const u8 po2030n_sensor_param1[][8] = { - {0xa1, 0x6e, 0x1a, 0x01, 0x00, 0x00, 0x00, 0x10}, - {DELAY, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 8ms */ - {0xa1, 0x6e, 0x1b, 0xf4, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, - {0xd1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x40, 0x10}, /* RGBG gains */ -/*param2*/ - {0xa1, 0x6e, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x6e, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10}, - {} -}; - -static const u8 soi768_sensor_init[][8] = { - {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */ - {DELAY, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 96ms */ - {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10}, - {} -}; -static const u8 soi768_sensor_param1[][8] = { - {0xa1, 0x21, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xb1, 0x21, 0x01, 0x7f, 0x7f, 0x00, 0x00, 0x10}, -/* */ -/* {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, */ -/* {0xa1, 0x21, 0x2d, 0x25, 0x00, 0x00, 0x00, 0x10}, */ - {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, -/* {0xb1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, */ - {0xa1, 0x21, 0x02, 0x8d, 0x00, 0x00, 0x00, 0x10}, -/* the next sequence should be used for auto gain */ - {0xa1, 0x21, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10}, - /* global gain ? : 07 - change with 0x15 at the end */ - {0xa1, 0x21, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x10}, /* ???? : 063f */ - {0xa1, 0x21, 0x04, 0x06, 0x00, 0x00, 0x00, 0x10}, - {0xb1, 0x21, 0x2d, 0x63, 0x03, 0x00, 0x00, 0x10}, - /* exposure ? : 0200 - change with 0x1e at the end */ - {} -}; - -static const u8 sp80708_sensor_init[][8] = { - {0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x10, 0x40, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x11, 0x4e, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x12, 0x53, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x15, 0x80, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x19, 0x18, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x1a, 0x10, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x1c, 0x28, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x1d, 0x02, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x26, 0x04, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x27, 0x1e, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x28, 0x5a, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x29, 0x28, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x2a, 0x78, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x2c, 0xf7, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x2d, 0x2d, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x2e, 0xd5, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x39, 0x42, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x3a, 0x67, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x3b, 0x87, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x3c, 0xa3, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x3d, 0xb0, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x3e, 0xbc, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x3f, 0xc8, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x40, 0xd4, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x41, 0xdf, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x42, 0xea, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x43, 0xf5, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x45, 0x80, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x46, 0x60, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x47, 0x50, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x48, 0x30, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x49, 0x01, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x4d, 0xae, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x4e, 0x03, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x4f, 0x66, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x50, 0x1c, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x44, 0x10, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x4a, 0x30, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x51, 0x80, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x52, 0x80, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x53, 0x80, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x54, 0x80, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x55, 0x80, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x56, 0x80, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x57, 0xe0, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x58, 0xc0, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x59, 0xab, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x5a, 0xa0, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x5b, 0x99, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x5c, 0x90, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x5e, 0x24, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x61, 0x73, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x63, 0x42, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x64, 0x42, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x65, 0x42, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x66, 0x24, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x67, 0x24, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x68, 0x08, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x2f, 0xc9, 0x00, 0x00, 0x00, 0x10}, - {} -}; -static const u8 sp80708_sensor_param1[][8] = { - {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x03, 0x01, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x04, 0xa4, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x14, 0x3f, 0x00, 0x00, 0x00, 0x10}, - {0xa1, 0x18, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10}, - {0xb1, 0x18, 0x11, 0x40, 0x40, 0x00, 0x00, 0x10}, - {} -}; - -static const u8 (*sensor_init[])[8] = { -[SENSOR_ADCM1700] = adcm1700_sensor_init, -[SENSOR_GC0307] = gc0307_sensor_init, -[SENSOR_HV7131R] = hv7131r_sensor_init, -[SENSOR_MI0360] = mi0360_sensor_init, -[SENSOR_MI0360B] = mi0360b_sensor_init, -[SENSOR_MO4000] = mo4000_sensor_init, -[SENSOR_MT9V111] = mt9v111_sensor_init, -[SENSOR_OM6802] = om6802_sensor_init, -[SENSOR_OV7630] = ov7630_sensor_init, -[SENSOR_OV7648] = ov7648_sensor_init, -[SENSOR_OV7660] = ov7660_sensor_init, -[SENSOR_PO1030] = po1030_sensor_init, -[SENSOR_PO2030N] = po2030n_sensor_init, -[SENSOR_SOI768] = soi768_sensor_init, -[SENSOR_SP80708] = sp80708_sensor_init, -}; - -/* read <len> bytes to gspca_dev->usb_buf */ -static void reg_r(struct gspca_dev *gspca_dev, - u16 value, int len) -{ - int ret; - - if (gspca_dev->usb_err < 0) - return; -#ifdef GSPCA_DEBUG - if (len > USB_BUF_SZ) { - pr_err("reg_r: buffer overflow\n"); - return; - } -#endif - ret = usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - 0, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - value, 0, - gspca_dev->usb_buf, len, - 500); - PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]); - if (ret < 0) { - pr_err("reg_r err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -static void reg_w1(struct gspca_dev *gspca_dev, - u16 value, - u8 data) -{ - int ret; - - if (gspca_dev->usb_err < 0) - return; - PDEBUG(D_USBO, "reg_w1 [%04x] = %02x", value, data); - gspca_dev->usb_buf[0] = data; - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x08, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - value, - 0, - gspca_dev->usb_buf, 1, - 500); - if (ret < 0) { - pr_err("reg_w1 err %d\n", ret); - gspca_dev->usb_err = ret; - } -} -static void reg_w(struct gspca_dev *gspca_dev, - u16 value, - const u8 *buffer, - int len) -{ - int ret; - - if (gspca_dev->usb_err < 0) - return; - PDEBUG(D_USBO, "reg_w [%04x] = %02x %02x ..", - value, buffer[0], buffer[1]); -#ifdef GSPCA_DEBUG - if (len > USB_BUF_SZ) { - pr_err("reg_w: buffer overflow\n"); - return; - } -#endif - memcpy(gspca_dev->usb_buf, buffer, len); - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x08, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - value, 0, - gspca_dev->usb_buf, len, - 500); - if (ret < 0) { - pr_err("reg_w err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -/* I2C write 1 byte */ -static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret; - - if (gspca_dev->usb_err < 0) - return; - PDEBUG(D_USBO, "i2c_w1 [%02x] = %02x", reg, val); - switch (sd->sensor) { - case SENSOR_ADCM1700: - case SENSOR_OM6802: - case SENSOR_GC0307: /* i2c command = a0 (100 kHz) */ - gspca_dev->usb_buf[0] = 0x80 | (2 << 4); - break; - default: /* i2c command = a1 (400 kHz) */ - gspca_dev->usb_buf[0] = 0x81 | (2 << 4); - break; - } - gspca_dev->usb_buf[1] = sd->i2c_addr; - gspca_dev->usb_buf[2] = reg; - gspca_dev->usb_buf[3] = val; - gspca_dev->usb_buf[4] = 0; - gspca_dev->usb_buf[5] = 0; - gspca_dev->usb_buf[6] = 0; - gspca_dev->usb_buf[7] = 0x10; - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x08, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x08, /* value = i2c */ - 0, - gspca_dev->usb_buf, 8, - 500); - if (ret < 0) { - pr_err("i2c_w1 err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -/* I2C write 8 bytes */ -static void i2c_w8(struct gspca_dev *gspca_dev, - const u8 *buffer) -{ - int ret; - - if (gspca_dev->usb_err < 0) - return; - PDEBUG(D_USBO, "i2c_w8 [%02x] = %02x ..", - buffer[2], buffer[3]); - memcpy(gspca_dev->usb_buf, buffer, 8); - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x08, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x08, 0, /* value, index */ - gspca_dev->usb_buf, 8, - 500); - msleep(2); - if (ret < 0) { - pr_err("i2c_w8 err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -/* sensor read 'len' (1..5) bytes in gspca_dev->usb_buf */ -static void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 mode[8]; - - switch (sd->sensor) { - case SENSOR_ADCM1700: - case SENSOR_OM6802: - case SENSOR_GC0307: /* i2c command = a0 (100 kHz) */ - mode[0] = 0x80 | 0x10; - break; - default: /* i2c command = 91 (400 kHz) */ - mode[0] = 0x81 | 0x10; - break; - } - mode[1] = sd->i2c_addr; - mode[2] = reg; - mode[3] = 0; - mode[4] = 0; - mode[5] = 0; - mode[6] = 0; - mode[7] = 0x10; - i2c_w8(gspca_dev, mode); - msleep(2); - mode[0] = (mode[0] & 0x81) | (len << 4) | 0x02; - mode[2] = 0; - i2c_w8(gspca_dev, mode); - msleep(2); - reg_r(gspca_dev, 0x0a, 5); -} - -static void i2c_w_seq(struct gspca_dev *gspca_dev, - const u8 (*data)[8]) -{ - while ((*data)[0] != 0) { - if ((*data)[0] != DELAY) - i2c_w8(gspca_dev, *data); - else - msleep((*data)[1]); - data++; - } -} - -/* check the ID of the hv7131 sensor */ -/* this sequence is needed because it activates the sensor */ -static void hv7131r_probe(struct gspca_dev *gspca_dev) -{ - i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */ - msleep(10); - reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */ - msleep(10); - i2c_r(gspca_dev, 0, 5); /* read sensor id */ - if (gspca_dev->usb_buf[0] == 0x02 /* chip ID (02 is R) */ - && gspca_dev->usb_buf[1] == 0x09 - && gspca_dev->usb_buf[2] == 0x01) { - PDEBUG(D_PROBE, "Sensor HV7131R found"); - return; - } - pr_warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x\n", - gspca_dev->usb_buf[0], gspca_dev->usb_buf[1], - gspca_dev->usb_buf[2]); -} - -static void mi0360_probe(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i, j; - u16 val = 0; - static const u8 probe_tb[][4][8] = { - { /* mi0360 */ - {0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, - {0x90, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa2, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xb0, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10} - }, - { /* mt9v111 */ - {0xb0, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, - {0x90, 0x5c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x10}, - {0xa2, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, - {} - }, - }; - - for (i = 0; i < ARRAY_SIZE(probe_tb); i++) { - reg_w1(gspca_dev, 0x17, 0x62); - reg_w1(gspca_dev, 0x01, 0x08); - for (j = 0; j < 3; j++) - i2c_w8(gspca_dev, probe_tb[i][j]); - msleep(2); - reg_r(gspca_dev, 0x0a, 5); - val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; - if (probe_tb[i][3][0] != 0) - i2c_w8(gspca_dev, probe_tb[i][3]); - reg_w1(gspca_dev, 0x01, 0x29); - reg_w1(gspca_dev, 0x17, 0x42); - if (val != 0xffff) - break; - } - if (gspca_dev->usb_err < 0) - return; - switch (val) { - case 0x8221: - PDEBUG(D_PROBE, "Sensor mi0360b"); - sd->sensor = SENSOR_MI0360B; - break; - case 0x823a: - PDEBUG(D_PROBE, "Sensor mt9v111"); - sd->sensor = SENSOR_MT9V111; - break; - case 0x8243: - PDEBUG(D_PROBE, "Sensor mi0360"); - break; - default: - PDEBUG(D_PROBE, "Unknown sensor %04x - forced to mi0360", val); - break; - } -} - -static void ov7630_probe(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u16 val; - - /* check ov76xx */ - reg_w1(gspca_dev, 0x17, 0x62); - reg_w1(gspca_dev, 0x01, 0x08); - sd->i2c_addr = 0x21; - i2c_r(gspca_dev, 0x0a, 2); - val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; - reg_w1(gspca_dev, 0x01, 0x29); - reg_w1(gspca_dev, 0x17, 0x42); - if (gspca_dev->usb_err < 0) - return; - if (val == 0x7628) { /* soi768 */ - sd->sensor = SENSOR_SOI768; -/*fixme: only valid for 0c45:613e?*/ - gspca_dev->cam.input_flags = - V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP; - PDEBUG(D_PROBE, "Sensor soi768"); - return; - } - PDEBUG(D_PROBE, "Sensor ov%04x", val); -} - -static void ov7648_probe(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u16 val; - - /* check ov76xx */ - reg_w1(gspca_dev, 0x17, 0x62); - reg_w1(gspca_dev, 0x01, 0x08); - sd->i2c_addr = 0x21; - i2c_r(gspca_dev, 0x0a, 2); - val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; - reg_w1(gspca_dev, 0x01, 0x29); - reg_w1(gspca_dev, 0x17, 0x42); - if ((val & 0xff00) == 0x7600) { /* ov76xx */ - PDEBUG(D_PROBE, "Sensor ov%04x", val); - return; - } - - /* check po1030 */ - reg_w1(gspca_dev, 0x17, 0x62); - reg_w1(gspca_dev, 0x01, 0x08); - sd->i2c_addr = 0x6e; - i2c_r(gspca_dev, 0x00, 2); - val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; - reg_w1(gspca_dev, 0x01, 0x29); - reg_w1(gspca_dev, 0x17, 0x42); - if (gspca_dev->usb_err < 0) - return; - if (val == 0x1030) { /* po1030 */ - PDEBUG(D_PROBE, "Sensor po1030"); - sd->sensor = SENSOR_PO1030; - return; - } - pr_err("Unknown sensor %04x\n", val); -} - -/* 0c45:6142 sensor may be po2030n, gc0305 or gc0307 */ -static void po2030n_probe(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u16 val; - - /* check gc0307 */ - reg_w1(gspca_dev, 0x17, 0x62); - reg_w1(gspca_dev, 0x01, 0x08); - reg_w1(gspca_dev, 0x02, 0x22); - sd->i2c_addr = 0x21; - i2c_r(gspca_dev, 0x00, 1); - val = gspca_dev->usb_buf[4]; - reg_w1(gspca_dev, 0x01, 0x29); /* reset */ - reg_w1(gspca_dev, 0x17, 0x42); - if (val == 0x99) { /* gc0307 (?) */ - PDEBUG(D_PROBE, "Sensor gc0307"); - sd->sensor = SENSOR_GC0307; - return; - } - - /* check po2030n */ - reg_w1(gspca_dev, 0x17, 0x62); - reg_w1(gspca_dev, 0x01, 0x0a); - sd->i2c_addr = 0x6e; - i2c_r(gspca_dev, 0x00, 2); - val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; - reg_w1(gspca_dev, 0x01, 0x29); - reg_w1(gspca_dev, 0x17, 0x42); - if (gspca_dev->usb_err < 0) - return; - if (val == 0x2030) { - PDEBUG(D_PROBE, "Sensor po2030n"); -/* sd->sensor = SENSOR_PO2030N; */ - } else { - pr_err("Unknown sensor ID %04x\n", val); - } -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - - sd->bridge = id->driver_info >> 16; - sd->sensor = id->driver_info >> 8; - sd->flags = id->driver_info; - - cam = &gspca_dev->cam; - if (sd->sensor == SENSOR_ADCM1700) { - cam->cam_mode = cif_mode; - cam->nmodes = ARRAY_SIZE(cif_mode); - } else { - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - } - cam->npkt = 24; /* 24 packets per ISOC message */ - cam->ctrls = sd->ctrls; - - sd->ag_cnt = -1; - sd->quality = QUALITY_DEF; - - INIT_WORK(&sd->work, qual_upd); - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - const u8 *sn9c1xx; - u8 regGpio[] = { 0x29, 0x70 }; /* no audio */ - u8 regF1; - - /* setup a selector by bridge */ - reg_w1(gspca_dev, 0xf1, 0x01); - reg_r(gspca_dev, 0x00, 1); - reg_w1(gspca_dev, 0xf1, 0x00); - reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */ - regF1 = gspca_dev->usb_buf[0]; - if (gspca_dev->usb_err < 0) - return gspca_dev->usb_err; - PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1); - if (gspca_dev->audio) - regGpio[1] |= 0x04; /* with audio */ - switch (sd->bridge) { - case BRIDGE_SN9C102P: - case BRIDGE_SN9C105: - if (regF1 != 0x11) - return -ENODEV; - break; - default: -/* case BRIDGE_SN9C110: */ -/* case BRIDGE_SN9C120: */ - if (regF1 != 0x12) - return -ENODEV; - } - - switch (sd->sensor) { - case SENSOR_MI0360: - mi0360_probe(gspca_dev); - break; - case SENSOR_OV7630: - ov7630_probe(gspca_dev); - break; - case SENSOR_OV7648: - ov7648_probe(gspca_dev); - break; - case SENSOR_PO2030N: - po2030n_probe(gspca_dev); - break; - } - - switch (sd->bridge) { - case BRIDGE_SN9C102P: - reg_w1(gspca_dev, 0x02, regGpio[1]); - break; - default: - reg_w(gspca_dev, 0x01, regGpio, 2); - break; - } - - if (sd->sensor == SENSOR_OM6802) - sd->ctrls[SHARPNESS].def = 0x10; - - /* Note we do not disable the sensor clock here (power saving mode), - as that also disables the button on the cam. */ - reg_w1(gspca_dev, 0xf1, 0x00); - - /* set the i2c address */ - sn9c1xx = sn_tb[sd->sensor]; - sd->i2c_addr = sn9c1xx[9]; - - gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; - if (!(sd->flags & F_ILLUM)) - gspca_dev->ctrl_dis |= (1 << ILLUM); - - return gspca_dev->usb_err; -} - -static u32 expo_adjust(struct gspca_dev *gspca_dev, - u32 expo) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->sensor) { - case SENSOR_GC0307: { - int a, b; - - /* expo = 0..255 -> a = 19..43 */ - a = 19 + expo * 25 / 256; - i2c_w1(gspca_dev, 0x68, a); - a -= 12; - b = a * a * 4; /* heuristic */ - i2c_w1(gspca_dev, 0x03, b >> 8); - i2c_w1(gspca_dev, 0x04, b); - break; - } - case SENSOR_HV7131R: { - u8 Expodoit[] = - { 0xc1, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x16 }; - - Expodoit[3] = expo >> 16; - Expodoit[4] = expo >> 8; - Expodoit[5] = expo; - i2c_w8(gspca_dev, Expodoit); - break; - } - case SENSOR_MI0360: - case SENSOR_MI0360B: { - u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */ - { 0xb1, 0x5d, 0x09, 0x00, 0x00, 0x00, 0x00, 0x16 }; - static const u8 doit[] = /* update sensor */ - { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 }; - static const u8 sensorgo[] = /* sensor on */ - { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 }; - - if (expo > 0x0635) - expo = 0x0635; - else if (expo < 0x0001) - expo = 0x0001; - expoMi[3] = expo >> 8; - expoMi[4] = expo; - i2c_w8(gspca_dev, expoMi); - i2c_w8(gspca_dev, doit); - i2c_w8(gspca_dev, sensorgo); - break; - } - case SENSOR_MO4000: { - u8 expoMof[] = - { 0xa1, 0x21, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x10 }; - u8 expoMo10[] = - { 0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10 }; - static const u8 gainMo[] = - { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d }; - - if (expo > 0x1fff) - expo = 0x1fff; - else if (expo < 0x0001) - expo = 0x0001; - expoMof[3] = (expo & 0x03fc) >> 2; - i2c_w8(gspca_dev, expoMof); - expoMo10[3] = ((expo & 0x1c00) >> 10) - | ((expo & 0x0003) << 4); - i2c_w8(gspca_dev, expoMo10); - i2c_w8(gspca_dev, gainMo); - PDEBUG(D_FRAM, "set exposure %d", - ((expoMo10[3] & 0x07) << 10) - | (expoMof[3] << 2) - | ((expoMo10[3] & 0x30) >> 4)); - break; - } - case SENSOR_MT9V111: { - u8 expo_c1[] = - { 0xb1, 0x5c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x10 }; - - if (expo > 0x0390) - expo = 0x0390; - else if (expo < 0x0060) - expo = 0x0060; - expo_c1[3] = expo >> 8; - expo_c1[4] = expo; - i2c_w8(gspca_dev, expo_c1); - break; - } - case SENSOR_OM6802: { - u8 gainOm[] = - { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 }; - /* preset AGC - works when AutoExpo = off */ - - if (expo > 0x03ff) - expo = 0x03ff; - if (expo < 0x0001) - expo = 0x0001; - gainOm[3] = expo >> 2; - i2c_w8(gspca_dev, gainOm); - reg_w1(gspca_dev, 0x96, expo >> 5); - PDEBUG(D_FRAM, "set exposure %d", gainOm[3]); - break; - } - } - return expo; -} - -static void setbrightness(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - unsigned int expo; - int brightness; - u8 k2; - - brightness = sd->ctrls[BRIGHTNESS].val; - k2 = (brightness - 0x80) >> 2; - switch (sd->sensor) { - case SENSOR_ADCM1700: - if (k2 > 0x1f) - k2 = 0; /* only positive Y offset */ - break; - case SENSOR_HV7131R: - expo = brightness << 12; - if (expo > 0x002dc6c0) - expo = 0x002dc6c0; - else if (expo < 0x02a0) - expo = 0x02a0; - sd->exposure = expo_adjust(gspca_dev, expo); - break; - case SENSOR_MI0360: - case SENSOR_MO4000: - expo = brightness << 4; - sd->exposure = expo_adjust(gspca_dev, expo); - break; - case SENSOR_MI0360B: - expo = brightness << 2; - sd->exposure = expo_adjust(gspca_dev, expo); - break; - case SENSOR_GC0307: - expo = brightness; - sd->exposure = expo_adjust(gspca_dev, expo); - return; /* don't set the Y offset */ - case SENSOR_MT9V111: - expo = brightness << 2; - sd->exposure = expo_adjust(gspca_dev, expo); - return; /* don't set the Y offset */ - case SENSOR_OM6802: - expo = brightness << 2; - sd->exposure = expo_adjust(gspca_dev, expo); - return; /* Y offset already set */ - } - - reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */ -} - -static void setcontrast(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 k2; - u8 contrast[6]; - - k2 = sd->ctrls[CONTRAST].val * 37 / (CONTRAST_MAX + 1) - + 37; /* 37..73 */ - contrast[0] = (k2 + 1) / 2; /* red */ - contrast[1] = 0; - contrast[2] = k2; /* green */ - contrast[3] = 0; - contrast[4] = k2 / 5; /* blue */ - contrast[5] = 0; - reg_w(gspca_dev, 0x84, contrast, sizeof contrast); -} - -static void setcolors(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i, v, colors; - const s16 *uv; - u8 reg8a[12]; /* U & V gains */ - static const s16 uv_com[6] = { /* same as reg84 in signed decimal */ - -24, -38, 64, /* UR UG UB */ - 62, -51, -9 /* VR VG VB */ - }; - static const s16 uv_mi0360b[6] = { - -20, -38, 64, /* UR UG UB */ - 60, -51, -9 /* VR VG VB */ - }; - - colors = sd->ctrls[COLORS].val; - if (sd->sensor == SENSOR_MI0360B) - uv = uv_mi0360b; - else - uv = uv_com; - for (i = 0; i < 6; i++) { - v = uv[i] * colors / COLORS_DEF; - reg8a[i * 2] = v; - reg8a[i * 2 + 1] = (v >> 8) & 0x0f; - } - reg_w(gspca_dev, 0x8a, reg8a, sizeof reg8a); -} - -static void setredblue(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_PO2030N) { - u8 rg1b[] = /* red green1 blue (no g2) */ - {0xc1, 0x6e, 0x16, 0x00, 0x40, 0x00, 0x00, 0x10}; - - /* 0x40 = normal value = gain x 1 */ - rg1b[3] = sd->ctrls[RED].val * 2; - rg1b[5] = sd->ctrls[BLUE].val * 2; - i2c_w8(gspca_dev, rg1b); - return; - } - reg_w1(gspca_dev, 0x05, sd->ctrls[RED].val); -/* reg_w1(gspca_dev, 0x07, 32); */ - reg_w1(gspca_dev, 0x06, sd->ctrls[BLUE].val); -} - -static void setgamma(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i, val; - u8 gamma[17]; - const u8 *gamma_base; - static const u8 delta[17] = { - 0x00, 0x14, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a, - 0x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x00 - }; - - switch (sd->sensor) { - case SENSOR_ADCM1700: - gamma_base = gamma_spec_0; - break; - case SENSOR_HV7131R: - case SENSOR_MI0360B: - case SENSOR_MT9V111: - gamma_base = gamma_spec_1; - break; - case SENSOR_GC0307: - gamma_base = gamma_spec_2; - break; - case SENSOR_SP80708: - gamma_base = gamma_spec_3; - break; - default: - gamma_base = gamma_def; - break; - } - - val = sd->ctrls[GAMMA].val; - for (i = 0; i < sizeof gamma; i++) - gamma[i] = gamma_base[i] - + delta[i] * (val - GAMMA_DEF) / 32; - reg_w(gspca_dev, 0x20, gamma, sizeof gamma); -} - -static void setexposure(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_PO2030N) { - u8 rexpo[] = /* 1a: expo H, 1b: expo M */ - {0xa1, 0x6e, 0x1a, 0x00, 0x40, 0x00, 0x00, 0x10}; - - rexpo[3] = sd->ctrls[EXPOSURE].val >> 8; - i2c_w8(gspca_dev, rexpo); - msleep(6); - rexpo[2] = 0x1b; - rexpo[3] = sd->ctrls[EXPOSURE].val; - i2c_w8(gspca_dev, rexpo); - } -} - -static void setautogain(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (gspca_dev->ctrl_dis & (1 << AUTOGAIN)) - return; - switch (sd->sensor) { - case SENSOR_OV7630: - case SENSOR_OV7648: { - u8 comb; - - if (sd->sensor == SENSOR_OV7630) - comb = 0xc0; - else - comb = 0xa0; - if (sd->ctrls[AUTOGAIN].val) - comb |= 0x03; - i2c_w1(&sd->gspca_dev, 0x13, comb); - return; - } - } - if (sd->ctrls[AUTOGAIN].val) - sd->ag_cnt = AG_CNT_START; - else - sd->ag_cnt = -1; -} - -static void setgain(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_PO2030N) { - u8 rgain[] = /* 15: gain */ - {0xa1, 0x6e, 0x15, 0x00, 0x40, 0x00, 0x00, 0x15}; - - rgain[3] = sd->ctrls[GAIN].val; - i2c_w8(gspca_dev, rgain); - } -} - -static void sethvflip(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 comn; - - switch (sd->sensor) { - case SENSOR_HV7131R: - comn = 0x18; /* clkdiv = 1, ablcen = 1 */ - if (sd->ctrls[VFLIP].val) - comn |= 0x01; - i2c_w1(gspca_dev, 0x01, comn); /* sctra */ - break; - case SENSOR_OV7630: - comn = 0x02; - if (!sd->ctrls[VFLIP].val) - comn |= 0x80; - i2c_w1(gspca_dev, 0x75, comn); - break; - case SENSOR_OV7648: - comn = 0x06; - if (sd->ctrls[VFLIP].val) - comn |= 0x80; - i2c_w1(gspca_dev, 0x75, comn); - break; - case SENSOR_PO2030N: - /* Reg. 0x1E: Timing Generator Control Register 2 (Tgcontrol2) - * (reset value: 0x0A) - * bit7: HM: Horizontal Mirror: 0: disable, 1: enable - * bit6: VM: Vertical Mirror: 0: disable, 1: enable - * bit5: ST: Shutter Selection: 0: electrical, 1: mechanical - * bit4: FT: Single Frame Transfer: 0: disable, 1: enable - * bit3-0: X - */ - comn = 0x0a; - if (sd->ctrls[HFLIP].val) - comn |= 0x80; - if (sd->ctrls[VFLIP].val) - comn |= 0x40; - i2c_w1(&sd->gspca_dev, 0x1e, comn); - break; - } -} - -static void setsharpness(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - reg_w1(gspca_dev, 0x99, sd->ctrls[SHARPNESS].val); -} - -static void setillum(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (gspca_dev->ctrl_dis & (1 << ILLUM)) - return; - switch (sd->sensor) { - case SENSOR_ADCM1700: - reg_w1(gspca_dev, 0x02, /* gpio */ - sd->ctrls[ILLUM].val ? 0x64 : 0x60); - break; - case SENSOR_MT9V111: - reg_w1(gspca_dev, 0x02, - sd->ctrls[ILLUM].val ? 0x77 : 0x74); -/* should have been: */ -/* 0x55 : 0x54); * 370i */ -/* 0x66 : 0x64); * Clip */ - break; - } -} - -static void setfreq(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (gspca_dev->ctrl_dis & (1 << FREQ)) - return; - if (sd->sensor == SENSOR_OV7660) { - u8 com8; - - com8 = 0xdf; /* auto gain/wb/expo */ - switch (sd->ctrls[FREQ].val) { - case 0: /* Banding filter disabled */ - i2c_w1(gspca_dev, 0x13, com8 | 0x20); - break; - case 1: /* 50 hz */ - i2c_w1(gspca_dev, 0x13, com8); - i2c_w1(gspca_dev, 0x3b, 0x0a); - break; - case 2: /* 60 hz */ - i2c_w1(gspca_dev, 0x13, com8); - i2c_w1(gspca_dev, 0x3b, 0x02); - break; - } - } else { - u8 reg2a = 0, reg2b = 0, reg2d = 0; - - /* Get reg2a / reg2d base values */ - switch (sd->sensor) { - case SENSOR_OV7630: - reg2a = 0x08; - reg2d = 0x01; - break; - case SENSOR_OV7648: - reg2a = 0x11; - reg2d = 0x81; - break; - } - - switch (sd->ctrls[FREQ].val) { - case 0: /* Banding filter disabled */ - break; - case 1: /* 50 hz (filter on and framerate adj) */ - reg2a |= 0x80; - reg2b = 0xac; - reg2d |= 0x04; - break; - case 2: /* 60 hz (filter on, no framerate adj) */ - reg2a |= 0x80; - reg2d |= 0x04; - break; - } - i2c_w1(gspca_dev, 0x2a, reg2a); - i2c_w1(gspca_dev, 0x2b, reg2b); - i2c_w1(gspca_dev, 0x2d, reg2d); - } -} - -static void setjpegqual(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - jpeg_set_qual(sd->jpeg_hdr, sd->quality); -#if USB_BUF_SZ < 64 -#error "No room enough in usb_buf for quantization table" -#endif - memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64); - usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x08, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x0100, 0, - gspca_dev->usb_buf, 64, - 500); - memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64); - usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x08, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 0x0140, 0, - gspca_dev->usb_buf, 64, - 500); - - sd->reg18 ^= 0x40; - reg_w1(gspca_dev, 0x18, sd->reg18); -} - -/* JPEG quality update */ -/* This function is executed from a work queue. */ -static void qual_upd(struct work_struct *work) -{ - struct sd *sd = container_of(work, struct sd, work); - struct gspca_dev *gspca_dev = &sd->gspca_dev; - - mutex_lock(&gspca_dev->usb_lock); - PDEBUG(D_STREAM, "qual_upd %d%%", sd->quality); - setjpegqual(gspca_dev); - mutex_unlock(&gspca_dev->usb_lock); -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i; - u8 reg01, reg17; - u8 reg0102[2]; - const u8 *sn9c1xx; - const u8 (*init)[8]; - const u8 *reg9a; - int mode; - static const u8 reg9a_def[] = - {0x00, 0x40, 0x20, 0x00, 0x00, 0x00}; - static const u8 reg9a_spec[] = - {0x00, 0x40, 0x38, 0x30, 0x00, 0x20}; - static const u8 regd4[] = {0x60, 0x00, 0x00}; - static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; - static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; - static const u8 CA_adcm1700[] = - { 0x14, 0xec, 0x0a, 0xf6 }; - static const u8 CA_po2030n[] = - { 0x1e, 0xe2, 0x14, 0xec }; - static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */ - static const u8 CE_gc0307[] = - { 0x32, 0xce, 0x2d, 0xd3 }; - static const u8 CE_ov76xx[] = - { 0x32, 0xdd, 0x32, 0xdd }; - static const u8 CE_po2030n[] = - { 0x14, 0xe7, 0x1e, 0xdd }; - - /* create the JPEG header */ - jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, - 0x21); /* JPEG 422 */ - - /* initialize the bridge */ - sn9c1xx = sn_tb[sd->sensor]; - - /* sensor clock already enabled in sd_init */ - /* reg_w1(gspca_dev, 0xf1, 0x00); */ - reg01 = sn9c1xx[1]; - if (sd->flags & F_PDN_INV) - reg01 ^= S_PDN_INV; /* power down inverted */ - reg_w1(gspca_dev, 0x01, reg01); - - /* configure gpio */ - reg0102[0] = reg01; - reg0102[1] = sn9c1xx[2]; - if (gspca_dev->audio) - reg0102[1] |= 0x04; /* keep the audio connection */ - reg_w(gspca_dev, 0x01, reg0102, 2); - reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2); - reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); - switch (sd->sensor) { - case SENSOR_GC0307: - case SENSOR_OV7660: - case SENSOR_PO1030: - case SENSOR_PO2030N: - case SENSOR_SOI768: - case SENSOR_SP80708: - reg9a = reg9a_spec; - break; - default: - reg9a = reg9a_def; - break; - } - reg_w(gspca_dev, 0x9a, reg9a, 6); - - reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); - - reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); - - reg17 = sn9c1xx[0x17]; - switch (sd->sensor) { - case SENSOR_GC0307: - msleep(50); /*fixme: is it useful? */ - break; - case SENSOR_OM6802: - msleep(10); - reg_w1(gspca_dev, 0x02, 0x73); - reg17 |= SEN_CLK_EN; - reg_w1(gspca_dev, 0x17, reg17); - reg_w1(gspca_dev, 0x01, 0x22); - msleep(100); - reg01 = SCL_SEL_OD | S_PDN_INV; - reg17 &= ~MCK_SIZE_MASK; - reg17 |= 0x04; /* clock / 4 */ - break; - } - reg01 |= SYS_SEL_48M; - reg_w1(gspca_dev, 0x01, reg01); - reg17 |= SEN_CLK_EN; - reg_w1(gspca_dev, 0x17, reg17); - reg01 &= ~S_PWR_DN; /* sensor power on */ - reg_w1(gspca_dev, 0x01, reg01); - reg01 &= ~SCL_SEL_OD; /* remove open-drain mode */ - reg_w1(gspca_dev, 0x01, reg01); - - switch (sd->sensor) { - case SENSOR_HV7131R: - hv7131r_probe(gspca_dev); /*fixme: is it useful? */ - break; - case SENSOR_OM6802: - msleep(10); - reg_w1(gspca_dev, 0x01, reg01); - i2c_w8(gspca_dev, om6802_init0[0]); - i2c_w8(gspca_dev, om6802_init0[1]); - msleep(15); - reg_w1(gspca_dev, 0x02, 0x71); - msleep(150); - break; - case SENSOR_SP80708: - msleep(100); - reg_w1(gspca_dev, 0x02, 0x62); - break; - } - - /* initialize the sensor */ - i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); - - reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]); - reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]); - reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]); - reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]); - reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); - if (sd->sensor == SENSOR_ADCM1700) { - reg_w1(gspca_dev, 0xd2, 0x3a); /* AE_H_SIZE = 116 */ - reg_w1(gspca_dev, 0xd3, 0x30); /* AE_V_SIZE = 96 */ - } else { - reg_w1(gspca_dev, 0xd2, 0x6a); /* AE_H_SIZE = 212 */ - reg_w1(gspca_dev, 0xd3, 0x50); /* AE_V_SIZE = 160 */ - } - reg_w1(gspca_dev, 0xc6, 0x00); - reg_w1(gspca_dev, 0xc7, 0x00); - if (sd->sensor == SENSOR_ADCM1700) { - reg_w1(gspca_dev, 0xc8, 0x2c); /* AW_H_STOP = 352 */ - reg_w1(gspca_dev, 0xc9, 0x24); /* AW_V_STOP = 288 */ - } else { - reg_w1(gspca_dev, 0xc8, 0x50); /* AW_H_STOP = 640 */ - reg_w1(gspca_dev, 0xc9, 0x3c); /* AW_V_STOP = 480 */ - } - reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); - switch (sd->sensor) { - case SENSOR_OM6802: -/* case SENSOR_OV7648: * fixme: sometimes */ - break; - default: - reg17 |= DEF_EN; - break; - } - reg_w1(gspca_dev, 0x17, reg17); - - reg_w1(gspca_dev, 0x05, 0x00); /* red */ - reg_w1(gspca_dev, 0x07, 0x00); /* green */ - reg_w1(gspca_dev, 0x06, 0x00); /* blue */ - reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]); - - setgamma(gspca_dev); - -/*fixme: 8 times with all zeroes and 1 or 2 times with normal values */ - for (i = 0; i < 8; i++) - reg_w(gspca_dev, 0x84, reg84, sizeof reg84); - switch (sd->sensor) { - case SENSOR_ADCM1700: - case SENSOR_OV7660: - case SENSOR_SP80708: - reg_w1(gspca_dev, 0x9a, 0x05); - break; - case SENSOR_GC0307: - case SENSOR_MT9V111: - case SENSOR_MI0360B: - reg_w1(gspca_dev, 0x9a, 0x07); - break; - case SENSOR_OV7630: - case SENSOR_OV7648: - reg_w1(gspca_dev, 0x9a, 0x0a); - break; - case SENSOR_PO2030N: - case SENSOR_SOI768: - reg_w1(gspca_dev, 0x9a, 0x06); - break; - default: - reg_w1(gspca_dev, 0x9a, 0x08); - break; - } - setsharpness(gspca_dev); - - reg_w(gspca_dev, 0x84, reg84, sizeof reg84); - reg_w1(gspca_dev, 0x05, 0x20); /* red */ - reg_w1(gspca_dev, 0x07, 0x20); /* green */ - reg_w1(gspca_dev, 0x06, 0x20); /* blue */ - - init = NULL; - mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - reg01 |= SYS_SEL_48M | V_TX_EN; - reg17 &= ~MCK_SIZE_MASK; - reg17 |= 0x02; /* clock / 2 */ - switch (sd->sensor) { - case SENSOR_ADCM1700: - init = adcm1700_sensor_param1; - break; - case SENSOR_GC0307: - init = gc0307_sensor_param1; - break; - case SENSOR_HV7131R: - case SENSOR_MI0360: - if (!mode) - reg01 &= ~SYS_SEL_48M; /* 640x480: clk 24Mhz */ - reg17 &= ~MCK_SIZE_MASK; - reg17 |= 0x01; /* clock / 1 */ - break; - case SENSOR_MI0360B: - init = mi0360b_sensor_param1; - break; - case SENSOR_MO4000: - if (mode) { /* if 320x240 */ - reg01 &= ~SYS_SEL_48M; /* clk 24Mz */ - reg17 &= ~MCK_SIZE_MASK; - reg17 |= 0x01; /* clock / 1 */ - } - break; - case SENSOR_MT9V111: - init = mt9v111_sensor_param1; - break; - case SENSOR_OM6802: - init = om6802_sensor_param1; - if (!mode) { /* if 640x480 */ - reg17 &= ~MCK_SIZE_MASK; - reg17 |= 0x04; /* clock / 4 */ - } else { - reg01 &= ~SYS_SEL_48M; /* clk 24Mz */ - reg17 &= ~MCK_SIZE_MASK; - reg17 |= 0x02; /* clock / 2 */ - } - break; - case SENSOR_OV7630: - init = ov7630_sensor_param1; - break; - case SENSOR_OV7648: - init = ov7648_sensor_param1; - reg17 &= ~MCK_SIZE_MASK; - reg17 |= 0x01; /* clock / 1 */ - break; - case SENSOR_OV7660: - init = ov7660_sensor_param1; - break; - case SENSOR_PO1030: - init = po1030_sensor_param1; - break; - case SENSOR_PO2030N: - init = po2030n_sensor_param1; - break; - case SENSOR_SOI768: - init = soi768_sensor_param1; - break; - case SENSOR_SP80708: - init = sp80708_sensor_param1; - break; - } - - /* more sensor initialization - param1 */ - if (init != NULL) { - i2c_w_seq(gspca_dev, init); -/* init = NULL; */ - } - - reg_w(gspca_dev, 0xc0, C0, 6); - switch (sd->sensor) { - case SENSOR_ADCM1700: - case SENSOR_GC0307: - case SENSOR_SOI768: - reg_w(gspca_dev, 0xca, CA_adcm1700, 4); - break; - case SENSOR_PO2030N: - reg_w(gspca_dev, 0xca, CA_po2030n, 4); - break; - default: - reg_w(gspca_dev, 0xca, CA, 4); - break; - } - switch (sd->sensor) { - case SENSOR_ADCM1700: - case SENSOR_OV7630: - case SENSOR_OV7648: - case SENSOR_OV7660: - case SENSOR_SOI768: - reg_w(gspca_dev, 0xce, CE_ov76xx, 4); - break; - case SENSOR_GC0307: - reg_w(gspca_dev, 0xce, CE_gc0307, 4); - break; - case SENSOR_PO2030N: - reg_w(gspca_dev, 0xce, CE_po2030n, 4); - break; - default: - reg_w(gspca_dev, 0xce, CE, 4); - /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */ - break; - } - - /* here change size mode 0 -> VGA; 1 -> CIF */ - sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40; - reg_w1(gspca_dev, 0x18, sd->reg18); - setjpegqual(gspca_dev); - - reg_w1(gspca_dev, 0x17, reg17); - reg_w1(gspca_dev, 0x01, reg01); - sd->reg01 = reg01; - sd->reg17 = reg17; - - sethvflip(gspca_dev); - setbrightness(gspca_dev); - setcontrast(gspca_dev); - setcolors(gspca_dev); - setautogain(gspca_dev); - if (!(gspca_dev->ctrl_inac & ((1 << EXPOSURE) | (1 << GAIN)))) { - setexposure(gspca_dev); - setgain(gspca_dev); - } - setfreq(gspca_dev); - - sd->pktsz = sd->npkt = 0; - sd->nchg = sd->short_mark = 0; - sd->work_thread = create_singlethread_workqueue(MODULE_NAME); - - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - static const u8 stophv7131[] = - { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 }; - static const u8 stopmi0360[] = - { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 }; - static const u8 stopov7648[] = - { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 }; - static const u8 stopsoi768[] = - { 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 }; - u8 reg01; - u8 reg17; - - reg01 = sd->reg01; - reg17 = sd->reg17 & ~SEN_CLK_EN; - switch (sd->sensor) { - case SENSOR_ADCM1700: - case SENSOR_GC0307: - case SENSOR_PO2030N: - case SENSOR_SP80708: - reg01 |= LED; - reg_w1(gspca_dev, 0x01, reg01); - reg01 &= ~(LED | V_TX_EN); - reg_w1(gspca_dev, 0x01, reg01); -/* reg_w1(gspca_dev, 0x02, 0x??); * LED off ? */ - break; - case SENSOR_HV7131R: - reg01 &= ~V_TX_EN; - reg_w1(gspca_dev, 0x01, reg01); - i2c_w8(gspca_dev, stophv7131); - break; - case SENSOR_MI0360: - case SENSOR_MI0360B: - reg01 &= ~V_TX_EN; - reg_w1(gspca_dev, 0x01, reg01); -/* reg_w1(gspca_dev, 0x02, 0x40); * LED off ? */ - i2c_w8(gspca_dev, stopmi0360); - break; - case SENSOR_MT9V111: - case SENSOR_OM6802: - case SENSOR_PO1030: - reg01 &= ~V_TX_EN; - reg_w1(gspca_dev, 0x01, reg01); - break; - case SENSOR_OV7630: - case SENSOR_OV7648: - reg01 &= ~V_TX_EN; - reg_w1(gspca_dev, 0x01, reg01); - i2c_w8(gspca_dev, stopov7648); - break; - case SENSOR_OV7660: - reg01 &= ~V_TX_EN; - reg_w1(gspca_dev, 0x01, reg01); - break; - case SENSOR_SOI768: - i2c_w8(gspca_dev, stopsoi768); - break; - } - - reg01 |= SCL_SEL_OD; - reg_w1(gspca_dev, 0x01, reg01); - reg01 |= S_PWR_DN; /* sensor power down */ - reg_w1(gspca_dev, 0x01, reg01); - reg_w1(gspca_dev, 0x17, reg17); - reg01 &= ~SYS_SEL_48M; /* clock 24MHz */ - reg_w1(gspca_dev, 0x01, reg01); - reg01 |= LED; - reg_w1(gspca_dev, 0x01, reg01); - /* Don't disable sensor clock as that disables the button on the cam */ - /* reg_w1(gspca_dev, 0xf1, 0x01); */ -} - -/* called on streamoff with alt==0 and on disconnect */ -/* the usb_lock is held at entry - restore on exit */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->work_thread != NULL) { - mutex_unlock(&gspca_dev->usb_lock); - destroy_workqueue(sd->work_thread); - mutex_lock(&gspca_dev->usb_lock); - sd->work_thread = NULL; - } -} - -#define WANT_REGULAR_AUTOGAIN -#include "autogain_functions.h" - -static void do_autogain(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int delta; - int expotimes; - u8 luma_mean = 130; - u8 luma_delta = 20; - - /* Thanks S., without your advice, autobright should not work :) */ - if (sd->ag_cnt < 0) - return; - if (--sd->ag_cnt >= 0) - return; - sd->ag_cnt = AG_CNT_START; - - delta = atomic_read(&sd->avg_lum); - PDEBUG(D_FRAM, "mean lum %d", delta); - - if (sd->sensor == SENSOR_PO2030N) { - auto_gain_n_exposure(gspca_dev, delta, luma_mean, luma_delta, - 15, 1024); - return; - } - - if (delta < luma_mean - luma_delta || - delta > luma_mean + luma_delta) { - switch (sd->sensor) { - case SENSOR_GC0307: - expotimes = sd->exposure; - expotimes += (luma_mean - delta) >> 6; - if (expotimes < 0) - expotimes = 0; - sd->exposure = expo_adjust(gspca_dev, - (unsigned int) expotimes); - break; - case SENSOR_HV7131R: - expotimes = sd->exposure >> 8; - expotimes += (luma_mean - delta) >> 4; - if (expotimes < 0) - expotimes = 0; - sd->exposure = expo_adjust(gspca_dev, - (unsigned int) (expotimes << 8)); - break; - case SENSOR_OM6802: - case SENSOR_MT9V111: - expotimes = sd->exposure; - expotimes += (luma_mean - delta) >> 2; - if (expotimes < 0) - expotimes = 0; - sd->exposure = expo_adjust(gspca_dev, - (unsigned int) expotimes); - setredblue(gspca_dev); - break; - default: -/* case SENSOR_MO4000: */ -/* case SENSOR_MI0360: */ -/* case SENSOR_MI0360B: */ - expotimes = sd->exposure; - expotimes += (luma_mean - delta) >> 6; - if (expotimes < 0) - expotimes = 0; - sd->exposure = expo_adjust(gspca_dev, - (unsigned int) expotimes); - setredblue(gspca_dev); - break; - } - } -} - -/* set the average luminosity from an isoc marker */ -static void set_lum(struct sd *sd, - u8 *data) -{ - int avg_lum; - - /* w0 w1 w2 - * w3 w4 w5 - * w6 w7 w8 - */ - avg_lum = (data[27] << 8) + data[28] /* w3 */ - - + (data[31] << 8) + data[32] /* w5 */ - - + (data[23] << 8) + data[24] /* w1 */ - - + (data[35] << 8) + data[36] /* w7 */ - - + (data[29] << 10) + (data[30] << 2); /* w4 * 4 */ - avg_lum >>= 10; - atomic_set(&sd->avg_lum, avg_lum); -} - -/* scan the URB packets */ -/* This function is run at interrupt level. */ -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - int i, new_qual; - - /* - * A frame ends on the marker - * ff ff 00 c4 c4 96 .. - * which is 62 bytes long and is followed by various information - * including statuses and luminosity. - * - * A marker may be splitted on two packets. - * - * The 6th byte of a marker contains the bits: - * 0x08: USB full - * 0xc0: frame sequence - * When the bit 'USB full' is set, the frame must be discarded; - * this is also the case when the 2 bytes before the marker are - * not the JPEG end of frame ('ff d9'). - */ - - /* count the packets and their size */ - sd->npkt++; - sd->pktsz += len; - -/*fixme: assumption about the following code: - * - there can be only one marker in a packet - */ - - /* skip the remaining bytes of a short marker */ - i = sd->short_mark; - if (i != 0) { - sd->short_mark = 0; - if (i < 0 /* if 'ff' at end of previous packet */ - && data[0] == 0xff - && data[1] == 0x00) - goto marker_found; - if (data[0] == 0xff && data[1] == 0xff) { - i = 0; - goto marker_found; - } - len -= i; - if (len <= 0) - return; - data += i; - } - - /* search backwards if there is a marker in the packet */ - for (i = len - 1; --i >= 0; ) { - if (data[i] != 0xff) { - i--; - continue; - } - if (data[i + 1] == 0xff) { - - /* (there may be 'ff ff' inside a marker) */ - if (i + 2 >= len || data[i + 2] == 0x00) - goto marker_found; - } - } - - /* no marker found */ - /* add the JPEG header if first fragment */ - if (data[len - 1] == 0xff) - sd->short_mark = -1; - if (gspca_dev->last_packet_type == LAST_PACKET) - gspca_frame_add(gspca_dev, FIRST_PACKET, - sd->jpeg_hdr, JPEG_HDR_SZ); - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); - return; - - /* marker found */ - /* if some error, discard the frame and decrease the quality */ -marker_found: - new_qual = 0; - if (i > 2) { - if (data[i - 2] != 0xff || data[i - 1] != 0xd9) { - gspca_dev->last_packet_type = DISCARD_PACKET; - new_qual = -3; - } - } else if (i + 6 < len) { - if (data[i + 6] & 0x08) { - gspca_dev->last_packet_type = DISCARD_PACKET; - new_qual = -5; - } - } - - gspca_frame_add(gspca_dev, LAST_PACKET, data, i); - - /* compute the filling rate and a new JPEG quality */ - if (new_qual == 0) { - int r; - - r = (sd->pktsz * 100) / - (sd->npkt * - gspca_dev->urb[0]->iso_frame_desc[0].length); - if (r >= 85) - new_qual = -3; - else if (r < 75) - new_qual = 2; - } - if (new_qual != 0) { - sd->nchg += new_qual; - if (sd->nchg < -6 || sd->nchg >= 12) { - sd->nchg = 0; - new_qual += sd->quality; - if (new_qual < QUALITY_MIN) - new_qual = QUALITY_MIN; - else if (new_qual > QUALITY_MAX) - new_qual = QUALITY_MAX; - if (new_qual != sd->quality) { - sd->quality = new_qual; - queue_work(sd->work_thread, &sd->work); - } - } - } else { - sd->nchg = 0; - } - sd->pktsz = sd->npkt = 0; - - /* if the marker is smaller than 62 bytes, - * memorize the number of bytes to skip in the next packet */ - if (i + 62 > len) { /* no more usable data */ - sd->short_mark = i + 62 - len; - return; - } - if (sd->ag_cnt >= 0) - set_lum(sd, data + i); - - /* if more data, start a new frame */ - i += 62; - if (i < len) { - data += i; - len -= i; - gspca_frame_add(gspca_dev, FIRST_PACKET, - sd->jpeg_hdr, JPEG_HDR_SZ); - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); - } -} - -static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->ctrls[AUTOGAIN].val = val; - if (val) - gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN); - else - gspca_dev->ctrl_inac &= ~(1 << EXPOSURE) & ~(1 << GAIN); - if (gspca_dev->streaming) - setautogain(gspca_dev); - return gspca_dev->usb_err; -} - -static int sd_querymenu(struct gspca_dev *gspca_dev, - struct v4l2_querymenu *menu) -{ - switch (menu->id) { - case V4L2_CID_POWER_LINE_FREQUENCY: - switch (menu->index) { - case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ - strcpy((char *) menu->name, "NoFliker"); - return 0; - case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ - strcpy((char *) menu->name, "50 Hz"); - return 0; - case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ - strcpy((char *) menu->name, "60 Hz"); - return 0; - } - break; - } - return -EINVAL; -} - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) -static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* interrupt packet data */ - int len) /* interrupt packet length */ -{ - int ret = -EINVAL; - - if (len == 1 && data[0] == 1) { - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); - input_sync(gspca_dev->input_dev); - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); - input_sync(gspca_dev->input_dev); - ret = 0; - } - - return ret; -} -#endif - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .ctrls = sd_ctrls, - .nctrls = NCTRLS, - .config = sd_config, - .init = sd_init, - .start = sd_start, - .stopN = sd_stopN, - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, - .dq_callback = do_autogain, - .querymenu = sd_querymenu, -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .int_pkt_scan = sd_int_pkt_scan, -#endif -}; - -/* -- module initialisation -- */ -#define BS(bridge, sensor) \ - .driver_info = (BRIDGE_ ## bridge << 16) \ - | (SENSOR_ ## sensor << 8) -#define BSF(bridge, sensor, flags) \ - .driver_info = (BRIDGE_ ## bridge << 16) \ - | (SENSOR_ ## sensor << 8) \ - | (flags) -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x0458, 0x7025), BSF(SN9C120, MI0360B, F_PDN_INV)}, - {USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)}, - {USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, F_PDN_INV)}, - {USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, F_PDN_INV)}, - {USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)}, - {USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)}, - {USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)}, - {USB_DEVICE(0x06f8, 0x3004), BS(SN9C105, OV7660)}, - {USB_DEVICE(0x06f8, 0x3008), BS(SN9C105, OV7660)}, -/* {USB_DEVICE(0x0c45, 0x603a), BS(SN9C102P, OV7648)}, */ - {USB_DEVICE(0x0c45, 0x6040), BS(SN9C102P, HV7131R)}, -/* {USB_DEVICE(0x0c45, 0x607a), BS(SN9C102P, OV7648)}, */ -/* {USB_DEVICE(0x0c45, 0x607b), BS(SN9C102P, OV7660)}, */ - {USB_DEVICE(0x0c45, 0x607c), BS(SN9C102P, HV7131R)}, -/* {USB_DEVICE(0x0c45, 0x607e), BS(SN9C102P, OV7630)}, */ - {USB_DEVICE(0x0c45, 0x60c0), BSF(SN9C105, MI0360, F_ILLUM)}, - /* or MT9V111 */ -/* {USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */ -/* {USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */ -/* {USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */ - {USB_DEVICE(0x0c45, 0x60ce), BS(SN9C105, SP80708)}, - {USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)}, -/* {USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */ -/* {USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */ -/* {USB_DEVICE(0x0c45, 0x60f2), BS(SN9C105, OV7660)}, */ - {USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)}, - {USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)}, - {USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)}, - {USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)}, /*sn9c128*/ - {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, PO2030N)}, /* /GC0305*/ -/* {USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */ - {USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)}, /*sn9c128*/ - {USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)}, /*sn9c128*/ - {USB_DEVICE(0x0c45, 0x610c), BS(SN9C120, HV7131R)}, /*sn9c128*/ - {USB_DEVICE(0x0c45, 0x610e), BS(SN9C120, OV7630)}, /*sn9c128*/ -/* {USB_DEVICE(0x0c45, 0x610f), BS(SN9C120, S5K53BEB)}, */ -/* {USB_DEVICE(0x0c45, 0x6122), BS(SN9C110, ICM105C)}, */ -/* {USB_DEVICE(0x0c45, 0x6123), BS(SN9C110, SanyoCCD)}, */ - {USB_DEVICE(0x0c45, 0x6128), BS(SN9C120, OM6802)}, /*sn9c325?*/ -/*bw600.inf:*/ - {USB_DEVICE(0x0c45, 0x612a), BS(SN9C120, OV7648)}, /*sn9c325?*/ - {USB_DEVICE(0x0c45, 0x612b), BS(SN9C110, ADCM1700)}, - {USB_DEVICE(0x0c45, 0x612c), BS(SN9C110, MO4000)}, - {USB_DEVICE(0x0c45, 0x612e), BS(SN9C110, OV7630)}, -/* {USB_DEVICE(0x0c45, 0x612f), BS(SN9C110, ICM105C)}, */ - {USB_DEVICE(0x0c45, 0x6130), BS(SN9C120, MI0360)}, - /* or MT9V111 / MI0360B */ -/* {USB_DEVICE(0x0c45, 0x6132), BS(SN9C120, OV7670)}, */ - {USB_DEVICE(0x0c45, 0x6138), BS(SN9C120, MO4000)}, - {USB_DEVICE(0x0c45, 0x613a), BS(SN9C120, OV7648)}, - {USB_DEVICE(0x0c45, 0x613b), BS(SN9C120, OV7660)}, - {USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)}, - {USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)}, - {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, /*sn9c120b*/ - /* or GC0305 / GC0307 */ - {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/ - {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/ - {USB_DEVICE(0x0c45, 0x614a), BSF(SN9C120, ADCM1700, F_ILLUM)}, -/* {USB_DEVICE(0x0c45, 0x614c), BS(SN9C120, GC0306)}, */ /*sn9c120b*/ - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/spca1528.c b/drivers/media/video/gspca/spca1528.c deleted file mode 100644 index 14d635277d71..000000000000 --- a/drivers/media/video/gspca/spca1528.c +++ /dev/null @@ -1,444 +0,0 @@ -/* - * spca1528 subdriver - * - * Copyright (C) 2010-2011 Jean-Francois Moine (http://moinejf.free.fr) - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "spca1528" - -#include "gspca.h" -#include "jpeg.h" - -MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); -MODULE_DESCRIPTION("SPCA1528 USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - u8 pkt_seq; - - u8 jpeg_hdr[JPEG_HDR_SZ]; -}; - -static const struct v4l2_pix_format vga_mode[] = { -/* (does not work correctly) - {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144 * 5 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 3}, -*/ - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 4 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, -}; - -/* read <len> bytes to gspca usb_buf */ -static void reg_r(struct gspca_dev *gspca_dev, - u8 req, - u16 index, - int len) -{ -#if USB_BUF_SZ < 64 -#error "USB buffer too small" -#endif - struct usb_device *dev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return; - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0000, /* value */ - index, - gspca_dev->usb_buf, len, - 500); - PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", req, index, - gspca_dev->usb_buf[0]); - if (ret < 0) { - pr_err("reg_r err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -static void reg_w(struct gspca_dev *gspca_dev, - u8 req, - u16 value, - u16 index) -{ - struct usb_device *dev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return; - PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index); - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, - NULL, 0, 500); - if (ret < 0) { - pr_err("reg_w err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -static void reg_wb(struct gspca_dev *gspca_dev, - u8 req, - u16 value, - u16 index, - u8 byte) -{ - struct usb_device *dev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return; - PDEBUG(D_USBO, "SET %02x %04x %04x %02x", req, value, index, byte); - gspca_dev->usb_buf[0] = byte; - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, - gspca_dev->usb_buf, 1, 500); - if (ret < 0) { - pr_err("reg_w err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -static void wait_status_0(struct gspca_dev *gspca_dev) -{ - int i, w; - - i = 16; - w = 0; - do { - reg_r(gspca_dev, 0x21, 0x0000, 1); - if (gspca_dev->usb_buf[0] == 0) - return; - w += 15; - msleep(w); - } while (--i > 0); - PDEBUG(D_ERR, "wait_status_0 timeout"); - gspca_dev->usb_err = -ETIME; -} - -static void wait_status_1(struct gspca_dev *gspca_dev) -{ - int i; - - i = 10; - do { - reg_r(gspca_dev, 0x21, 0x0001, 1); - msleep(10); - if (gspca_dev->usb_buf[0] == 1) { - reg_wb(gspca_dev, 0x21, 0x0000, 0x0001, 0x00); - reg_r(gspca_dev, 0x21, 0x0001, 1); - return; - } - } while (--i > 0); - PDEBUG(D_ERR, "wait_status_1 timeout"); - gspca_dev->usb_err = -ETIME; -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 val) -{ - reg_wb(gspca_dev, 0xc0, 0x0000, 0x00c0, val); -} - -static void setcontrast(struct gspca_dev *gspca_dev, s32 val) -{ - reg_wb(gspca_dev, 0xc1, 0x0000, 0x00c1, val); -} - -static void sethue(struct gspca_dev *gspca_dev, s32 val) -{ - reg_wb(gspca_dev, 0xc2, 0x0000, 0x0000, val); -} - -static void setcolor(struct gspca_dev *gspca_dev, s32 val) -{ - reg_wb(gspca_dev, 0xc3, 0x0000, 0x00c3, val); -} - -static void setsharpness(struct gspca_dev *gspca_dev, s32 val) -{ - reg_wb(gspca_dev, 0xc4, 0x0000, 0x00c4, val); -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - gspca_dev->cam.cam_mode = vga_mode; - gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); - gspca_dev->cam.npkt = 128; /* number of packets per ISOC message */ - /*fixme: 256 in ms-win traces*/ - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - reg_w(gspca_dev, 0x00, 0x0001, 0x2067); - reg_w(gspca_dev, 0x00, 0x00d0, 0x206b); - reg_w(gspca_dev, 0x00, 0x0000, 0x206c); - reg_w(gspca_dev, 0x00, 0x0001, 0x2069); - msleep(8); - reg_w(gspca_dev, 0x00, 0x00c0, 0x206b); - reg_w(gspca_dev, 0x00, 0x0000, 0x206c); - reg_w(gspca_dev, 0x00, 0x0001, 0x2069); - - reg_r(gspca_dev, 0x20, 0x0000, 1); - reg_r(gspca_dev, 0x20, 0x0000, 5); - reg_r(gspca_dev, 0x23, 0x0000, 64); - PDEBUG(D_PROBE, "%s%s", &gspca_dev->usb_buf[0x1c], - &gspca_dev->usb_buf[0x30]); - reg_r(gspca_dev, 0x23, 0x0001, 64); - return gspca_dev->usb_err; -} - -/* function called at start time before URB creation */ -static int sd_isoc_init(struct gspca_dev *gspca_dev) -{ - u8 mode; - - reg_r(gspca_dev, 0x00, 0x2520, 1); - wait_status_0(gspca_dev); - reg_w(gspca_dev, 0xc5, 0x0003, 0x0000); - wait_status_1(gspca_dev); - - wait_status_0(gspca_dev); - mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - reg_wb(gspca_dev, 0x25, 0x0000, 0x0004, mode); - reg_r(gspca_dev, 0x25, 0x0004, 1); - reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06); /* 420 */ - reg_r(gspca_dev, 0x27, 0x0000, 1); - -/* not useful.. - gspca_dev->alt = 4; * use alternate setting 3 */ - - return gspca_dev->usb_err; -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* initialize the JPEG header */ - jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, - 0x22); /* JPEG 411 */ - - /* the JPEG quality shall be 85% */ - jpeg_set_qual(sd->jpeg_hdr, 85); - - reg_r(gspca_dev, 0x00, 0x2520, 1); - msleep(8); - - /* start the capture */ - wait_status_0(gspca_dev); - reg_w(gspca_dev, 0x31, 0x0000, 0x0004); /* start request */ - wait_status_1(gspca_dev); - wait_status_0(gspca_dev); - msleep(200); - - sd->pkt_seq = 0; - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - /* stop the capture */ - wait_status_0(gspca_dev); - reg_w(gspca_dev, 0x31, 0x0000, 0x0000); /* stop request */ - wait_status_1(gspca_dev); - wait_status_0(gspca_dev); -} - -/* move a packet adding 0x00 after 0xff */ -static void add_packet(struct gspca_dev *gspca_dev, - u8 *data, - int len) -{ - int i; - - i = 0; - do { - if (data[i] == 0xff) { - gspca_frame_add(gspca_dev, INTER_PACKET, - data, i + 1); - len -= i; - data += i; - *data = 0x00; - i = 0; - } - } while (++i < len); - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - static const u8 ffd9[] = {0xff, 0xd9}; - - /* image packets start with: - * 02 8n - * with <n> bit: - * 0x01: even (0) / odd (1) image - * 0x02: end of image when set - */ - if (len < 3) - return; /* empty packet */ - if (*data == 0x02) { - if (data[1] & 0x02) { - sd->pkt_seq = !(data[1] & 1); - add_packet(gspca_dev, data + 2, len - 2); - gspca_frame_add(gspca_dev, LAST_PACKET, - ffd9, 2); - return; - } - if ((data[1] & 1) != sd->pkt_seq) - goto err; - if (gspca_dev->last_packet_type == LAST_PACKET) - gspca_frame_add(gspca_dev, FIRST_PACKET, - sd->jpeg_hdr, JPEG_HDR_SZ); - add_packet(gspca_dev, data + 2, len - 2); - return; - } -err: - gspca_dev->last_packet_type = DISCARD_PACKET; -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_CONTRAST: - setcontrast(gspca_dev, ctrl->val); - break; - case V4L2_CID_HUE: - sethue(gspca_dev, ctrl->val); - break; - case V4L2_CID_SATURATION: - setcolor(gspca_dev, ctrl->val); - break; - case V4L2_CID_SHARPNESS: - setsharpness(gspca_dev, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 5); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 8, 1, 1); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_HUE, 0, 255, 1, 0); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SATURATION, 0, 8, 1, 1); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SHARPNESS, 0, 255, 1, 0); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .isoc_init = sd_isoc_init, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x04fc, 0x1528)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - /* the video interface for isochronous transfer is 1 */ - if (intf->cur_altsetting->desc.bInterfaceNumber != 1) - return -ENODEV; - - return gspca_dev_probe2(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c deleted file mode 100644 index 25cb68d0556d..000000000000 --- a/drivers/media/video/gspca/spca500.c +++ /dev/null @@ -1,990 +0,0 @@ -/* - * SPCA500 chip based cameras initialization data - * - * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "spca500" - -#include "gspca.h" -#include "jpeg.h" - -MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); -MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver"); -MODULE_LICENSE("GPL"); - -#define QUALITY 85 - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - char subtype; -#define AgfaCl20 0 -#define AiptekPocketDV 1 -#define BenqDC1016 2 -#define CreativePCCam300 3 -#define DLinkDSC350 4 -#define Gsmartmini 5 -#define IntelPocketPCCamera 6 -#define KodakEZ200 7 -#define LogitechClickSmart310 8 -#define LogitechClickSmart510 9 -#define LogitechTraveler 10 -#define MustekGsmart300 11 -#define Optimedia 12 -#define PalmPixDC85 13 -#define ToptroIndus 14 - - u8 jpeg_hdr[JPEG_HDR_SZ]; -}; - -static const struct v4l2_pix_format vga_mode[] = { - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; - -static const struct v4l2_pix_format sif_mode[] = { - {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, - {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; - -/* Frame packet header offsets for the spca500 */ -#define SPCA500_OFFSET_PADDINGLB 2 -#define SPCA500_OFFSET_PADDINGHB 3 -#define SPCA500_OFFSET_MODE 4 -#define SPCA500_OFFSET_IMGWIDTH 5 -#define SPCA500_OFFSET_IMGHEIGHT 6 -#define SPCA500_OFFSET_IMGMODE 7 -#define SPCA500_OFFSET_QTBLINDEX 8 -#define SPCA500_OFFSET_FRAMSEQ 9 -#define SPCA500_OFFSET_CDSPINFO 10 -#define SPCA500_OFFSET_GPIO 11 -#define SPCA500_OFFSET_AUGPIO 12 -#define SPCA500_OFFSET_DATA 16 - - -static const __u16 spca500_visual_defaults[][3] = { - {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync, - * hue (H byte) = 0, - * saturation/hue enable, - * brightness/contrast enable. - */ - {0x00, 0x0000, 0x8167}, /* brightness = 0 */ - {0x00, 0x0020, 0x8168}, /* contrast = 0 */ - {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync, - * hue (H byte) = 0, saturation/hue enable, - * brightness/contrast enable. - * was 0x0003, now 0x0000. - */ - {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */ - {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */ - {0x00, 0x0050, 0x8157}, /* edge gain high threshold */ - {0x00, 0x0030, 0x8158}, /* edge gain low threshold */ - {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */ - {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */ - {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */ - {0x0c, 0x0004, 0x0000}, - /* set interface */ - {} -}; -static const __u16 Clicksmart510_defaults[][3] = { - {0x00, 0x00, 0x8211}, - {0x00, 0x01, 0x82c0}, - {0x00, 0x10, 0x82cb}, - {0x00, 0x0f, 0x800d}, - {0x00, 0x82, 0x8225}, - {0x00, 0x21, 0x8228}, - {0x00, 0x00, 0x8203}, - {0x00, 0x00, 0x8204}, - {0x00, 0x08, 0x8205}, - {0x00, 0xf8, 0x8206}, - {0x00, 0x28, 0x8207}, - {0x00, 0xa0, 0x8208}, - {0x00, 0x08, 0x824a}, - {0x00, 0x08, 0x8214}, - {0x00, 0x80, 0x82c1}, - {0x00, 0x00, 0x82c2}, - {0x00, 0x00, 0x82ca}, - {0x00, 0x80, 0x82c1}, - {0x00, 0x04, 0x82c2}, - {0x00, 0x00, 0x82ca}, - {0x00, 0xfc, 0x8100}, - {0x00, 0xfc, 0x8105}, - {0x00, 0x30, 0x8101}, - {0x00, 0x00, 0x8102}, - {0x00, 0x00, 0x8103}, - {0x00, 0x66, 0x8107}, - {0x00, 0x00, 0x816b}, - {0x00, 0x00, 0x8155}, - {0x00, 0x01, 0x8156}, - {0x00, 0x60, 0x8157}, - {0x00, 0x40, 0x8158}, - {0x00, 0x0a, 0x8159}, - {0x00, 0x06, 0x815a}, - {0x00, 0x00, 0x813f}, - {0x00, 0x00, 0x8200}, - {0x00, 0x19, 0x8201}, - {0x00, 0x00, 0x82c1}, - {0x00, 0xa0, 0x82c2}, - {0x00, 0x00, 0x82ca}, - {0x00, 0x00, 0x8117}, - {0x00, 0x00, 0x8118}, - {0x00, 0x65, 0x8119}, - {0x00, 0x00, 0x811a}, - {0x00, 0x00, 0x811b}, - {0x00, 0x55, 0x811c}, - {0x00, 0x65, 0x811d}, - {0x00, 0x55, 0x811e}, - {0x00, 0x16, 0x811f}, - {0x00, 0x19, 0x8120}, - {0x00, 0x80, 0x8103}, - {0x00, 0x83, 0x816b}, - {0x00, 0x25, 0x8168}, - {0x00, 0x01, 0x820f}, - {0x00, 0xff, 0x8115}, - {0x00, 0x48, 0x8116}, - {0x00, 0x50, 0x8151}, - {0x00, 0x40, 0x8152}, - {0x00, 0x78, 0x8153}, - {0x00, 0x40, 0x8154}, - {0x00, 0x00, 0x8167}, - {0x00, 0x20, 0x8168}, - {0x00, 0x00, 0x816a}, - {0x00, 0x03, 0x816b}, - {0x00, 0x20, 0x8169}, - {0x00, 0x60, 0x8157}, - {0x00, 0x00, 0x8190}, - {0x00, 0x00, 0x81a1}, - {0x00, 0x00, 0x81b2}, - {0x00, 0x27, 0x8191}, - {0x00, 0x27, 0x81a2}, - {0x00, 0x27, 0x81b3}, - {0x00, 0x4b, 0x8192}, - {0x00, 0x4b, 0x81a3}, - {0x00, 0x4b, 0x81b4}, - {0x00, 0x66, 0x8193}, - {0x00, 0x66, 0x81a4}, - {0x00, 0x66, 0x81b5}, - {0x00, 0x79, 0x8194}, - {0x00, 0x79, 0x81a5}, - {0x00, 0x79, 0x81b6}, - {0x00, 0x8a, 0x8195}, - {0x00, 0x8a, 0x81a6}, - {0x00, 0x8a, 0x81b7}, - {0x00, 0x9b, 0x8196}, - {0x00, 0x9b, 0x81a7}, - {0x00, 0x9b, 0x81b8}, - {0x00, 0xa6, 0x8197}, - {0x00, 0xa6, 0x81a8}, - {0x00, 0xa6, 0x81b9}, - {0x00, 0xb2, 0x8198}, - {0x00, 0xb2, 0x81a9}, - {0x00, 0xb2, 0x81ba}, - {0x00, 0xbe, 0x8199}, - {0x00, 0xbe, 0x81aa}, - {0x00, 0xbe, 0x81bb}, - {0x00, 0xc8, 0x819a}, - {0x00, 0xc8, 0x81ab}, - {0x00, 0xc8, 0x81bc}, - {0x00, 0xd2, 0x819b}, - {0x00, 0xd2, 0x81ac}, - {0x00, 0xd2, 0x81bd}, - {0x00, 0xdb, 0x819c}, - {0x00, 0xdb, 0x81ad}, - {0x00, 0xdb, 0x81be}, - {0x00, 0xe4, 0x819d}, - {0x00, 0xe4, 0x81ae}, - {0x00, 0xe4, 0x81bf}, - {0x00, 0xed, 0x819e}, - {0x00, 0xed, 0x81af}, - {0x00, 0xed, 0x81c0}, - {0x00, 0xf7, 0x819f}, - {0x00, 0xf7, 0x81b0}, - {0x00, 0xf7, 0x81c1}, - {0x00, 0xff, 0x81a0}, - {0x00, 0xff, 0x81b1}, - {0x00, 0xff, 0x81c2}, - {0x00, 0x03, 0x8156}, - {0x00, 0x00, 0x8211}, - {0x00, 0x20, 0x8168}, - {0x00, 0x01, 0x8202}, - {0x00, 0x30, 0x8101}, - {0x00, 0x00, 0x8111}, - {0x00, 0x00, 0x8112}, - {0x00, 0x00, 0x8113}, - {0x00, 0x00, 0x8114}, - {} -}; - -static const __u8 qtable_creative_pccam[2][64] = { - { /* Q-table Y-components */ - 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12, - 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11, - 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11, - 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13, - 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17, - 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c, - 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e, - 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e}, - { /* Q-table C-components */ - 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, - 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e} -}; - -static const __u8 qtable_kodak_ez200[2][64] = { - { /* Q-table Y-components */ - 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06, - 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06, - 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06, - 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06, - 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08, - 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09, - 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a, - 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a}, - { /* Q-table C-components */ - 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a, - 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, - 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a} -}; - -static const __u8 qtable_pocketdv[2][64] = { - { /* Q-table Y-components start registers 0x8800 */ - 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18, - 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16, - 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16, - 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19, - 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f, - 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25, - 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28, - 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28, - }, - { /* Q-table C-components start registers 0x8840 */ - 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28, - 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28, - 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28} -}; - -/* read 'len' bytes to gspca_dev->usb_buf */ -static void reg_r(struct gspca_dev *gspca_dev, - __u16 index, - __u16 length) -{ - usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - 0, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, /* value */ - index, gspca_dev->usb_buf, length, 500); -} - -static int reg_w(struct gspca_dev *gspca_dev, - __u16 req, __u16 index, __u16 value) -{ - int ret; - - PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value); - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, NULL, 0, 500); - if (ret < 0) - pr_err("reg write: error %d\n", ret); - return ret; -} - -/* returns: negative is error, pos or zero is data */ -static int reg_r_12(struct gspca_dev *gspca_dev, - __u16 req, /* bRequest */ - __u16 index, /* wIndex */ - __u16 length) /* wLength (1 or 2 only) */ -{ - int ret; - - gspca_dev->usb_buf[1] = 0; - ret = usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, /* value */ - index, - gspca_dev->usb_buf, length, - 500); /* timeout */ - if (ret < 0) { - pr_err("reg_r_12 err %d\n", ret); - return ret; - } - return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]; -} - -/* - * Simple function to wait for a given 8-bit value to be returned from - * a reg_read call. - * Returns: negative is error or timeout, zero is success. - */ -static int reg_r_wait(struct gspca_dev *gspca_dev, - __u16 reg, __u16 index, __u16 value) -{ - int ret, cnt = 20; - - while (--cnt > 0) { - ret = reg_r_12(gspca_dev, reg, index, 1); - if (ret == value) - return 0; - msleep(50); - } - return -EIO; -} - -static int write_vector(struct gspca_dev *gspca_dev, - const __u16 data[][3]) -{ - int ret, i = 0; - - while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) { - ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]); - if (ret < 0) - return ret; - i++; - } - return 0; -} - -static int spca50x_setup_qtable(struct gspca_dev *gspca_dev, - unsigned int request, - unsigned int ybase, - unsigned int cbase, - const __u8 qtable[2][64]) -{ - int i, err; - - /* loop over y components */ - for (i = 0; i < 64; i++) { - err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]); - if (err < 0) - return err; - } - - /* loop over c components */ - for (i = 0; i < 64; i++) { - err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]); - if (err < 0) - return err; - } - return 0; -} - -static void spca500_ping310(struct gspca_dev *gspca_dev) -{ - reg_r(gspca_dev, 0x0d04, 2); - PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x", - gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]); -} - -static void spca500_clksmart310_init(struct gspca_dev *gspca_dev) -{ - reg_r(gspca_dev, 0x0d05, 2); - PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x", - gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]); - reg_w(gspca_dev, 0x00, 0x8167, 0x5a); - spca500_ping310(gspca_dev); - - reg_w(gspca_dev, 0x00, 0x8168, 0x22); - reg_w(gspca_dev, 0x00, 0x816a, 0xc0); - reg_w(gspca_dev, 0x00, 0x816b, 0x0b); - reg_w(gspca_dev, 0x00, 0x8169, 0x25); - reg_w(gspca_dev, 0x00, 0x8157, 0x5b); - reg_w(gspca_dev, 0x00, 0x8158, 0x5b); - reg_w(gspca_dev, 0x00, 0x813f, 0x03); - reg_w(gspca_dev, 0x00, 0x8151, 0x4a); - reg_w(gspca_dev, 0x00, 0x8153, 0x78); - reg_w(gspca_dev, 0x00, 0x0d01, 0x04); - /* 00 for adjust shutter */ - reg_w(gspca_dev, 0x00, 0x0d02, 0x01); - reg_w(gspca_dev, 0x00, 0x8169, 0x25); - reg_w(gspca_dev, 0x00, 0x0d01, 0x02); -} - -static void spca500_setmode(struct gspca_dev *gspca_dev, - __u8 xmult, __u8 ymult) -{ - int mode; - - /* set x multiplier */ - reg_w(gspca_dev, 0, 0x8001, xmult); - - /* set y multiplier */ - reg_w(gspca_dev, 0, 0x8002, ymult); - - /* use compressed mode, VGA, with mode specific subsample */ - mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; - reg_w(gspca_dev, 0, 0x8003, mode << 4); -} - -static int spca500_full_reset(struct gspca_dev *gspca_dev) -{ - int err; - - /* send the reset command */ - err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000); - if (err < 0) - return err; - - /* wait for the reset to complete */ - err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000); - if (err < 0) - return err; - err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000); - if (err < 0) - return err; - err = reg_r_wait(gspca_dev, 0x06, 0, 0); - if (err < 0) { - PDEBUG(D_ERR, "reg_r_wait() failed"); - return err; - } - /* all ok */ - return 0; -} - -/* Synchro the Bridge with sensor */ -/* Maybe that will work on all spca500 chip */ -/* because i only own a clicksmart310 try for that chip */ -/* using spca50x_set_packet_size() cause an Ooops here */ -/* usb_set_interface from kernel 2.6.x clear all the urb stuff */ -/* up-port the same feature as in 2.4.x kernel */ -static int spca500_synch310(struct gspca_dev *gspca_dev) -{ - if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) { - PDEBUG(D_ERR, "Set packet size: set interface error"); - goto error; - } - spca500_ping310(gspca_dev); - - reg_r(gspca_dev, 0x0d00, 1); - - /* need alt setting here */ - PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt); - - /* Windoze use pipe with altsetting 6 why 7 here */ - if (usb_set_interface(gspca_dev->dev, - gspca_dev->iface, - gspca_dev->alt) < 0) { - PDEBUG(D_ERR, "Set packet size: set interface error"); - goto error; - } - return 0; -error: - return -EBUSY; -} - -static void spca500_reinit(struct gspca_dev *gspca_dev) -{ - int err; - __u8 Data; - - /* some unknown command from Aiptek pocket dv and family300 */ - - reg_w(gspca_dev, 0x00, 0x0d01, 0x01); - reg_w(gspca_dev, 0x00, 0x0d03, 0x00); - reg_w(gspca_dev, 0x00, 0x0d02, 0x01); - - /* enable drop packet */ - reg_w(gspca_dev, 0x00, 0x850a, 0x0001); - - err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840, - qtable_pocketdv); - if (err < 0) - PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init"); - - /* set qtable index */ - reg_w(gspca_dev, 0x00, 0x8880, 2); - /* family cam Quicksmart stuff */ - reg_w(gspca_dev, 0x00, 0x800a, 0x00); - /* Set agc transfer: synced between frames */ - reg_w(gspca_dev, 0x00, 0x820f, 0x01); - /* Init SDRAM - needed for SDRAM access */ - reg_w(gspca_dev, 0x00, 0x870a, 0x04); - /*Start init sequence or stream */ - reg_w(gspca_dev, 0, 0x8003, 0x00); - /* switch to video camera mode */ - reg_w(gspca_dev, 0x00, 0x8000, 0x0004); - msleep(2000); - if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) { - reg_r(gspca_dev, 0x816b, 1); - Data = gspca_dev->usb_buf[0]; - reg_w(gspca_dev, 0x00, 0x816b, Data); - } -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - - cam = &gspca_dev->cam; - sd->subtype = id->driver_info; - if (sd->subtype != LogitechClickSmart310) { - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - } else { - cam->cam_mode = sif_mode; - cam->nmodes = ARRAY_SIZE(sif_mode); - } - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* initialisation of spca500 based cameras is deferred */ - PDEBUG(D_STREAM, "SPCA500 init"); - if (sd->subtype == LogitechClickSmart310) - spca500_clksmart310_init(gspca_dev); -/* else - spca500_initialise(gspca_dev); */ - PDEBUG(D_STREAM, "SPCA500 init done"); - return 0; -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int err; - __u8 Data; - __u8 xmult, ymult; - - /* create the JPEG header */ - jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, - 0x22); /* JPEG 411 */ - jpeg_set_qual(sd->jpeg_hdr, QUALITY); - - if (sd->subtype == LogitechClickSmart310) { - xmult = 0x16; - ymult = 0x12; - } else { - xmult = 0x28; - ymult = 0x1e; - } - - /* is there a sensor here ? */ - reg_r(gspca_dev, 0x8a04, 1); - PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x", - gspca_dev->usb_buf[0]); - PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x", - gspca_dev->curr_mode, xmult, ymult); - - /* setup qtable */ - switch (sd->subtype) { - case LogitechClickSmart310: - spca500_setmode(gspca_dev, xmult, ymult); - - /* enable drop packet */ - reg_w(gspca_dev, 0x00, 0x850a, 0x0001); - reg_w(gspca_dev, 0x00, 0x8880, 3); - err = spca50x_setup_qtable(gspca_dev, - 0x00, 0x8800, 0x8840, - qtable_creative_pccam); - if (err < 0) - PDEBUG(D_ERR, "spca50x_setup_qtable failed"); - /* Init SDRAM - needed for SDRAM access */ - reg_w(gspca_dev, 0x00, 0x870a, 0x04); - - /* switch to video camera mode */ - reg_w(gspca_dev, 0x00, 0x8000, 0x0004); - msleep(500); - if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) - PDEBUG(D_ERR, "reg_r_wait() failed"); - - reg_r(gspca_dev, 0x816b, 1); - Data = gspca_dev->usb_buf[0]; - reg_w(gspca_dev, 0x00, 0x816b, Data); - - spca500_synch310(gspca_dev); - - write_vector(gspca_dev, spca500_visual_defaults); - spca500_setmode(gspca_dev, xmult, ymult); - /* enable drop packet */ - err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001); - if (err < 0) - PDEBUG(D_ERR, "failed to enable drop packet"); - reg_w(gspca_dev, 0x00, 0x8880, 3); - err = spca50x_setup_qtable(gspca_dev, - 0x00, 0x8800, 0x8840, - qtable_creative_pccam); - if (err < 0) - PDEBUG(D_ERR, "spca50x_setup_qtable failed"); - - /* Init SDRAM - needed for SDRAM access */ - reg_w(gspca_dev, 0x00, 0x870a, 0x04); - - /* switch to video camera mode */ - reg_w(gspca_dev, 0x00, 0x8000, 0x0004); - - if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) - PDEBUG(D_ERR, "reg_r_wait() failed"); - - reg_r(gspca_dev, 0x816b, 1); - Data = gspca_dev->usb_buf[0]; - reg_w(gspca_dev, 0x00, 0x816b, Data); - break; - case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */ - case IntelPocketPCCamera: /* FIXME: Temporary fix for - * Intel Pocket PC Camera - * - NWG (Sat 29th March 2003) */ - - /* do a full reset */ - err = spca500_full_reset(gspca_dev); - if (err < 0) - PDEBUG(D_ERR, "spca500_full_reset failed"); - - /* enable drop packet */ - err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001); - if (err < 0) - PDEBUG(D_ERR, "failed to enable drop packet"); - reg_w(gspca_dev, 0x00, 0x8880, 3); - err = spca50x_setup_qtable(gspca_dev, - 0x00, 0x8800, 0x8840, - qtable_creative_pccam); - if (err < 0) - PDEBUG(D_ERR, "spca50x_setup_qtable failed"); - - spca500_setmode(gspca_dev, xmult, ymult); - reg_w(gspca_dev, 0x20, 0x0001, 0x0004); - - /* switch to video camera mode */ - reg_w(gspca_dev, 0x00, 0x8000, 0x0004); - - if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) - PDEBUG(D_ERR, "reg_r_wait() failed"); - - reg_r(gspca_dev, 0x816b, 1); - Data = gspca_dev->usb_buf[0]; - reg_w(gspca_dev, 0x00, 0x816b, Data); - -/* write_vector(gspca_dev, spca500_visual_defaults); */ - break; - case KodakEZ200: /* Kodak EZ200 */ - - /* do a full reset */ - err = spca500_full_reset(gspca_dev); - if (err < 0) - PDEBUG(D_ERR, "spca500_full_reset failed"); - /* enable drop packet */ - reg_w(gspca_dev, 0x00, 0x850a, 0x0001); - reg_w(gspca_dev, 0x00, 0x8880, 0); - err = spca50x_setup_qtable(gspca_dev, - 0x00, 0x8800, 0x8840, - qtable_kodak_ez200); - if (err < 0) - PDEBUG(D_ERR, "spca50x_setup_qtable failed"); - spca500_setmode(gspca_dev, xmult, ymult); - - reg_w(gspca_dev, 0x20, 0x0001, 0x0004); - - /* switch to video camera mode */ - reg_w(gspca_dev, 0x00, 0x8000, 0x0004); - - if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) - PDEBUG(D_ERR, "reg_r_wait() failed"); - - reg_r(gspca_dev, 0x816b, 1); - Data = gspca_dev->usb_buf[0]; - reg_w(gspca_dev, 0x00, 0x816b, Data); - -/* write_vector(gspca_dev, spca500_visual_defaults); */ - break; - - case BenqDC1016: - case DLinkDSC350: /* FamilyCam 300 */ - case AiptekPocketDV: /* Aiptek PocketDV */ - case Gsmartmini: /*Mustek Gsmart Mini */ - case MustekGsmart300: /* Mustek Gsmart 300 */ - case PalmPixDC85: - case Optimedia: - case ToptroIndus: - case AgfaCl20: - spca500_reinit(gspca_dev); - reg_w(gspca_dev, 0x00, 0x0d01, 0x01); - /* enable drop packet */ - reg_w(gspca_dev, 0x00, 0x850a, 0x0001); - - err = spca50x_setup_qtable(gspca_dev, - 0x00, 0x8800, 0x8840, qtable_pocketdv); - if (err < 0) - PDEBUG(D_ERR, "spca50x_setup_qtable failed"); - reg_w(gspca_dev, 0x00, 0x8880, 2); - - /* familycam Quicksmart pocketDV stuff */ - reg_w(gspca_dev, 0x00, 0x800a, 0x00); - /* Set agc transfer: synced between frames */ - reg_w(gspca_dev, 0x00, 0x820f, 0x01); - /* Init SDRAM - needed for SDRAM access */ - reg_w(gspca_dev, 0x00, 0x870a, 0x04); - - spca500_setmode(gspca_dev, xmult, ymult); - /* switch to video camera mode */ - reg_w(gspca_dev, 0x00, 0x8000, 0x0004); - - reg_r_wait(gspca_dev, 0, 0x8000, 0x44); - - reg_r(gspca_dev, 0x816b, 1); - Data = gspca_dev->usb_buf[0]; - reg_w(gspca_dev, 0x00, 0x816b, Data); - break; - case LogitechTraveler: - case LogitechClickSmart510: - reg_w(gspca_dev, 0x02, 0x00, 0x00); - /* enable drop packet */ - reg_w(gspca_dev, 0x00, 0x850a, 0x0001); - - err = spca50x_setup_qtable(gspca_dev, - 0x00, 0x8800, - 0x8840, qtable_creative_pccam); - if (err < 0) - PDEBUG(D_ERR, "spca50x_setup_qtable failed"); - reg_w(gspca_dev, 0x00, 0x8880, 3); - reg_w(gspca_dev, 0x00, 0x800a, 0x00); - /* Init SDRAM - needed for SDRAM access */ - reg_w(gspca_dev, 0x00, 0x870a, 0x04); - - spca500_setmode(gspca_dev, xmult, ymult); - - /* switch to video camera mode */ - reg_w(gspca_dev, 0x00, 0x8000, 0x0004); - reg_r_wait(gspca_dev, 0, 0x8000, 0x44); - - reg_r(gspca_dev, 0x816b, 1); - Data = gspca_dev->usb_buf[0]; - reg_w(gspca_dev, 0x00, 0x816b, Data); - write_vector(gspca_dev, Clicksmart510_defaults); - break; - } - return 0; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - reg_w(gspca_dev, 0, 0x8003, 0x00); - - /* switch to video camera mode */ - reg_w(gspca_dev, 0x00, 0x8000, 0x0004); - reg_r(gspca_dev, 0x8000, 1); - PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x", - gspca_dev->usb_buf[0]); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - int i; - static __u8 ffd9[] = {0xff, 0xd9}; - -/* frames are jpeg 4.1.1 without 0xff escape */ - if (data[0] == 0xff) { - if (data[1] != 0x01) { /* drop packet */ -/* gspca_dev->last_packet_type = DISCARD_PACKET; */ - return; - } - gspca_frame_add(gspca_dev, LAST_PACKET, - ffd9, 2); - - /* put the JPEG header in the new frame */ - gspca_frame_add(gspca_dev, FIRST_PACKET, - sd->jpeg_hdr, JPEG_HDR_SZ); - - data += SPCA500_OFFSET_DATA; - len -= SPCA500_OFFSET_DATA; - } else { - data += 1; - len -= 1; - } - - /* add 0x00 after 0xff */ - i = 0; - do { - if (data[i] == 0xff) { - gspca_frame_add(gspca_dev, INTER_PACKET, - data, i + 1); - len -= i; - data += i; - *data = 0x00; - i = 0; - } - i++; - } while (i < len); - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 val) -{ - reg_w(gspca_dev, 0x00, 0x8167, - (__u8) (val - 128)); -} - -static void setcontrast(struct gspca_dev *gspca_dev, s32 val) -{ - reg_w(gspca_dev, 0x00, 0x8168, val); -} - -static void setcolors(struct gspca_dev *gspca_dev, s32 val) -{ - reg_w(gspca_dev, 0x00, 0x8169, val); -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_CONTRAST: - setcontrast(gspca_dev, ctrl->val); - break; - case V4L2_CID_SATURATION: - setcolors(gspca_dev, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 3); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 63, 1, 31); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SATURATION, 0, 63, 1, 31); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200}, - {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300}, - {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler}, - {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310}, - {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510}, - {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016}, - {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85}, - {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300}, - {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini}, - {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20}, - {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia}, - {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350}, - {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV}, - {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus}, - {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c deleted file mode 100644 index 3b7f777785b4..000000000000 --- a/drivers/media/video/gspca/spca501.c +++ /dev/null @@ -1,2054 +0,0 @@ -/* - * SPCA501 chip based cameras initialization data - * - * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "spca501" - -#include "gspca.h" - -MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); -MODULE_DESCRIPTION("GSPCA/SPCA501 USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - unsigned short contrast; - __u8 brightness; - __u8 colors; - __u8 blue_balance; - __u8 red_balance; - - char subtype; -#define Arowana300KCMOSCamera 0 -#define IntelCreateAndShare 1 -#define KodakDVC325 2 -#define MystFromOriUnknownCamera 3 -#define SmileIntlCamera 4 -#define ThreeComHomeConnectLite 5 -#define ViewQuestM318B 6 -}; - -static const struct v4l2_pix_format vga_mode[] = { - {160, 120, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, - {320, 240, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; - -#define SPCA50X_REG_USB 0x2 /* spca505 501 */ -/* - * Data to initialize a SPCA501. From a capture file provided by Bill Roehl - * With SPCA501 chip description - */ -#define CCDSP_SET /* set CCDSP parameters */ -#define TG_SET /* set time generator set */ -#undef DSPWIN_SET /* set DSP windows parameters */ -#undef ALTER_GAMA /* Set alternate set to YUV transform coeffs. */ -#define SPCA501_SNAPBIT 0x80 -#define SPCA501_SNAPCTRL 0x10 -/* Frame packet header offsets for the spca501 */ -#define SPCA501_OFFSET_GPIO 1 -#define SPCA501_OFFSET_TYPE 2 -#define SPCA501_OFFSET_TURN3A 3 -#define SPCA501_OFFSET_FRAMSEQ 4 -#define SPCA501_OFFSET_COMPRESS 5 -#define SPCA501_OFFSET_QUANT 6 -#define SPCA501_OFFSET_QUANT2 7 -#define SPCA501_OFFSET_DATA 8 - -#define SPCA501_PROP_COMP_ENABLE(d) ((d) & 1) -#define SPCA501_PROP_SNAP(d) ((d) & 0x40) -#define SPCA501_PROP_SNAP_CTRL(d) ((d) & 0x10) -#define SPCA501_PROP_COMP_THRESH(d) (((d) & 0x0e) >> 1) -#define SPCA501_PROP_COMP_QUANT(d) (((d) & 0x70) >> 4) - -/* SPCA501 CCDSP control */ -#define SPCA501_REG_CCDSP 0x01 -/* SPCA501 control/status registers */ -#define SPCA501_REG_CTLRL 0x02 - -/* registers for color correction and YUV transformation */ -#define SPCA501_A11 0x08 -#define SPCA501_A12 0x09 -#define SPCA501_A13 0x0A -#define SPCA501_A21 0x0B -#define SPCA501_A22 0x0C -#define SPCA501_A23 0x0D -#define SPCA501_A31 0x0E -#define SPCA501_A32 0x0F -#define SPCA501_A33 0x10 - -/* Data for video camera initialization before capturing */ -static const __u16 spca501_open_data[][3] = { - /* bmRequest,value,index */ - - {0x2, 0x50, 0x00}, /* C/S enable soft reset */ - {0x2, 0x40, 0x00}, /* C/S disable soft reset */ - {0x2, 0x02, 0x05}, /* C/S general purpose I/O data */ - {0x2, 0x03, 0x05}, /* C/S general purpose I/O data */ - -#ifdef CCDSP_SET - {0x1, 0x38, 0x01}, /* CCDSP options */ - {0x1, 0x05, 0x02}, /* CCDSP Optical black level for user settings */ - {0x1, 0xC0, 0x03}, /* CCDSP Optical black settings */ - - {0x1, 0x67, 0x07}, - {0x1, 0x63, 0x3f}, /* CCDSP CCD gamma enable */ - {0x1, 0x03, 0x56}, /* Add gamma correction */ - - {0x1, 0xFF, 0x15}, /* CCDSP High luminance for white balance */ - {0x1, 0x01, 0x16}, /* CCDSP Low luminance for white balance */ - -/* Color correction and RGB-to-YUV transformation coefficients changing */ -#ifdef ALTER_GAMA - {0x0, 0x00, 0x08}, /* A11 */ - {0x0, 0x00, 0x09}, /* A12 */ - {0x0, 0x90, 0x0A}, /* A13 */ - {0x0, 0x12, 0x0B}, /* A21 */ - {0x0, 0x00, 0x0C}, /* A22 */ - {0x0, 0x00, 0x0D}, /* A23 */ - {0x0, 0x00, 0x0E}, /* A31 */ - {0x0, 0x02, 0x0F}, /* A32 */ - {0x0, 0x00, 0x10}, /* A33 */ -#else - {0x1, 0x2a, 0x08}, /* A11 0x31 */ - {0x1, 0xf8, 0x09}, /* A12 f8 */ - {0x1, 0xf8, 0x0A}, /* A13 f8 */ - {0x1, 0xf8, 0x0B}, /* A21 f8 */ - {0x1, 0x14, 0x0C}, /* A22 0x14 */ - {0x1, 0xf8, 0x0D}, /* A23 f8 */ - {0x1, 0xf8, 0x0E}, /* A31 f8 */ - {0x1, 0xf8, 0x0F}, /* A32 f8 */ - {0x1, 0x20, 0x10}, /* A33 0x20 */ -#endif - {0x1, 0x00, 0x11}, /* R offset */ - {0x1, 0x00, 0x12}, /* G offset */ - {0x1, 0x00, 0x13}, /* B offset */ - {0x1, 0x00, 0x14}, /* GB offset */ - -#endif - -#ifdef TG_SET - /* Time generator manipulations */ - {0x0, 0xfc, 0x0}, /* Set up high bits of shutter speed */ - {0x0, 0x01, 0x1}, /* Set up low bits of shutter speed */ - - {0x0, 0xe4, 0x04}, /* DCLK*2 clock phase adjustment */ - {0x0, 0x08, 0x05}, /* ADCK phase adjustment, inv. ext. VB */ - {0x0, 0x03, 0x06}, /* FR phase adjustment */ - {0x0, 0x01, 0x07}, /* FCDS phase adjustment */ - {0x0, 0x39, 0x08}, /* FS phase adjustment */ - {0x0, 0x88, 0x0a}, /* FH1 phase and delay adjustment */ - {0x0, 0x03, 0x0f}, /* pixel identification */ - {0x0, 0x00, 0x11}, /* clock source selection (default) */ - - /*VERY strange manipulations with - * select DMCLP or OBPX to be ADCLP output (0x0C) - * OPB always toggle or not (0x0D) but they allow - * us to set up brightness - */ - {0x0, 0x01, 0x0c}, - {0x0, 0xe0, 0x0d}, - /* Done */ -#endif - -#ifdef DSPWIN_SET - {0x1, 0xa0, 0x01}, /* Setting image processing parameters */ - {0x1, 0x1c, 0x17}, /* Changing Windows positions X1 */ - {0x1, 0xe2, 0x19}, /* X2 */ - {0x1, 0x1c, 0x1b}, /* X3 */ - {0x1, 0xe2, 0x1d}, /* X4 */ - {0x1, 0x5f, 0x1f}, /* X5 */ - {0x1, 0x32, 0x20}, /* Y5 */ - {0x1, 0x01, 0x10}, /* Changing A33 */ -#endif - - {0x2, 0x204a, 0x07},/* Setting video compression & resolution 160x120 */ - {0x2, 0x94, 0x06}, /* Setting video no compression */ - {} -}; - -/* - The SPCAxxx docs from Sunplus document these values - in tables, one table per register number. In the data - below, dmRequest is the register number, index is the Addr, - and value is a combination of Bit values. - Bit Value (hex) - 0 01 - 1 02 - 2 04 - 3 08 - 4 10 - 5 20 - 6 40 - 7 80 - */ - -/* Data for chip initialization (set default values) */ -static const __u16 spca501_init_data[][3] = { - /* Set all the values to powerup defaults */ - /* bmRequest,value,index */ - {0x0, 0xAA, 0x00}, - {0x0, 0x02, 0x01}, - {0x0, 0x01, 0x02}, - {0x0, 0x02, 0x03}, - {0x0, 0xCE, 0x04}, - {0x0, 0x00, 0x05}, - {0x0, 0x00, 0x06}, - {0x0, 0x00, 0x07}, - {0x0, 0x00, 0x08}, - {0x0, 0x00, 0x09}, - {0x0, 0x90, 0x0A}, - {0x0, 0x12, 0x0B}, - {0x0, 0x00, 0x0C}, - {0x0, 0x00, 0x0D}, - {0x0, 0x00, 0x0E}, - {0x0, 0x02, 0x0F}, - {0x0, 0x00, 0x10}, - {0x0, 0x00, 0x11}, - {0x0, 0x00, 0x12}, - {0x0, 0x00, 0x13}, - {0x0, 0x00, 0x14}, - {0x0, 0x00, 0x15}, - {0x0, 0x00, 0x16}, - {0x0, 0x00, 0x17}, - {0x0, 0x00, 0x18}, - {0x0, 0x00, 0x19}, - {0x0, 0x00, 0x1A}, - {0x0, 0x00, 0x1B}, - {0x0, 0x00, 0x1C}, - {0x0, 0x00, 0x1D}, - {0x0, 0x00, 0x1E}, - {0x0, 0x00, 0x1F}, - {0x0, 0x00, 0x20}, - {0x0, 0x00, 0x21}, - {0x0, 0x00, 0x22}, - {0x0, 0x00, 0x23}, - {0x0, 0x00, 0x24}, - {0x0, 0x00, 0x25}, - {0x0, 0x00, 0x26}, - {0x0, 0x00, 0x27}, - {0x0, 0x00, 0x28}, - {0x0, 0x00, 0x29}, - {0x0, 0x00, 0x2A}, - {0x0, 0x00, 0x2B}, - {0x0, 0x00, 0x2C}, - {0x0, 0x00, 0x2D}, - {0x0, 0x00, 0x2E}, - {0x0, 0x00, 0x2F}, - {0x0, 0x00, 0x30}, - {0x0, 0x00, 0x31}, - {0x0, 0x00, 0x32}, - {0x0, 0x00, 0x33}, - {0x0, 0x00, 0x34}, - {0x0, 0x00, 0x35}, - {0x0, 0x00, 0x36}, - {0x0, 0x00, 0x37}, - {0x0, 0x00, 0x38}, - {0x0, 0x00, 0x39}, - {0x0, 0x00, 0x3A}, - {0x0, 0x00, 0x3B}, - {0x0, 0x00, 0x3C}, - {0x0, 0x00, 0x3D}, - {0x0, 0x00, 0x3E}, - {0x0, 0x00, 0x3F}, - {0x0, 0x00, 0x40}, - {0x0, 0x00, 0x41}, - {0x0, 0x00, 0x42}, - {0x0, 0x00, 0x43}, - {0x0, 0x00, 0x44}, - {0x0, 0x00, 0x45}, - {0x0, 0x00, 0x46}, - {0x0, 0x00, 0x47}, - {0x0, 0x00, 0x48}, - {0x0, 0x00, 0x49}, - {0x0, 0x00, 0x4A}, - {0x0, 0x00, 0x4B}, - {0x0, 0x00, 0x4C}, - {0x0, 0x00, 0x4D}, - {0x0, 0x00, 0x4E}, - {0x0, 0x00, 0x4F}, - {0x0, 0x00, 0x50}, - {0x0, 0x00, 0x51}, - {0x0, 0x00, 0x52}, - {0x0, 0x00, 0x53}, - {0x0, 0x00, 0x54}, - {0x0, 0x00, 0x55}, - {0x0, 0x00, 0x56}, - {0x0, 0x00, 0x57}, - {0x0, 0x00, 0x58}, - {0x0, 0x00, 0x59}, - {0x0, 0x00, 0x5A}, - {0x0, 0x00, 0x5B}, - {0x0, 0x00, 0x5C}, - {0x0, 0x00, 0x5D}, - {0x0, 0x00, 0x5E}, - {0x0, 0x00, 0x5F}, - {0x0, 0x00, 0x60}, - {0x0, 0x00, 0x61}, - {0x0, 0x00, 0x62}, - {0x0, 0x00, 0x63}, - {0x0, 0x00, 0x64}, - {0x0, 0x00, 0x65}, - {0x0, 0x00, 0x66}, - {0x0, 0x00, 0x67}, - {0x0, 0x00, 0x68}, - {0x0, 0x00, 0x69}, - {0x0, 0x00, 0x6A}, - {0x0, 0x00, 0x6B}, - {0x0, 0x00, 0x6C}, - {0x0, 0x00, 0x6D}, - {0x0, 0x00, 0x6E}, - {0x0, 0x00, 0x6F}, - {0x0, 0x00, 0x70}, - {0x0, 0x00, 0x71}, - {0x0, 0x00, 0x72}, - {0x0, 0x00, 0x73}, - {0x0, 0x00, 0x74}, - {0x0, 0x00, 0x75}, - {0x0, 0x00, 0x76}, - {0x0, 0x00, 0x77}, - {0x0, 0x00, 0x78}, - {0x0, 0x00, 0x79}, - {0x0, 0x00, 0x7A}, - {0x0, 0x00, 0x7B}, - {0x0, 0x00, 0x7C}, - {0x0, 0x00, 0x7D}, - {0x0, 0x00, 0x7E}, - {0x0, 0x00, 0x7F}, - {0x0, 0x00, 0x80}, - {0x0, 0x00, 0x81}, - {0x0, 0x00, 0x82}, - {0x0, 0x00, 0x83}, - {0x0, 0x00, 0x84}, - {0x0, 0x00, 0x85}, - {0x0, 0x00, 0x86}, - {0x0, 0x00, 0x87}, - {0x0, 0x00, 0x88}, - {0x0, 0x00, 0x89}, - {0x0, 0x00, 0x8A}, - {0x0, 0x00, 0x8B}, - {0x0, 0x00, 0x8C}, - {0x0, 0x00, 0x8D}, - {0x0, 0x00, 0x8E}, - {0x0, 0x00, 0x8F}, - {0x0, 0x00, 0x90}, - {0x0, 0x00, 0x91}, - {0x0, 0x00, 0x92}, - {0x0, 0x00, 0x93}, - {0x0, 0x00, 0x94}, - {0x0, 0x00, 0x95}, - {0x0, 0x00, 0x96}, - {0x0, 0x00, 0x97}, - {0x0, 0x00, 0x98}, - {0x0, 0x00, 0x99}, - {0x0, 0x00, 0x9A}, - {0x0, 0x00, 0x9B}, - {0x0, 0x00, 0x9C}, - {0x0, 0x00, 0x9D}, - {0x0, 0x00, 0x9E}, - {0x0, 0x00, 0x9F}, - {0x0, 0x00, 0xA0}, - {0x0, 0x00, 0xA1}, - {0x0, 0x00, 0xA2}, - {0x0, 0x00, 0xA3}, - {0x0, 0x00, 0xA4}, - {0x0, 0x00, 0xA5}, - {0x0, 0x00, 0xA6}, - {0x0, 0x00, 0xA7}, - {0x0, 0x00, 0xA8}, - {0x0, 0x00, 0xA9}, - {0x0, 0x00, 0xAA}, - {0x0, 0x00, 0xAB}, - {0x0, 0x00, 0xAC}, - {0x0, 0x00, 0xAD}, - {0x0, 0x00, 0xAE}, - {0x0, 0x00, 0xAF}, - {0x0, 0x00, 0xB0}, - {0x0, 0x00, 0xB1}, - {0x0, 0x00, 0xB2}, - {0x0, 0x00, 0xB3}, - {0x0, 0x00, 0xB4}, - {0x0, 0x00, 0xB5}, - {0x0, 0x00, 0xB6}, - {0x0, 0x00, 0xB7}, - {0x0, 0x00, 0xB8}, - {0x0, 0x00, 0xB9}, - {0x0, 0x00, 0xBA}, - {0x0, 0x00, 0xBB}, - {0x0, 0x00, 0xBC}, - {0x0, 0x00, 0xBD}, - {0x0, 0x00, 0xBE}, - {0x0, 0x00, 0xBF}, - {0x0, 0x00, 0xC0}, - {0x0, 0x00, 0xC1}, - {0x0, 0x00, 0xC2}, - {0x0, 0x00, 0xC3}, - {0x0, 0x00, 0xC4}, - {0x0, 0x00, 0xC5}, - {0x0, 0x00, 0xC6}, - {0x0, 0x00, 0xC7}, - {0x0, 0x00, 0xC8}, - {0x0, 0x00, 0xC9}, - {0x0, 0x00, 0xCA}, - {0x0, 0x00, 0xCB}, - {0x0, 0x00, 0xCC}, - {0x1, 0xF4, 0x00}, - {0x1, 0x38, 0x01}, - {0x1, 0x40, 0x02}, - {0x1, 0x0A, 0x03}, - {0x1, 0x40, 0x04}, - {0x1, 0x40, 0x05}, - {0x1, 0x40, 0x06}, - {0x1, 0x67, 0x07}, - {0x1, 0x31, 0x08}, - {0x1, 0x00, 0x09}, - {0x1, 0x00, 0x0A}, - {0x1, 0x00, 0x0B}, - {0x1, 0x14, 0x0C}, - {0x1, 0x00, 0x0D}, - {0x1, 0x00, 0x0E}, - {0x1, 0x00, 0x0F}, - {0x1, 0x1E, 0x10}, - {0x1, 0x00, 0x11}, - {0x1, 0x00, 0x12}, - {0x1, 0x00, 0x13}, - {0x1, 0x00, 0x14}, - {0x1, 0xFF, 0x15}, - {0x1, 0x01, 0x16}, - {0x1, 0x32, 0x17}, - {0x1, 0x23, 0x18}, - {0x1, 0xCE, 0x19}, - {0x1, 0x23, 0x1A}, - {0x1, 0x32, 0x1B}, - {0x1, 0x8D, 0x1C}, - {0x1, 0xCE, 0x1D}, - {0x1, 0x8D, 0x1E}, - {0x1, 0x00, 0x1F}, - {0x1, 0x00, 0x20}, - {0x1, 0xFF, 0x3E}, - {0x1, 0x02, 0x3F}, - {0x1, 0x00, 0x40}, - {0x1, 0x00, 0x41}, - {0x1, 0x00, 0x42}, - {0x1, 0x00, 0x43}, - {0x1, 0x00, 0x44}, - {0x1, 0x00, 0x45}, - {0x1, 0x00, 0x46}, - {0x1, 0x00, 0x47}, - {0x1, 0x00, 0x48}, - {0x1, 0x00, 0x49}, - {0x1, 0x00, 0x4A}, - {0x1, 0x00, 0x4B}, - {0x1, 0x00, 0x4C}, - {0x1, 0x00, 0x4D}, - {0x1, 0x00, 0x4E}, - {0x1, 0x00, 0x4F}, - {0x1, 0x00, 0x50}, - {0x1, 0x00, 0x51}, - {0x1, 0x00, 0x52}, - {0x1, 0x00, 0x53}, - {0x1, 0x00, 0x54}, - {0x1, 0x00, 0x55}, - {0x1, 0x00, 0x56}, - {0x1, 0x00, 0x57}, - {0x1, 0x00, 0x58}, - {0x1, 0x00, 0x59}, - {0x1, 0x00, 0x5A}, - {0x2, 0x03, 0x00}, - {0x2, 0x00, 0x01}, - {0x2, 0x00, 0x05}, - {0x2, 0x00, 0x06}, - {0x2, 0x00, 0x07}, - {0x2, 0x00, 0x10}, - {0x2, 0x00, 0x11}, - /* Strange - looks like the 501 driver doesn't do anything - * at insert time except read the EEPROM - */ - {} -}; - -/* Data for video camera init before capture. - * Capture and decoding by Colin Peart. - * This is is for the 3com HomeConnect Lite which is spca501a based. - */ -static const __u16 spca501_3com_open_data[][3] = { - /* bmRequest,value,index */ - {0x2, 0x0050, 0x0000}, /* C/S Enable TG soft reset, timing mode=010 */ - {0x2, 0x0043, 0x0000}, /* C/S Disable TG soft reset, timing mode=010 */ - {0x2, 0x0002, 0x0005}, /* C/S GPIO */ - {0x2, 0x0003, 0x0005}, /* C/S GPIO */ - -#ifdef CCDSP_SET - {0x1, 0x0020, 0x0001}, /* CCDSP Options */ - - {0x1, 0x0020, 0x0002}, /* CCDSP Black Level */ - {0x1, 0x006e, 0x0007}, /* CCDSP Gamma options */ - {0x1, 0x0090, 0x0015}, /* CCDSP Luminance Low */ - {0x1, 0x00ff, 0x0016}, /* CCDSP Luminance High */ - {0x1, 0x0003, 0x003F}, /* CCDSP Gamma correction toggle */ - -#ifdef ALTER_GAMMA - {0x1, 0x0010, 0x0008}, /* CCDSP YUV A11 */ - {0x1, 0x0000, 0x0009}, /* CCDSP YUV A12 */ - {0x1, 0x0000, 0x000a}, /* CCDSP YUV A13 */ - {0x1, 0x0000, 0x000b}, /* CCDSP YUV A21 */ - {0x1, 0x0010, 0x000c}, /* CCDSP YUV A22 */ - {0x1, 0x0000, 0x000d}, /* CCDSP YUV A23 */ - {0x1, 0x0000, 0x000e}, /* CCDSP YUV A31 */ - {0x1, 0x0000, 0x000f}, /* CCDSP YUV A32 */ - {0x1, 0x0010, 0x0010}, /* CCDSP YUV A33 */ - {0x1, 0x0000, 0x0011}, /* CCDSP R Offset */ - {0x1, 0x0000, 0x0012}, /* CCDSP G Offset */ - {0x1, 0x0001, 0x0013}, /* CCDSP B Offset */ - {0x1, 0x0001, 0x0014}, /* CCDSP BG Offset */ - {0x1, 0x003f, 0x00C1}, /* CCDSP Gamma Correction Enable */ -#endif -#endif - -#ifdef TG_SET - {0x0, 0x00fc, 0x0000}, /* TG Shutter Speed High Bits */ - {0x0, 0x0000, 0x0001}, /* TG Shutter Speed Low Bits */ - {0x0, 0x00e4, 0x0004}, /* TG DCLK*2 Adjust */ - {0x0, 0x0008, 0x0005}, /* TG ADCK Adjust */ - {0x0, 0x0003, 0x0006}, /* TG FR Phase Adjust */ - {0x0, 0x0001, 0x0007}, /* TG FCDS Phase Adjust */ - {0x0, 0x0039, 0x0008}, /* TG FS Phase Adjust */ - {0x0, 0x0088, 0x000a}, /* TG MH1 */ - {0x0, 0x0003, 0x000f}, /* TG Pixel ID */ - - /* Like below, unexplained toglleing */ - {0x0, 0x0080, 0x000c}, - {0x0, 0x0000, 0x000d}, - {0x0, 0x0080, 0x000c}, - {0x0, 0x0004, 0x000d}, - {0x0, 0x0000, 0x000c}, - {0x0, 0x0000, 0x000d}, - {0x0, 0x0040, 0x000c}, - {0x0, 0x0017, 0x000d}, - {0x0, 0x00c0, 0x000c}, - {0x0, 0x0000, 0x000d}, - {0x0, 0x0080, 0x000c}, - {0x0, 0x0006, 0x000d}, - {0x0, 0x0080, 0x000c}, - {0x0, 0x0004, 0x000d}, - {0x0, 0x0002, 0x0003}, -#endif - -#ifdef DSPWIN_SET - {0x1, 0x001c, 0x0017}, /* CCDSP W1 Start X */ - {0x1, 0x00e2, 0x0019}, /* CCDSP W2 Start X */ - {0x1, 0x001c, 0x001b}, /* CCDSP W3 Start X */ - {0x1, 0x00e2, 0x001d}, /* CCDSP W4 Start X */ - {0x1, 0x00aa, 0x001f}, /* CCDSP W5 Start X */ - {0x1, 0x0070, 0x0020}, /* CCDSP W5 Start Y */ -#endif - {0x0, 0x0001, 0x0010}, /* TG Start Clock */ - -/* {0x2, 0x006a, 0x0001}, * C/S Enable ISOSYNCH Packet Engine */ - {0x2, 0x0068, 0x0001}, /* C/S Diable ISOSYNCH Packet Engine */ - {0x2, 0x0000, 0x0005}, - {0x2, 0x0043, 0x0000}, /* C/S Set Timing Mode, Disable TG soft reset */ - {0x2, 0x0043, 0x0000}, /* C/S Set Timing Mode, Disable TG soft reset */ - {0x2, 0x0002, 0x0005}, /* C/S GPIO */ - {0x2, 0x0003, 0x0005}, /* C/S GPIO */ - - {0x2, 0x006a, 0x0001}, /* C/S Enable ISOSYNCH Packet Engine */ - {} -}; - -/* - * Data used to initialize a SPCA501C with HV7131B sensor. - * From a capture file taken with USBSnoop v 1.5 - * I have a "SPCA501C pc camera chipset" manual by sunplus, but some - * of the value meanings are obscure or simply "reserved". - * to do list: - * 1) Understand what every value means - * 2) Understand why some values seem to appear more than once - * 3) Write a small comment for each line of the following arrays. - */ -static const __u16 spca501c_arowana_open_data[][3] = { - /* bmRequest,value,index */ - {0x02, 0x0007, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x05, 0x0022, 0x0004}, - {0x01, 0x0006, 0x0011}, - {0x01, 0x00ff, 0x0012}, - {0x01, 0x0014, 0x0013}, - {0x01, 0x0000, 0x0014}, - {0x01, 0x0042, 0x0051}, - {0x01, 0x0040, 0x0052}, - {0x01, 0x0051, 0x0053}, - {0x01, 0x0040, 0x0054}, - {0x01, 0x0000, 0x0055}, - {0x00, 0x0025, 0x0000}, - {0x00, 0x0026, 0x0000}, - {0x00, 0x0001, 0x0000}, - {0x00, 0x0027, 0x0000}, - {0x00, 0x008a, 0x0000}, - {} -}; - -static const __u16 spca501c_arowana_init_data[][3] = { - /* bmRequest,value,index */ - {0x02, 0x0007, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x05, 0x0022, 0x0004}, - {0x01, 0x0006, 0x0011}, - {0x01, 0x00ff, 0x0012}, - {0x01, 0x0014, 0x0013}, - {0x01, 0x0000, 0x0014}, - {0x01, 0x0042, 0x0051}, - {0x01, 0x0040, 0x0052}, - {0x01, 0x0051, 0x0053}, - {0x01, 0x0040, 0x0054}, - {0x01, 0x0000, 0x0055}, - {0x00, 0x0025, 0x0000}, - {0x00, 0x0026, 0x0000}, - {0x00, 0x0001, 0x0000}, - {0x00, 0x0027, 0x0000}, - {0x00, 0x008a, 0x0000}, - {0x02, 0x0000, 0x0005}, - {0x02, 0x0007, 0x0005}, - {0x02, 0x2000, 0x0000}, - {0x05, 0x0022, 0x0004}, - {0x05, 0x0015, 0x0001}, - {0x05, 0x00ea, 0x0000}, - {0x05, 0x0021, 0x0001}, - {0x05, 0x00d2, 0x0000}, - {0x05, 0x0023, 0x0001}, - {0x05, 0x0003, 0x0000}, - {0x05, 0x0030, 0x0001}, - {0x05, 0x002b, 0x0000}, - {0x05, 0x0031, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0032, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0033, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0034, 0x0001}, - {0x05, 0x0002, 0x0000}, - {0x05, 0x0050, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0051, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0052, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0054, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x00, 0x0000, 0x0001}, - {0x00, 0x0000, 0x0002}, - {0x00, 0x000c, 0x0003}, - {0x00, 0x0000, 0x0004}, - {0x00, 0x0090, 0x0005}, - {0x00, 0x0000, 0x0006}, - {0x00, 0x0040, 0x0007}, - {0x00, 0x00c0, 0x0008}, - {0x00, 0x004a, 0x0009}, - {0x00, 0x0000, 0x000a}, - {0x00, 0x0000, 0x000b}, - {0x00, 0x0001, 0x000c}, - {0x00, 0x0001, 0x000d}, - {0x00, 0x0000, 0x000e}, - {0x00, 0x0002, 0x000f}, - {0x00, 0x0001, 0x0010}, - {0x00, 0x0000, 0x0011}, - {0x00, 0x0000, 0x0012}, - {0x00, 0x0002, 0x0020}, - {0x00, 0x0080, 0x0021}, - {0x00, 0x0001, 0x0022}, - {0x00, 0x00e0, 0x0023}, - {0x00, 0x0000, 0x0024}, - {0x00, 0x00d5, 0x0025}, - {0x00, 0x0000, 0x0026}, - {0x00, 0x000b, 0x0027}, - {0x00, 0x0000, 0x0046}, - {0x00, 0x0000, 0x0047}, - {0x00, 0x0000, 0x0048}, - {0x00, 0x0000, 0x0049}, - {0x00, 0x0008, 0x004a}, - {0xff, 0x0000, 0x00d0}, - {0xff, 0x00d8, 0x00d1}, - {0xff, 0x0000, 0x00d4}, - {0xff, 0x0000, 0x00d5}, - {0x01, 0x00a6, 0x0000}, - {0x01, 0x0028, 0x0001}, - {0x01, 0x0000, 0x0002}, - {0x01, 0x000a, 0x0003}, - {0x01, 0x0040, 0x0004}, - {0x01, 0x0066, 0x0007}, - {0x01, 0x0011, 0x0008}, - {0x01, 0x0032, 0x0009}, - {0x01, 0x00fd, 0x000a}, - {0x01, 0x0038, 0x000b}, - {0x01, 0x00d1, 0x000c}, - {0x01, 0x00f7, 0x000d}, - {0x01, 0x00ed, 0x000e}, - {0x01, 0x00d8, 0x000f}, - {0x01, 0x0038, 0x0010}, - {0x01, 0x00ff, 0x0015}, - {0x01, 0x0001, 0x0016}, - {0x01, 0x0032, 0x0017}, - {0x01, 0x0023, 0x0018}, - {0x01, 0x00ce, 0x0019}, - {0x01, 0x0023, 0x001a}, - {0x01, 0x0032, 0x001b}, - {0x01, 0x008d, 0x001c}, - {0x01, 0x00ce, 0x001d}, - {0x01, 0x008d, 0x001e}, - {0x01, 0x0000, 0x001f}, - {0x01, 0x0000, 0x0020}, - {0x01, 0x00ff, 0x003e}, - {0x01, 0x0003, 0x003f}, - {0x01, 0x0000, 0x0040}, - {0x01, 0x0035, 0x0041}, - {0x01, 0x0053, 0x0042}, - {0x01, 0x0069, 0x0043}, - {0x01, 0x007c, 0x0044}, - {0x01, 0x008c, 0x0045}, - {0x01, 0x009a, 0x0046}, - {0x01, 0x00a8, 0x0047}, - {0x01, 0x00b4, 0x0048}, - {0x01, 0x00bf, 0x0049}, - {0x01, 0x00ca, 0x004a}, - {0x01, 0x00d4, 0x004b}, - {0x01, 0x00dd, 0x004c}, - {0x01, 0x00e7, 0x004d}, - {0x01, 0x00ef, 0x004e}, - {0x01, 0x00f8, 0x004f}, - {0x01, 0x00ff, 0x0050}, - {0x01, 0x0001, 0x0056}, - {0x01, 0x0060, 0x0057}, - {0x01, 0x0040, 0x0058}, - {0x01, 0x0011, 0x0059}, - {0x01, 0x0001, 0x005a}, - {0x02, 0x0007, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x02, 0x0007, 0x0005}, - {0x02, 0x0015, 0x0006}, - {0x02, 0x100a, 0x0007}, - {0x02, 0xa048, 0x0000}, - {0x02, 0xc002, 0x0001}, - {0x02, 0x000f, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x05, 0x0022, 0x0004}, - {0x05, 0x0025, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0026, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x05, 0x0027, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0001, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0021, 0x0001}, - {0x05, 0x00d2, 0x0000}, - {0x05, 0x0020, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x00, 0x0090, 0x0005}, - {0x01, 0x00a6, 0x0000}, - {0x02, 0x0007, 0x0005}, - {0x02, 0x2000, 0x0000}, - {0x05, 0x0022, 0x0004}, - {0x05, 0x0015, 0x0001}, - {0x05, 0x00ea, 0x0000}, - {0x05, 0x0021, 0x0001}, - {0x05, 0x00d2, 0x0000}, - {0x05, 0x0023, 0x0001}, - {0x05, 0x0003, 0x0000}, - {0x05, 0x0030, 0x0001}, - {0x05, 0x002b, 0x0000}, - {0x05, 0x0031, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0032, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0033, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0034, 0x0001}, - {0x05, 0x0002, 0x0000}, - {0x05, 0x0050, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0051, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0052, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0054, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x00, 0x0000, 0x0001}, - {0x00, 0x0000, 0x0002}, - {0x00, 0x000c, 0x0003}, - {0x00, 0x0000, 0x0004}, - {0x00, 0x0090, 0x0005}, - {0x00, 0x0000, 0x0006}, - {0x00, 0x0040, 0x0007}, - {0x00, 0x00c0, 0x0008}, - {0x00, 0x004a, 0x0009}, - {0x00, 0x0000, 0x000a}, - {0x00, 0x0000, 0x000b}, - {0x00, 0x0001, 0x000c}, - {0x00, 0x0001, 0x000d}, - {0x00, 0x0000, 0x000e}, - {0x00, 0x0002, 0x000f}, - {0x00, 0x0001, 0x0010}, - {0x00, 0x0000, 0x0011}, - {0x00, 0x0000, 0x0012}, - {0x00, 0x0002, 0x0020}, - {0x00, 0x0080, 0x0021}, - {0x00, 0x0001, 0x0022}, - {0x00, 0x00e0, 0x0023}, - {0x00, 0x0000, 0x0024}, - {0x00, 0x00d5, 0x0025}, - {0x00, 0x0000, 0x0026}, - {0x00, 0x000b, 0x0027}, - {0x00, 0x0000, 0x0046}, - {0x00, 0x0000, 0x0047}, - {0x00, 0x0000, 0x0048}, - {0x00, 0x0000, 0x0049}, - {0x00, 0x0008, 0x004a}, - {0xff, 0x0000, 0x00d0}, - {0xff, 0x00d8, 0x00d1}, - {0xff, 0x0000, 0x00d4}, - {0xff, 0x0000, 0x00d5}, - {0x01, 0x00a6, 0x0000}, - {0x01, 0x0028, 0x0001}, - {0x01, 0x0000, 0x0002}, - {0x01, 0x000a, 0x0003}, - {0x01, 0x0040, 0x0004}, - {0x01, 0x0066, 0x0007}, - {0x01, 0x0011, 0x0008}, - {0x01, 0x0032, 0x0009}, - {0x01, 0x00fd, 0x000a}, - {0x01, 0x0038, 0x000b}, - {0x01, 0x00d1, 0x000c}, - {0x01, 0x00f7, 0x000d}, - {0x01, 0x00ed, 0x000e}, - {0x01, 0x00d8, 0x000f}, - {0x01, 0x0038, 0x0010}, - {0x01, 0x00ff, 0x0015}, - {0x01, 0x0001, 0x0016}, - {0x01, 0x0032, 0x0017}, - {0x01, 0x0023, 0x0018}, - {0x01, 0x00ce, 0x0019}, - {0x01, 0x0023, 0x001a}, - {0x01, 0x0032, 0x001b}, - {0x01, 0x008d, 0x001c}, - {0x01, 0x00ce, 0x001d}, - {0x01, 0x008d, 0x001e}, - {0x01, 0x0000, 0x001f}, - {0x01, 0x0000, 0x0020}, - {0x01, 0x00ff, 0x003e}, - {0x01, 0x0003, 0x003f}, - {0x01, 0x0000, 0x0040}, - {0x01, 0x0035, 0x0041}, - {0x01, 0x0053, 0x0042}, - {0x01, 0x0069, 0x0043}, - {0x01, 0x007c, 0x0044}, - {0x01, 0x008c, 0x0045}, - {0x01, 0x009a, 0x0046}, - {0x01, 0x00a8, 0x0047}, - {0x01, 0x00b4, 0x0048}, - {0x01, 0x00bf, 0x0049}, - {0x01, 0x00ca, 0x004a}, - {0x01, 0x00d4, 0x004b}, - {0x01, 0x00dd, 0x004c}, - {0x01, 0x00e7, 0x004d}, - {0x01, 0x00ef, 0x004e}, - {0x01, 0x00f8, 0x004f}, - {0x01, 0x00ff, 0x0050}, - {0x01, 0x0001, 0x0056}, - {0x01, 0x0060, 0x0057}, - {0x01, 0x0040, 0x0058}, - {0x01, 0x0011, 0x0059}, - {0x01, 0x0001, 0x005a}, - {0x02, 0x0007, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x02, 0x0007, 0x0005}, - {0x02, 0x0015, 0x0006}, - {0x02, 0x100a, 0x0007}, - {0x02, 0xa048, 0x0000}, - {0x02, 0xc002, 0x0001}, - {0x02, 0x000f, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x05, 0x0022, 0x0004}, - {0x05, 0x0025, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0026, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x05, 0x0027, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0001, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0021, 0x0001}, - {0x05, 0x00d2, 0x0000}, - {0x05, 0x0020, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x00, 0x0090, 0x0005}, - {0x01, 0x00a6, 0x0000}, - {0x01, 0x0003, 0x003f}, - {0x01, 0x0001, 0x0056}, - {0x01, 0x0011, 0x0008}, - {0x01, 0x0032, 0x0009}, - {0x01, 0xfffd, 0x000a}, - {0x01, 0x0023, 0x000b}, - {0x01, 0xffea, 0x000c}, - {0x01, 0xfff4, 0x000d}, - {0x01, 0xfffc, 0x000e}, - {0x01, 0xffe3, 0x000f}, - {0x01, 0x001f, 0x0010}, - {0x01, 0x00a8, 0x0001}, - {0x01, 0x0067, 0x0007}, - {0x01, 0x0032, 0x0017}, - {0x01, 0x0023, 0x0018}, - {0x01, 0x00ce, 0x0019}, - {0x01, 0x0023, 0x001a}, - {0x01, 0x0032, 0x001b}, - {0x01, 0x008d, 0x001c}, - {0x01, 0x00ce, 0x001d}, - {0x01, 0x008d, 0x001e}, - {0x01, 0x00c8, 0x0015}, - {0x01, 0x0032, 0x0016}, - {0x01, 0x0000, 0x0011}, - {0x01, 0x0000, 0x0012}, - {0x01, 0x0000, 0x0013}, - {0x01, 0x000a, 0x0003}, - {0x02, 0xc002, 0x0001}, - {0x02, 0x0007, 0x0005}, - {0x02, 0xc000, 0x0001}, - {0x02, 0x0000, 0x0005}, - {0x02, 0x0007, 0x0005}, - {0x02, 0x2000, 0x0000}, - {0x05, 0x0022, 0x0004}, - {0x05, 0x0015, 0x0001}, - {0x05, 0x00ea, 0x0000}, - {0x05, 0x0021, 0x0001}, - {0x05, 0x00d2, 0x0000}, - {0x05, 0x0023, 0x0001}, - {0x05, 0x0003, 0x0000}, - {0x05, 0x0030, 0x0001}, - {0x05, 0x002b, 0x0000}, - {0x05, 0x0031, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0032, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0033, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0034, 0x0001}, - {0x05, 0x0002, 0x0000}, - {0x05, 0x0050, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0051, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0052, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0054, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x00, 0x0000, 0x0001}, - {0x00, 0x0000, 0x0002}, - {0x00, 0x000c, 0x0003}, - {0x00, 0x0000, 0x0004}, - {0x00, 0x0090, 0x0005}, - {0x00, 0x0000, 0x0006}, - {0x00, 0x0040, 0x0007}, - {0x00, 0x00c0, 0x0008}, - {0x00, 0x004a, 0x0009}, - {0x00, 0x0000, 0x000a}, - {0x00, 0x0000, 0x000b}, - {0x00, 0x0001, 0x000c}, - {0x00, 0x0001, 0x000d}, - {0x00, 0x0000, 0x000e}, - {0x00, 0x0002, 0x000f}, - {0x00, 0x0001, 0x0010}, - {0x00, 0x0000, 0x0011}, - {0x00, 0x0000, 0x0012}, - {0x00, 0x0002, 0x0020}, - {0x00, 0x0080, 0x0021}, - {0x00, 0x0001, 0x0022}, - {0x00, 0x00e0, 0x0023}, - {0x00, 0x0000, 0x0024}, - {0x00, 0x00d5, 0x0025}, - {0x00, 0x0000, 0x0026}, - {0x00, 0x000b, 0x0027}, - {0x00, 0x0000, 0x0046}, - {0x00, 0x0000, 0x0047}, - {0x00, 0x0000, 0x0048}, - {0x00, 0x0000, 0x0049}, - {0x00, 0x0008, 0x004a}, - {0xff, 0x0000, 0x00d0}, - {0xff, 0x00d8, 0x00d1}, - {0xff, 0x0000, 0x00d4}, - {0xff, 0x0000, 0x00d5}, - {0x01, 0x00a6, 0x0000}, - {0x01, 0x0028, 0x0001}, - {0x01, 0x0000, 0x0002}, - {0x01, 0x000a, 0x0003}, - {0x01, 0x0040, 0x0004}, - {0x01, 0x0066, 0x0007}, - {0x01, 0x0011, 0x0008}, - {0x01, 0x0032, 0x0009}, - {0x01, 0x00fd, 0x000a}, - {0x01, 0x0038, 0x000b}, - {0x01, 0x00d1, 0x000c}, - {0x01, 0x00f7, 0x000d}, - {0x01, 0x00ed, 0x000e}, - {0x01, 0x00d8, 0x000f}, - {0x01, 0x0038, 0x0010}, - {0x01, 0x00ff, 0x0015}, - {0x01, 0x0001, 0x0016}, - {0x01, 0x0032, 0x0017}, - {0x01, 0x0023, 0x0018}, - {0x01, 0x00ce, 0x0019}, - {0x01, 0x0023, 0x001a}, - {0x01, 0x0032, 0x001b}, - {0x01, 0x008d, 0x001c}, - {0x01, 0x00ce, 0x001d}, - {0x01, 0x008d, 0x001e}, - {0x01, 0x0000, 0x001f}, - {0x01, 0x0000, 0x0020}, - {0x01, 0x00ff, 0x003e}, - {0x01, 0x0003, 0x003f}, - {0x01, 0x0000, 0x0040}, - {0x01, 0x0035, 0x0041}, - {0x01, 0x0053, 0x0042}, - {0x01, 0x0069, 0x0043}, - {0x01, 0x007c, 0x0044}, - {0x01, 0x008c, 0x0045}, - {0x01, 0x009a, 0x0046}, - {0x01, 0x00a8, 0x0047}, - {0x01, 0x00b4, 0x0048}, - {0x01, 0x00bf, 0x0049}, - {0x01, 0x00ca, 0x004a}, - {0x01, 0x00d4, 0x004b}, - {0x01, 0x00dd, 0x004c}, - {0x01, 0x00e7, 0x004d}, - {0x01, 0x00ef, 0x004e}, - {0x01, 0x00f8, 0x004f}, - {0x01, 0x00ff, 0x0050}, - {0x01, 0x0001, 0x0056}, - {0x01, 0x0060, 0x0057}, - {0x01, 0x0040, 0x0058}, - {0x01, 0x0011, 0x0059}, - {0x01, 0x0001, 0x005a}, - {0x02, 0x0007, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x02, 0x0007, 0x0005}, - {0x02, 0x0015, 0x0006}, - {0x02, 0x100a, 0x0007}, - {0x02, 0xa048, 0x0000}, - {0x02, 0xc002, 0x0001}, - {0x02, 0x000f, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x05, 0x0022, 0x0004}, - {0x05, 0x0025, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0026, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x05, 0x0027, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0001, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0021, 0x0001}, - {0x05, 0x00d2, 0x0000}, - {0x05, 0x0020, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x00, 0x0090, 0x0005}, - {0x01, 0x00a6, 0x0000}, - {0x02, 0x0007, 0x0005}, - {0x02, 0x2000, 0x0000}, - {0x05, 0x0022, 0x0004}, - {0x05, 0x0015, 0x0001}, - {0x05, 0x00ea, 0x0000}, - {0x05, 0x0021, 0x0001}, - {0x05, 0x00d2, 0x0000}, - {0x05, 0x0023, 0x0001}, - {0x05, 0x0003, 0x0000}, - {0x05, 0x0030, 0x0001}, - {0x05, 0x002b, 0x0000}, - {0x05, 0x0031, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0032, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0033, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0034, 0x0001}, - {0x05, 0x0002, 0x0000}, - {0x05, 0x0050, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0051, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0052, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0054, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x00, 0x0000, 0x0001}, - {0x00, 0x0000, 0x0002}, - {0x00, 0x000c, 0x0003}, - {0x00, 0x0000, 0x0004}, - {0x00, 0x0090, 0x0005}, - {0x00, 0x0000, 0x0006}, - {0x00, 0x0040, 0x0007}, - {0x00, 0x00c0, 0x0008}, - {0x00, 0x004a, 0x0009}, - {0x00, 0x0000, 0x000a}, - {0x00, 0x0000, 0x000b}, - {0x00, 0x0001, 0x000c}, - {0x00, 0x0001, 0x000d}, - {0x00, 0x0000, 0x000e}, - {0x00, 0x0002, 0x000f}, - {0x00, 0x0001, 0x0010}, - {0x00, 0x0000, 0x0011}, - {0x00, 0x0000, 0x0012}, - {0x00, 0x0002, 0x0020}, - {0x00, 0x0080, 0x0021}, - {0x00, 0x0001, 0x0022}, - {0x00, 0x00e0, 0x0023}, - {0x00, 0x0000, 0x0024}, - {0x00, 0x00d5, 0x0025}, - {0x00, 0x0000, 0x0026}, - {0x00, 0x000b, 0x0027}, - {0x00, 0x0000, 0x0046}, - {0x00, 0x0000, 0x0047}, - {0x00, 0x0000, 0x0048}, - {0x00, 0x0000, 0x0049}, - {0x00, 0x0008, 0x004a}, - {0xff, 0x0000, 0x00d0}, - {0xff, 0x00d8, 0x00d1}, - {0xff, 0x0000, 0x00d4}, - {0xff, 0x0000, 0x00d5}, - {0x01, 0x00a6, 0x0000}, - {0x01, 0x0028, 0x0001}, - {0x01, 0x0000, 0x0002}, - {0x01, 0x000a, 0x0003}, - {0x01, 0x0040, 0x0004}, - {0x01, 0x0066, 0x0007}, - {0x01, 0x0011, 0x0008}, - {0x01, 0x0032, 0x0009}, - {0x01, 0x00fd, 0x000a}, - {0x01, 0x0038, 0x000b}, - {0x01, 0x00d1, 0x000c}, - {0x01, 0x00f7, 0x000d}, - {0x01, 0x00ed, 0x000e}, - {0x01, 0x00d8, 0x000f}, - {0x01, 0x0038, 0x0010}, - {0x01, 0x00ff, 0x0015}, - {0x01, 0x0001, 0x0016}, - {0x01, 0x0032, 0x0017}, - {0x01, 0x0023, 0x0018}, - {0x01, 0x00ce, 0x0019}, - {0x01, 0x0023, 0x001a}, - {0x01, 0x0032, 0x001b}, - {0x01, 0x008d, 0x001c}, - {0x01, 0x00ce, 0x001d}, - {0x01, 0x008d, 0x001e}, - {0x01, 0x0000, 0x001f}, - {0x01, 0x0000, 0x0020}, - {0x01, 0x00ff, 0x003e}, - {0x01, 0x0003, 0x003f}, - {0x01, 0x0000, 0x0040}, - {0x01, 0x0035, 0x0041}, - {0x01, 0x0053, 0x0042}, - {0x01, 0x0069, 0x0043}, - {0x01, 0x007c, 0x0044}, - {0x01, 0x008c, 0x0045}, - {0x01, 0x009a, 0x0046}, - {0x01, 0x00a8, 0x0047}, - {0x01, 0x00b4, 0x0048}, - {0x01, 0x00bf, 0x0049}, - {0x01, 0x00ca, 0x004a}, - {0x01, 0x00d4, 0x004b}, - {0x01, 0x00dd, 0x004c}, - {0x01, 0x00e7, 0x004d}, - {0x01, 0x00ef, 0x004e}, - {0x01, 0x00f8, 0x004f}, - {0x01, 0x00ff, 0x0050}, - {0x01, 0x0001, 0x0056}, - {0x01, 0x0060, 0x0057}, - {0x01, 0x0040, 0x0058}, - {0x01, 0x0011, 0x0059}, - {0x01, 0x0001, 0x005a}, - {0x02, 0x0007, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x02, 0x0007, 0x0005}, - {0x02, 0x0015, 0x0006}, - {0x02, 0x100a, 0x0007}, - {0x02, 0xa048, 0x0000}, - {0x02, 0xc002, 0x0001}, - {0x02, 0x000f, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x05, 0x0022, 0x0004}, - {0x05, 0x0025, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0026, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x05, 0x0027, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0001, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0021, 0x0001}, - {0x05, 0x00d2, 0x0000}, - {0x05, 0x0020, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x00, 0x0090, 0x0005}, - {0x01, 0x00a6, 0x0000}, - {0x05, 0x0026, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x05, 0x0027, 0x0001}, - {0x05, 0x000f, 0x0000}, - {0x01, 0x0003, 0x003f}, - {0x01, 0x0001, 0x0056}, - {0x01, 0x0011, 0x0008}, - {0x01, 0x0032, 0x0009}, - {0x01, 0xfffd, 0x000a}, - {0x01, 0x0023, 0x000b}, - {0x01, 0xffea, 0x000c}, - {0x01, 0xfff4, 0x000d}, - {0x01, 0xfffc, 0x000e}, - {0x01, 0xffe3, 0x000f}, - {0x01, 0x001f, 0x0010}, - {0x01, 0x00a8, 0x0001}, - {0x01, 0x0067, 0x0007}, - {0x01, 0x0042, 0x0051}, - {0x01, 0x0051, 0x0053}, - {0x01, 0x000a, 0x0003}, - {0x02, 0xc002, 0x0001}, - {0x02, 0x0007, 0x0005}, - {0x02, 0xc000, 0x0001}, - {0x02, 0x0000, 0x0005}, - {0x02, 0x0007, 0x0005}, - {0x02, 0x2000, 0x0000}, - {0x05, 0x0022, 0x0004}, - {0x05, 0x0015, 0x0001}, - {0x05, 0x00ea, 0x0000}, - {0x05, 0x0021, 0x0001}, - {0x05, 0x00d2, 0x0000}, - {0x05, 0x0023, 0x0001}, - {0x05, 0x0003, 0x0000}, - {0x05, 0x0030, 0x0001}, - {0x05, 0x002b, 0x0000}, - {0x05, 0x0031, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0032, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0033, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0034, 0x0001}, - {0x05, 0x0002, 0x0000}, - {0x05, 0x0050, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0051, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0052, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0054, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x00, 0x0000, 0x0001}, - {0x00, 0x0000, 0x0002}, - {0x00, 0x000c, 0x0003}, - {0x00, 0x0000, 0x0004}, - {0x00, 0x0090, 0x0005}, - {0x00, 0x0000, 0x0006}, - {0x00, 0x0040, 0x0007}, - {0x00, 0x00c0, 0x0008}, - {0x00, 0x004a, 0x0009}, - {0x00, 0x0000, 0x000a}, - {0x00, 0x0000, 0x000b}, - {0x00, 0x0001, 0x000c}, - {0x00, 0x0001, 0x000d}, - {0x00, 0x0000, 0x000e}, - {0x00, 0x0002, 0x000f}, - {0x00, 0x0001, 0x0010}, - {0x00, 0x0000, 0x0011}, - {0x00, 0x0000, 0x0012}, - {0x00, 0x0002, 0x0020}, - {0x00, 0x0080, 0x0021}, - {0x00, 0x0001, 0x0022}, - {0x00, 0x00e0, 0x0023}, - {0x00, 0x0000, 0x0024}, - {0x00, 0x00d5, 0x0025}, - {0x00, 0x0000, 0x0026}, - {0x00, 0x000b, 0x0027}, - {0x00, 0x0000, 0x0046}, - {0x00, 0x0000, 0x0047}, - {0x00, 0x0000, 0x0048}, - {0x00, 0x0000, 0x0049}, - {0x00, 0x0008, 0x004a}, - {0xff, 0x0000, 0x00d0}, - {0xff, 0x00d8, 0x00d1}, - {0xff, 0x0000, 0x00d4}, - {0xff, 0x0000, 0x00d5}, - {0x01, 0x00a6, 0x0000}, - {0x01, 0x0028, 0x0001}, - {0x01, 0x0000, 0x0002}, - {0x01, 0x000a, 0x0003}, - {0x01, 0x0040, 0x0004}, - {0x01, 0x0066, 0x0007}, - {0x01, 0x0011, 0x0008}, - {0x01, 0x0032, 0x0009}, - {0x01, 0x00fd, 0x000a}, - {0x01, 0x0038, 0x000b}, - {0x01, 0x00d1, 0x000c}, - {0x01, 0x00f7, 0x000d}, - {0x01, 0x00ed, 0x000e}, - {0x01, 0x00d8, 0x000f}, - {0x01, 0x0038, 0x0010}, - {0x01, 0x00ff, 0x0015}, - {0x01, 0x0001, 0x0016}, - {0x01, 0x0032, 0x0017}, - {0x01, 0x0023, 0x0018}, - {0x01, 0x00ce, 0x0019}, - {0x01, 0x0023, 0x001a}, - {0x01, 0x0032, 0x001b}, - {0x01, 0x008d, 0x001c}, - {0x01, 0x00ce, 0x001d}, - {0x01, 0x008d, 0x001e}, - {0x01, 0x0000, 0x001f}, - {0x01, 0x0000, 0x0020}, - {0x01, 0x00ff, 0x003e}, - {0x01, 0x0003, 0x003f}, - {0x01, 0x0000, 0x0040}, - {0x01, 0x0035, 0x0041}, - {0x01, 0x0053, 0x0042}, - {0x01, 0x0069, 0x0043}, - {0x01, 0x007c, 0x0044}, - {0x01, 0x008c, 0x0045}, - {0x01, 0x009a, 0x0046}, - {0x01, 0x00a8, 0x0047}, - {0x01, 0x00b4, 0x0048}, - {0x01, 0x00bf, 0x0049}, - {0x01, 0x00ca, 0x004a}, - {0x01, 0x00d4, 0x004b}, - {0x01, 0x00dd, 0x004c}, - {0x01, 0x00e7, 0x004d}, - {0x01, 0x00ef, 0x004e}, - {0x01, 0x00f8, 0x004f}, - {0x01, 0x00ff, 0x0050}, - {0x01, 0x0001, 0x0056}, - {0x01, 0x0060, 0x0057}, - {0x01, 0x0040, 0x0058}, - {0x01, 0x0011, 0x0059}, - {0x01, 0x0001, 0x005a}, - {0x02, 0x0007, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x02, 0x0007, 0x0005}, - {0x02, 0x0015, 0x0006}, - {0x02, 0x100a, 0x0007}, - {0x02, 0xa048, 0x0000}, - {0x02, 0xc002, 0x0001}, - {0x02, 0x000f, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x05, 0x0022, 0x0004}, - {0x05, 0x0025, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0026, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x05, 0x0027, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0001, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0021, 0x0001}, - {0x05, 0x00d2, 0x0000}, - {0x05, 0x0020, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x00, 0x0090, 0x0005}, - {0x01, 0x00a6, 0x0000}, - {0x02, 0x0007, 0x0005}, - {0x02, 0x2000, 0x0000}, - {0x05, 0x0022, 0x0004}, - {0x05, 0x0015, 0x0001}, - {0x05, 0x00ea, 0x0000}, - {0x05, 0x0021, 0x0001}, - {0x05, 0x00d2, 0x0000}, - {0x05, 0x0023, 0x0001}, - {0x05, 0x0003, 0x0000}, - {0x05, 0x0030, 0x0001}, - {0x05, 0x002b, 0x0000}, - {0x05, 0x0031, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0032, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0033, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0034, 0x0001}, - {0x05, 0x0002, 0x0000}, - {0x05, 0x0050, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0051, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0052, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0054, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x00, 0x0000, 0x0001}, - {0x00, 0x0000, 0x0002}, - {0x00, 0x000c, 0x0003}, - {0x00, 0x0000, 0x0004}, - {0x00, 0x0090, 0x0005}, - {0x00, 0x0000, 0x0006}, - {0x00, 0x0040, 0x0007}, - {0x00, 0x00c0, 0x0008}, - {0x00, 0x004a, 0x0009}, - {0x00, 0x0000, 0x000a}, - {0x00, 0x0000, 0x000b}, - {0x00, 0x0001, 0x000c}, - {0x00, 0x0001, 0x000d}, - {0x00, 0x0000, 0x000e}, - {0x00, 0x0002, 0x000f}, - {0x00, 0x0001, 0x0010}, - {0x00, 0x0000, 0x0011}, - {0x00, 0x0000, 0x0012}, - {0x00, 0x0002, 0x0020}, - {0x00, 0x0080, 0x0021}, - {0x00, 0x0001, 0x0022}, - {0x00, 0x00e0, 0x0023}, - {0x00, 0x0000, 0x0024}, - {0x00, 0x00d5, 0x0025}, - {0x00, 0x0000, 0x0026}, - {0x00, 0x000b, 0x0027}, - {0x00, 0x0000, 0x0046}, - {0x00, 0x0000, 0x0047}, - {0x00, 0x0000, 0x0048}, - {0x00, 0x0000, 0x0049}, - {0x00, 0x0008, 0x004a}, - {0xff, 0x0000, 0x00d0}, - {0xff, 0x00d8, 0x00d1}, - {0xff, 0x0000, 0x00d4}, - {0xff, 0x0000, 0x00d5}, - {0x01, 0x00a6, 0x0000}, - {0x01, 0x0028, 0x0001}, - {0x01, 0x0000, 0x0002}, - {0x01, 0x000a, 0x0003}, - {0x01, 0x0040, 0x0004}, - {0x01, 0x0066, 0x0007}, - {0x01, 0x0011, 0x0008}, - {0x01, 0x0032, 0x0009}, - {0x01, 0x00fd, 0x000a}, - {0x01, 0x0038, 0x000b}, - {0x01, 0x00d1, 0x000c}, - {0x01, 0x00f7, 0x000d}, - {0x01, 0x00ed, 0x000e}, - {0x01, 0x00d8, 0x000f}, - {0x01, 0x0038, 0x0010}, - {0x01, 0x00ff, 0x0015}, - {0x01, 0x0001, 0x0016}, - {0x01, 0x0032, 0x0017}, - {0x01, 0x0023, 0x0018}, - {0x01, 0x00ce, 0x0019}, - {0x01, 0x0023, 0x001a}, - {0x01, 0x0032, 0x001b}, - {0x01, 0x008d, 0x001c}, - {0x01, 0x00ce, 0x001d}, - {0x01, 0x008d, 0x001e}, - {0x01, 0x0000, 0x001f}, - {0x01, 0x0000, 0x0020}, - {0x01, 0x00ff, 0x003e}, - {0x01, 0x0003, 0x003f}, - {0x01, 0x0000, 0x0040}, - {0x01, 0x0035, 0x0041}, - {0x01, 0x0053, 0x0042}, - {0x01, 0x0069, 0x0043}, - {0x01, 0x007c, 0x0044}, - {0x01, 0x008c, 0x0045}, - {0x01, 0x009a, 0x0046}, - {0x01, 0x00a8, 0x0047}, - {0x01, 0x00b4, 0x0048}, - {0x01, 0x00bf, 0x0049}, - {0x01, 0x00ca, 0x004a}, - {0x01, 0x00d4, 0x004b}, - {0x01, 0x00dd, 0x004c}, - {0x01, 0x00e7, 0x004d}, - {0x01, 0x00ef, 0x004e}, - {0x01, 0x00f8, 0x004f}, - {0x01, 0x00ff, 0x0050}, - {0x01, 0x0001, 0x0056}, - {0x01, 0x0060, 0x0057}, - {0x01, 0x0040, 0x0058}, - {0x01, 0x0011, 0x0059}, - {0x01, 0x0001, 0x005a}, - {0x02, 0x0007, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x02, 0x0007, 0x0005}, - {0x02, 0x0015, 0x0006}, - {0x02, 0x100a, 0x0007}, - {0x02, 0xa048, 0x0000}, - {0x02, 0xc002, 0x0001}, - {0x02, 0x000f, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x05, 0x0022, 0x0004}, - {0x05, 0x0025, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0026, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x05, 0x0027, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0001, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0021, 0x0001}, - {0x05, 0x00d2, 0x0000}, - {0x05, 0x0020, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x00, 0x0090, 0x0005}, - {0x01, 0x00a6, 0x0000}, - {0x05, 0x0026, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x05, 0x0027, 0x0001}, - {0x05, 0x001e, 0x0000}, - {0x01, 0x0003, 0x003f}, - {0x01, 0x0001, 0x0056}, - {0x01, 0x0011, 0x0008}, - {0x01, 0x0032, 0x0009}, - {0x01, 0xfffd, 0x000a}, - {0x01, 0x0023, 0x000b}, - {0x01, 0xffea, 0x000c}, - {0x01, 0xfff4, 0x000d}, - {0x01, 0xfffc, 0x000e}, - {0x01, 0xffe3, 0x000f}, - {0x01, 0x001f, 0x0010}, - {0x01, 0x00a8, 0x0001}, - {0x01, 0x0067, 0x0007}, - {0x01, 0x0042, 0x0051}, - {0x01, 0x0051, 0x0053}, - {0x01, 0x000a, 0x0003}, - {0x02, 0xc002, 0x0001}, - {0x02, 0x0007, 0x0005}, - {0x01, 0x0042, 0x0051}, - {0x01, 0x0051, 0x0053}, - {0x05, 0x0026, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x05, 0x0027, 0x0001}, - {0x05, 0x002d, 0x0000}, - {0x01, 0x0003, 0x003f}, - {0x01, 0x0001, 0x0056}, - {0x02, 0xc000, 0x0001}, - {0x02, 0x0000, 0x0005}, - {} -}; - -/* Unknown camera from Ori Usbid 0x0000:0x0000 */ -/* Based on snoops from Ori Cohen */ -static const __u16 spca501c_mysterious_open_data[][3] = { - {0x02, 0x000f, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x05, 0x0022, 0x0004}, -/* DSP Registers */ - {0x01, 0x0016, 0x0011}, /* RGB offset */ - {0x01, 0x0000, 0x0012}, - {0x01, 0x0006, 0x0013}, - {0x01, 0x0078, 0x0051}, - {0x01, 0x0040, 0x0052}, - {0x01, 0x0046, 0x0053}, - {0x01, 0x0040, 0x0054}, - {0x00, 0x0025, 0x0000}, -/* {0x00, 0x0000, 0x0000 }, */ -/* Part 2 */ -/* TG Registers */ - {0x00, 0x0026, 0x0000}, - {0x00, 0x0001, 0x0000}, - {0x00, 0x0027, 0x0000}, - {0x00, 0x008a, 0x0000}, - {0x02, 0x0007, 0x0005}, - {0x02, 0x2000, 0x0000}, - {0x05, 0x0022, 0x0004}, - {0x05, 0x0015, 0x0001}, - {0x05, 0x00ea, 0x0000}, - {0x05, 0x0021, 0x0001}, - {0x05, 0x00d2, 0x0000}, - {0x05, 0x0023, 0x0001}, - {0x05, 0x0003, 0x0000}, - {0x05, 0x0030, 0x0001}, - {0x05, 0x002b, 0x0000}, - {0x05, 0x0031, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0032, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0033, 0x0001}, - {0x05, 0x0023, 0x0000}, - {0x05, 0x0034, 0x0001}, - {0x05, 0x0002, 0x0000}, - {0x05, 0x0050, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0051, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0052, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0054, 0x0001}, - {0x05, 0x0001, 0x0000}, - {} -}; - -/* Based on snoops from Ori Cohen */ -static const __u16 spca501c_mysterious_init_data[][3] = { -/* Part 3 */ -/* TG registers */ -/* {0x00, 0x0000, 0x0000}, */ - {0x00, 0x0000, 0x0001}, - {0x00, 0x0000, 0x0002}, - {0x00, 0x0006, 0x0003}, - {0x00, 0x0000, 0x0004}, - {0x00, 0x0090, 0x0005}, - {0x00, 0x0000, 0x0006}, - {0x00, 0x0040, 0x0007}, - {0x00, 0x00c0, 0x0008}, - {0x00, 0x004a, 0x0009}, - {0x00, 0x0000, 0x000a}, - {0x00, 0x0000, 0x000b}, - {0x00, 0x0001, 0x000c}, - {0x00, 0x0001, 0x000d}, - {0x00, 0x0000, 0x000e}, - {0x00, 0x0002, 0x000f}, - {0x00, 0x0001, 0x0010}, - {0x00, 0x0000, 0x0011}, - {0x00, 0x0001, 0x0012}, - {0x00, 0x0002, 0x0020}, - {0x00, 0x0080, 0x0021}, /* 640 */ - {0x00, 0x0001, 0x0022}, - {0x00, 0x00e0, 0x0023}, /* 480 */ - {0x00, 0x0000, 0x0024}, /* Offset H hight */ - {0x00, 0x00d3, 0x0025}, /* low */ - {0x00, 0x0000, 0x0026}, /* Offset V */ - {0x00, 0x000d, 0x0027}, /* low */ - {0x00, 0x0000, 0x0046}, - {0x00, 0x0000, 0x0047}, - {0x00, 0x0000, 0x0048}, - {0x00, 0x0000, 0x0049}, - {0x00, 0x0008, 0x004a}, -/* DSP Registers */ - {0x01, 0x00a6, 0x0000}, - {0x01, 0x0028, 0x0001}, - {0x01, 0x0000, 0x0002}, - {0x01, 0x000a, 0x0003}, /* Level Calc bit7 ->1 Auto */ - {0x01, 0x0040, 0x0004}, - {0x01, 0x0066, 0x0007}, - {0x01, 0x000f, 0x0008}, /* A11 Color correction coeff */ - {0x01, 0x002d, 0x0009}, /* A12 */ - {0x01, 0x0005, 0x000a}, /* A13 */ - {0x01, 0x0023, 0x000b}, /* A21 */ - {0x01, 0x00e0, 0x000c}, /* A22 */ - {0x01, 0x00fd, 0x000d}, /* A23 */ - {0x01, 0x00f4, 0x000e}, /* A31 */ - {0x01, 0x00e4, 0x000f}, /* A32 */ - {0x01, 0x0028, 0x0010}, /* A33 */ - {0x01, 0x00ff, 0x0015}, /* Reserved */ - {0x01, 0x0001, 0x0016}, /* Reserved */ - {0x01, 0x0032, 0x0017}, /* Win1 Start begin */ - {0x01, 0x0023, 0x0018}, - {0x01, 0x00ce, 0x0019}, - {0x01, 0x0023, 0x001a}, - {0x01, 0x0032, 0x001b}, - {0x01, 0x008d, 0x001c}, - {0x01, 0x00ce, 0x001d}, - {0x01, 0x008d, 0x001e}, - {0x01, 0x0000, 0x001f}, - {0x01, 0x0000, 0x0020}, /* Win1 Start end */ - {0x01, 0x00ff, 0x003e}, /* Reserved begin */ - {0x01, 0x0002, 0x003f}, - {0x01, 0x0000, 0x0040}, - {0x01, 0x0035, 0x0041}, - {0x01, 0x0053, 0x0042}, - {0x01, 0x0069, 0x0043}, - {0x01, 0x007c, 0x0044}, - {0x01, 0x008c, 0x0045}, - {0x01, 0x009a, 0x0046}, - {0x01, 0x00a8, 0x0047}, - {0x01, 0x00b4, 0x0048}, - {0x01, 0x00bf, 0x0049}, - {0x01, 0x00ca, 0x004a}, - {0x01, 0x00d4, 0x004b}, - {0x01, 0x00dd, 0x004c}, - {0x01, 0x00e7, 0x004d}, - {0x01, 0x00ef, 0x004e}, - {0x01, 0x00f8, 0x004f}, - {0x01, 0x00ff, 0x0050}, - {0x01, 0x0003, 0x0056}, /* Reserved end */ - {0x01, 0x0060, 0x0057}, /* Edge Gain */ - {0x01, 0x0040, 0x0058}, - {0x01, 0x0011, 0x0059}, /* Edge Bandwidth */ - {0x01, 0x0001, 0x005a}, - {0x02, 0x0007, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x02, 0x0007, 0x0005}, - {0x02, 0x0015, 0x0006}, - {0x02, 0x200a, 0x0007}, - {0x02, 0xa048, 0x0000}, - {0x02, 0xc000, 0x0001}, - {0x02, 0x000f, 0x0005}, - {0x02, 0xa048, 0x0000}, - {0x05, 0x0022, 0x0004}, - {0x05, 0x0025, 0x0001}, - {0x05, 0x0000, 0x0000}, -/* Part 4 */ - {0x05, 0x0026, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x05, 0x0027, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0001, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x05, 0x0021, 0x0001}, - {0x05, 0x00d2, 0x0000}, - {0x05, 0x0020, 0x0001}, - {0x05, 0x0000, 0x0000}, - {0x00, 0x0090, 0x0005}, - {0x01, 0x00a6, 0x0000}, - {0x02, 0x0000, 0x0005}, - {0x05, 0x0026, 0x0001}, - {0x05, 0x0001, 0x0000}, - {0x05, 0x0027, 0x0001}, - {0x05, 0x004e, 0x0000}, -/* Part 5 */ - {0x01, 0x0003, 0x003f}, - {0x01, 0x0001, 0x0056}, - {0x01, 0x000f, 0x0008}, - {0x01, 0x002d, 0x0009}, - {0x01, 0x0005, 0x000a}, - {0x01, 0x0023, 0x000b}, - {0x01, 0xffe0, 0x000c}, - {0x01, 0xfffd, 0x000d}, - {0x01, 0xfff4, 0x000e}, - {0x01, 0xffe4, 0x000f}, - {0x01, 0x0028, 0x0010}, - {0x01, 0x00a8, 0x0001}, - {0x01, 0x0066, 0x0007}, - {0x01, 0x0032, 0x0017}, - {0x01, 0x0023, 0x0018}, - {0x01, 0x00ce, 0x0019}, - {0x01, 0x0023, 0x001a}, - {0x01, 0x0032, 0x001b}, - {0x01, 0x008d, 0x001c}, - {0x01, 0x00ce, 0x001d}, - {0x01, 0x008d, 0x001e}, - {0x01, 0x00c8, 0x0015}, /* c8 Poids fort Luma */ - {0x01, 0x0032, 0x0016}, /* 32 */ - {0x01, 0x0016, 0x0011}, /* R 00 */ - {0x01, 0x0016, 0x0012}, /* G 00 */ - {0x01, 0x0016, 0x0013}, /* B 00 */ - {0x01, 0x000a, 0x0003}, - {0x02, 0xc002, 0x0001}, - {0x02, 0x0007, 0x0005}, - {} -}; - -static int reg_write(struct usb_device *dev, - __u16 req, __u16 index, __u16 value) -{ - int ret; - - ret = usb_control_msg(dev, - usb_sndctrlpipe(dev, 0), - req, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, NULL, 0, 500); - PDEBUG(D_USBO, "reg write: 0x%02x 0x%02x 0x%02x", - req, index, value); - if (ret < 0) - pr_err("reg write: error %d\n", ret); - return ret; -} - - -static int write_vector(struct gspca_dev *gspca_dev, - const __u16 data[][3]) -{ - struct usb_device *dev = gspca_dev->dev; - int ret, i = 0; - - while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) { - ret = reg_write(dev, data[i][0], data[i][2], data[i][1]); - if (ret < 0) { - PDEBUG(D_ERR, - "Reg write failed for 0x%02x,0x%02x,0x%02x", - data[i][0], data[i][1], data[i][2]); - return ret; - } - i++; - } - return 0; -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 val) -{ - reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x12, val); -} - -static void setcontrast(struct gspca_dev *gspca_dev, s32 val) -{ - reg_write(gspca_dev->dev, 0x00, 0x00, - (val >> 8) & 0xff); - reg_write(gspca_dev->dev, 0x00, 0x01, - val & 0xff); -} - -static void setcolors(struct gspca_dev *gspca_dev, s32 val) -{ - reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x0c, val); -} - -static void setblue_balance(struct gspca_dev *gspca_dev, s32 val) -{ - reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x11, val); -} - -static void setred_balance(struct gspca_dev *gspca_dev, s32 val) -{ - reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x13, val); -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - - cam = &gspca_dev->cam; - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - sd->subtype = id->driver_info; - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->subtype) { - case Arowana300KCMOSCamera: - case SmileIntlCamera: - /* Arowana 300k CMOS Camera data */ - if (write_vector(gspca_dev, spca501c_arowana_init_data)) - goto error; - break; - case MystFromOriUnknownCamera: - /* Unknown Ori CMOS Camera data */ - if (write_vector(gspca_dev, spca501c_mysterious_open_data)) - goto error; - break; - default: - /* generic spca501 init data */ - if (write_vector(gspca_dev, spca501_init_data)) - goto error; - break; - } - PDEBUG(D_STREAM, "Initializing SPCA501 finished"); - return 0; -error: - return -EINVAL; -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; - int mode; - - switch (sd->subtype) { - case ThreeComHomeConnectLite: - /* Special handling for 3com data */ - write_vector(gspca_dev, spca501_3com_open_data); - break; - case Arowana300KCMOSCamera: - case SmileIntlCamera: - /* Arowana 300k CMOS Camera data */ - write_vector(gspca_dev, spca501c_arowana_open_data); - break; - case MystFromOriUnknownCamera: - /* Unknown CMOS Camera data */ - write_vector(gspca_dev, spca501c_mysterious_init_data); - break; - default: - /* Generic 501 open data */ - write_vector(gspca_dev, spca501_open_data); - } - - /* memorize the wanted pixel format */ - mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; - - /* Enable ISO packet machine CTRL reg=2, - * index=1 bitmask=0x2 (bit ordinal 1) */ - reg_write(dev, SPCA50X_REG_USB, 0x6, 0x94); - switch (mode) { - case 0: /* 640x480 */ - reg_write(dev, SPCA50X_REG_USB, 0x07, 0x004a); - break; - case 1: /* 320x240 */ - reg_write(dev, SPCA50X_REG_USB, 0x07, 0x104a); - break; - default: -/* case 2: * 160x120 */ - reg_write(dev, SPCA50X_REG_USB, 0x07, 0x204a); - break; - } - reg_write(dev, SPCA501_REG_CTLRL, 0x01, 0x02); - - return 0; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - /* Disable ISO packet - * machine CTRL reg=2, index=1 bitmask=0x0 (bit ordinal 1) */ - reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00); -} - -/* called on streamoff with alt 0 and on disconnect */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - if (!gspca_dev->present) - return; - reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - switch (data[0]) { - case 0: /* start of frame */ - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - data += SPCA501_OFFSET_DATA; - len -= SPCA501_OFFSET_DATA; - gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); - return; - case 0xff: /* drop */ -/* gspca_dev->last_packet_type = DISCARD_PACKET; */ - return; - } - data++; - len--; - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_CONTRAST: - setcontrast(gspca_dev, ctrl->val); - break; - case V4L2_CID_SATURATION: - setcolors(gspca_dev, ctrl->val); - break; - case V4L2_CID_BLUE_BALANCE: - setblue_balance(gspca_dev, ctrl->val); - break; - case V4L2_CID_RED_BALANCE: - setred_balance(gspca_dev, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 5); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 127, 1, 0); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 64725, 1, 64725); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SATURATION, 0, 63, 1, 20); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BLUE_BALANCE, 0, 127, 1, 0); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_RED_BALANCE, 0, 127, 1, 0); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x040a, 0x0002), .driver_info = KodakDVC325}, - {USB_DEVICE(0x0497, 0xc001), .driver_info = SmileIntlCamera}, - {USB_DEVICE(0x0506, 0x00df), .driver_info = ThreeComHomeConnectLite}, - {USB_DEVICE(0x0733, 0x0401), .driver_info = IntelCreateAndShare}, - {USB_DEVICE(0x0733, 0x0402), .driver_info = ViewQuestM318B}, - {USB_DEVICE(0x1776, 0x501c), .driver_info = Arowana300KCMOSCamera}, - {USB_DEVICE(0x0000, 0x0000), .driver_info = MystFromOriUnknownCamera}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c deleted file mode 100644 index bc7d67c3cb04..000000000000 --- a/drivers/media/video/gspca/spca505.c +++ /dev/null @@ -1,807 +0,0 @@ -/* - * SPCA505 chip based cameras initialization data - * - * V4L2 by Jean-Francis Moine <http://moinejf.free.fr> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "spca505" - -#include "gspca.h" - -MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); -MODULE_DESCRIPTION("GSPCA/SPCA505 USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - u8 subtype; -#define IntelPCCameraPro 0 -#define Nxultra 1 -}; - -static const struct v4l2_pix_format vga_mode[] = { - {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 4}, - {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 3}, - {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, - {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; - -#define SPCA50X_OFFSET_DATA 10 - -#define SPCA50X_REG_USB 0x02 /* spca505 501 */ - -#define SPCA50X_USB_CTRL 0x00 /* spca505 */ -#define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */ - -#define SPCA50X_REG_GLOBAL 0x03 /* spca505 */ -#define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */ -#define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */ - -#define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */ -#define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */ -#define SPCA50X_GMISC3_SAA7113RST 0x20 /* Not sure about this one spca505 */ - -/* Image format and compression control */ -#define SPCA50X_REG_COMPRESS 0x04 - -/* - * Data to initialize a SPCA505. Common to the CCD and external modes - */ -static const u8 spca505_init_data[][3] = { - /* bmRequest,value,index */ - {SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3}, - /* Sensor reset */ - {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3}, - {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1}, - /* Block USB reset */ - {SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL, SPCA50X_GLOBAL_MISC0}, - - {0x05, 0x01, 0x10}, - /* Maybe power down some stuff */ - {0x05, 0x0f, 0x11}, - - /* Setup internal CCD ? */ - {0x06, 0x10, 0x08}, - {0x06, 0x00, 0x09}, - {0x06, 0x00, 0x0a}, - {0x06, 0x00, 0x0b}, - {0x06, 0x10, 0x0c}, - {0x06, 0x00, 0x0d}, - {0x06, 0x00, 0x0e}, - {0x06, 0x00, 0x0f}, - {0x06, 0x10, 0x10}, - {0x06, 0x02, 0x11}, - {0x06, 0x00, 0x12}, - {0x06, 0x04, 0x13}, - {0x06, 0x02, 0x14}, - {0x06, 0x8a, 0x51}, - {0x06, 0x40, 0x52}, - {0x06, 0xb6, 0x53}, - {0x06, 0x3d, 0x54}, - {} -}; - -/* - * Data to initialize the camera using the internal CCD - */ -static const u8 spca505_open_data_ccd[][3] = { - /* bmRequest,value,index */ - /* Internal CCD data set */ - {0x03, 0x04, 0x01}, - /* This could be a reset */ - {0x03, 0x00, 0x01}, - - /* Setup compression and image registers. 0x6 and 0x7 seem to be - related to H&V hold, and are resolution mode specific */ - {0x04, 0x10, 0x01}, - /* DIFF(0x50), was (0x10) */ - {0x04, 0x00, 0x04}, - {0x04, 0x00, 0x05}, - {0x04, 0x20, 0x06}, - {0x04, 0x20, 0x07}, - - {0x08, 0x0a, 0x00}, - /* DIFF (0x4a), was (0xa) */ - - {0x05, 0x00, 0x10}, - {0x05, 0x00, 0x11}, - {0x05, 0x00, 0x00}, - /* DIFF not written */ - {0x05, 0x00, 0x01}, - /* DIFF not written */ - {0x05, 0x00, 0x02}, - /* DIFF not written */ - {0x05, 0x00, 0x03}, - /* DIFF not written */ - {0x05, 0x00, 0x04}, - /* DIFF not written */ - {0x05, 0x80, 0x05}, - /* DIFF not written */ - {0x05, 0xe0, 0x06}, - /* DIFF not written */ - {0x05, 0x20, 0x07}, - /* DIFF not written */ - {0x05, 0xa0, 0x08}, - /* DIFF not written */ - {0x05, 0x0, 0x12}, - /* DIFF not written */ - {0x05, 0x02, 0x0f}, - /* DIFF not written */ - {0x05, 0x10, 0x46}, - /* DIFF not written */ - {0x05, 0x8, 0x4a}, - /* DIFF not written */ - - {0x03, 0x08, 0x03}, - /* DIFF (0x3,0x28,0x3) */ - {0x03, 0x08, 0x01}, - {0x03, 0x0c, 0x03}, - /* DIFF not written */ - {0x03, 0x21, 0x00}, - /* DIFF (0x39) */ - -/* Extra block copied from init to hopefully ensure CCD is in a sane state */ - {0x06, 0x10, 0x08}, - {0x06, 0x00, 0x09}, - {0x06, 0x00, 0x0a}, - {0x06, 0x00, 0x0b}, - {0x06, 0x10, 0x0c}, - {0x06, 0x00, 0x0d}, - {0x06, 0x00, 0x0e}, - {0x06, 0x00, 0x0f}, - {0x06, 0x10, 0x10}, - {0x06, 0x02, 0x11}, - {0x06, 0x00, 0x12}, - {0x06, 0x04, 0x13}, - {0x06, 0x02, 0x14}, - {0x06, 0x8a, 0x51}, - {0x06, 0x40, 0x52}, - {0x06, 0xb6, 0x53}, - {0x06, 0x3d, 0x54}, - /* End of extra block */ - - {0x06, 0x3f, 0x1}, - /* Block skipped */ - {0x06, 0x10, 0x02}, - {0x06, 0x64, 0x07}, - {0x06, 0x10, 0x08}, - {0x06, 0x00, 0x09}, - {0x06, 0x00, 0x0a}, - {0x06, 0x00, 0x0b}, - {0x06, 0x10, 0x0c}, - {0x06, 0x00, 0x0d}, - {0x06, 0x00, 0x0e}, - {0x06, 0x00, 0x0f}, - {0x06, 0x10, 0x10}, - {0x06, 0x02, 0x11}, - {0x06, 0x00, 0x12}, - {0x06, 0x04, 0x13}, - {0x06, 0x02, 0x14}, - {0x06, 0x8a, 0x51}, - {0x06, 0x40, 0x52}, - {0x06, 0xb6, 0x53}, - {0x06, 0x3d, 0x54}, - {0x06, 0x60, 0x57}, - {0x06, 0x20, 0x58}, - {0x06, 0x15, 0x59}, - {0x06, 0x05, 0x5a}, - - {0x05, 0x01, 0xc0}, - {0x05, 0x10, 0xcb}, - {0x05, 0x80, 0xc1}, - /* */ - {0x05, 0x0, 0xc2}, - /* 4 was 0 */ - {0x05, 0x00, 0xca}, - {0x05, 0x80, 0xc1}, - /* */ - {0x05, 0x04, 0xc2}, - {0x05, 0x00, 0xca}, - {0x05, 0x0, 0xc1}, - /* */ - {0x05, 0x00, 0xc2}, - {0x05, 0x00, 0xca}, - {0x05, 0x40, 0xc1}, - /* */ - {0x05, 0x17, 0xc2}, - {0x05, 0x00, 0xca}, - {0x05, 0x80, 0xc1}, - /* */ - {0x05, 0x06, 0xc2}, - {0x05, 0x00, 0xca}, - {0x05, 0x80, 0xc1}, - /* */ - {0x05, 0x04, 0xc2}, - {0x05, 0x00, 0xca}, - - {0x03, 0x4c, 0x3}, - {0x03, 0x18, 0x1}, - - {0x06, 0x70, 0x51}, - {0x06, 0xbe, 0x53}, - {0x06, 0x71, 0x57}, - {0x06, 0x20, 0x58}, - {0x06, 0x05, 0x59}, - {0x06, 0x15, 0x5a}, - - {0x04, 0x00, 0x08}, - /* Compress = OFF (0x1 to turn on) */ - {0x04, 0x12, 0x09}, - {0x04, 0x21, 0x0a}, - {0x04, 0x10, 0x0b}, - {0x04, 0x21, 0x0c}, - {0x04, 0x05, 0x00}, - /* was 5 (Image Type ? ) */ - {0x04, 0x00, 0x01}, - - {0x06, 0x3f, 0x01}, - - {0x04, 0x00, 0x04}, - {0x04, 0x00, 0x05}, - {0x04, 0x40, 0x06}, - {0x04, 0x40, 0x07}, - - {0x06, 0x1c, 0x17}, - {0x06, 0xe2, 0x19}, - {0x06, 0x1c, 0x1b}, - {0x06, 0xe2, 0x1d}, - {0x06, 0xaa, 0x1f}, - {0x06, 0x70, 0x20}, - - {0x05, 0x01, 0x10}, - {0x05, 0x00, 0x11}, - {0x05, 0x01, 0x00}, - {0x05, 0x05, 0x01}, - {0x05, 0x00, 0xc1}, - /* */ - {0x05, 0x00, 0xc2}, - {0x05, 0x00, 0xca}, - - {0x06, 0x70, 0x51}, - {0x06, 0xbe, 0x53}, - {} -}; - -/* - * Made by Tomasz Zablocki (skalamandra@poczta.onet.pl) - * SPCA505b chip based cameras initialization data - */ -/* jfm */ -#define initial_brightness 0x7f /* 0x0(white)-0xff(black) */ -/* #define initial_brightness 0x0 //0x0(white)-0xff(black) */ -/* - * Data to initialize a SPCA505. Common to the CCD and external modes - */ -static const u8 spca505b_init_data[][3] = { -/* start */ - {0x02, 0x00, 0x00}, /* init */ - {0x02, 0x00, 0x01}, - {0x02, 0x00, 0x02}, - {0x02, 0x00, 0x03}, - {0x02, 0x00, 0x04}, - {0x02, 0x00, 0x05}, - {0x02, 0x00, 0x06}, - {0x02, 0x00, 0x07}, - {0x02, 0x00, 0x08}, - {0x02, 0x00, 0x09}, - {0x03, 0x00, 0x00}, - {0x03, 0x00, 0x01}, - {0x03, 0x00, 0x02}, - {0x03, 0x00, 0x03}, - {0x03, 0x00, 0x04}, - {0x03, 0x00, 0x05}, - {0x03, 0x00, 0x06}, - {0x04, 0x00, 0x00}, - {0x04, 0x00, 0x02}, - {0x04, 0x00, 0x04}, - {0x04, 0x00, 0x05}, - {0x04, 0x00, 0x06}, - {0x04, 0x00, 0x07}, - {0x04, 0x00, 0x08}, - {0x04, 0x00, 0x09}, - {0x04, 0x00, 0x0a}, - {0x04, 0x00, 0x0b}, - {0x04, 0x00, 0x0c}, - {0x07, 0x00, 0x00}, - {0x07, 0x00, 0x03}, - {0x08, 0x00, 0x00}, - {0x08, 0x00, 0x01}, - {0x08, 0x00, 0x02}, - {0x06, 0x18, 0x08}, - {0x06, 0xfc, 0x09}, - {0x06, 0xfc, 0x0a}, - {0x06, 0xfc, 0x0b}, - {0x06, 0x18, 0x0c}, - {0x06, 0xfc, 0x0d}, - {0x06, 0xfc, 0x0e}, - {0x06, 0xfc, 0x0f}, - {0x06, 0x18, 0x10}, - {0x06, 0xfe, 0x12}, - {0x06, 0x00, 0x11}, - {0x06, 0x00, 0x14}, - {0x06, 0x00, 0x13}, - {0x06, 0x28, 0x51}, - {0x06, 0xff, 0x53}, - {0x02, 0x00, 0x08}, - - {0x03, 0x00, 0x03}, - {0x03, 0x10, 0x03}, - {} -}; - -/* - * Data to initialize the camera using the internal CCD - */ -static const u8 spca505b_open_data_ccd[][3] = { - -/* {0x02,0x00,0x00}, */ - {0x03, 0x04, 0x01}, /* rst */ - {0x03, 0x00, 0x01}, - {0x03, 0x00, 0x00}, - {0x03, 0x21, 0x00}, - {0x03, 0x00, 0x04}, - {0x03, 0x00, 0x03}, - {0x03, 0x18, 0x03}, - {0x03, 0x08, 0x01}, - {0x03, 0x1c, 0x03}, - {0x03, 0x5c, 0x03}, - {0x03, 0x5c, 0x03}, - {0x03, 0x18, 0x01}, - -/* same as 505 */ - {0x04, 0x10, 0x01}, - {0x04, 0x00, 0x04}, - {0x04, 0x00, 0x05}, - {0x04, 0x20, 0x06}, - {0x04, 0x20, 0x07}, - - {0x08, 0x0a, 0x00}, - - {0x05, 0x00, 0x10}, - {0x05, 0x00, 0x11}, - {0x05, 0x00, 0x12}, - {0x05, 0x6f, 0x00}, - {0x05, initial_brightness >> 6, 0x00}, - {0x05, (initial_brightness << 2) & 0xff, 0x01}, - {0x05, 0x00, 0x02}, - {0x05, 0x01, 0x03}, - {0x05, 0x00, 0x04}, - {0x05, 0x03, 0x05}, - {0x05, 0xe0, 0x06}, - {0x05, 0x20, 0x07}, - {0x05, 0xa0, 0x08}, - {0x05, 0x00, 0x12}, - {0x05, 0x02, 0x0f}, - {0x05, 0x80, 0x14}, /* max exposure off (0=on) */ - {0x05, 0x01, 0xb0}, - {0x05, 0x01, 0xbf}, - {0x03, 0x02, 0x06}, - {0x05, 0x10, 0x46}, - {0x05, 0x08, 0x4a}, - - {0x06, 0x00, 0x01}, - {0x06, 0x10, 0x02}, - {0x06, 0x64, 0x07}, - {0x06, 0x18, 0x08}, - {0x06, 0xfc, 0x09}, - {0x06, 0xfc, 0x0a}, - {0x06, 0xfc, 0x0b}, - {0x04, 0x00, 0x01}, - {0x06, 0x18, 0x0c}, - {0x06, 0xfc, 0x0d}, - {0x06, 0xfc, 0x0e}, - {0x06, 0xfc, 0x0f}, - {0x06, 0x11, 0x10}, /* contrast */ - {0x06, 0x00, 0x11}, - {0x06, 0xfe, 0x12}, - {0x06, 0x00, 0x13}, - {0x06, 0x00, 0x14}, - {0x06, 0x9d, 0x51}, - {0x06, 0x40, 0x52}, - {0x06, 0x7c, 0x53}, - {0x06, 0x40, 0x54}, - {0x06, 0x02, 0x57}, - {0x06, 0x03, 0x58}, - {0x06, 0x15, 0x59}, - {0x06, 0x05, 0x5a}, - {0x06, 0x03, 0x56}, - {0x06, 0x02, 0x3f}, - {0x06, 0x00, 0x40}, - {0x06, 0x39, 0x41}, - {0x06, 0x69, 0x42}, - {0x06, 0x87, 0x43}, - {0x06, 0x9e, 0x44}, - {0x06, 0xb1, 0x45}, - {0x06, 0xbf, 0x46}, - {0x06, 0xcc, 0x47}, - {0x06, 0xd5, 0x48}, - {0x06, 0xdd, 0x49}, - {0x06, 0xe3, 0x4a}, - {0x06, 0xe8, 0x4b}, - {0x06, 0xed, 0x4c}, - {0x06, 0xf2, 0x4d}, - {0x06, 0xf7, 0x4e}, - {0x06, 0xfc, 0x4f}, - {0x06, 0xff, 0x50}, - - {0x05, 0x01, 0xc0}, - {0x05, 0x10, 0xcb}, - {0x05, 0x40, 0xc1}, - {0x05, 0x04, 0xc2}, - {0x05, 0x00, 0xca}, - {0x05, 0x40, 0xc1}, - {0x05, 0x09, 0xc2}, - {0x05, 0x00, 0xca}, - {0x05, 0xc0, 0xc1}, - {0x05, 0x09, 0xc2}, - {0x05, 0x00, 0xca}, - {0x05, 0x40, 0xc1}, - {0x05, 0x59, 0xc2}, - {0x05, 0x00, 0xca}, - {0x04, 0x00, 0x01}, - {0x05, 0x80, 0xc1}, - {0x05, 0xec, 0xc2}, - {0x05, 0x0, 0xca}, - - {0x06, 0x02, 0x57}, - {0x06, 0x01, 0x58}, - {0x06, 0x15, 0x59}, - {0x06, 0x0a, 0x5a}, - {0x06, 0x01, 0x57}, - {0x06, 0x8a, 0x03}, - {0x06, 0x0a, 0x6c}, - {0x06, 0x30, 0x01}, - {0x06, 0x20, 0x02}, - {0x06, 0x00, 0x03}, - - {0x05, 0x8c, 0x25}, - - {0x06, 0x4d, 0x51}, /* maybe saturation (4d) */ - {0x06, 0x84, 0x53}, /* making green (84) */ - {0x06, 0x00, 0x57}, /* sharpness (1) */ - {0x06, 0x18, 0x08}, - {0x06, 0xfc, 0x09}, - {0x06, 0xfc, 0x0a}, - {0x06, 0xfc, 0x0b}, - {0x06, 0x18, 0x0c}, /* maybe hue (18) */ - {0x06, 0xfc, 0x0d}, - {0x06, 0xfc, 0x0e}, - {0x06, 0xfc, 0x0f}, - {0x06, 0x18, 0x10}, /* maybe contrast (18) */ - - {0x05, 0x01, 0x02}, - - {0x04, 0x00, 0x08}, /* compression */ - {0x04, 0x12, 0x09}, - {0x04, 0x21, 0x0a}, - {0x04, 0x10, 0x0b}, - {0x04, 0x21, 0x0c}, - {0x04, 0x1d, 0x00}, /* imagetype (1d) */ - {0x04, 0x41, 0x01}, /* hardware snapcontrol */ - - {0x04, 0x00, 0x04}, - {0x04, 0x00, 0x05}, - {0x04, 0x10, 0x06}, - {0x04, 0x10, 0x07}, - {0x04, 0x40, 0x06}, - {0x04, 0x40, 0x07}, - {0x04, 0x00, 0x04}, - {0x04, 0x00, 0x05}, - - {0x06, 0x1c, 0x17}, - {0x06, 0xe2, 0x19}, - {0x06, 0x1c, 0x1b}, - {0x06, 0xe2, 0x1d}, - {0x06, 0x5f, 0x1f}, - {0x06, 0x32, 0x20}, - - {0x05, initial_brightness >> 6, 0x00}, - {0x05, (initial_brightness << 2) & 0xff, 0x01}, - {0x05, 0x06, 0xc1}, - {0x05, 0x58, 0xc2}, - {0x05, 0x00, 0xca}, - {0x05, 0x00, 0x11}, - {} -}; - -static int reg_write(struct usb_device *dev, - u16 req, u16 index, u16 value) -{ - int ret; - - ret = usb_control_msg(dev, - usb_sndctrlpipe(dev, 0), - req, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, NULL, 0, 500); - PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d", - req, index, value, ret); - if (ret < 0) - pr_err("reg write: error %d\n", ret); - return ret; -} - -/* returns: negative is error, pos or zero is data */ -static int reg_read(struct gspca_dev *gspca_dev, - u16 req, /* bRequest */ - u16 index) /* wIndex */ -{ - int ret; - - ret = usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, /* value */ - index, - gspca_dev->usb_buf, 2, - 500); /* timeout */ - if (ret < 0) - return ret; - return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]; -} - -static int write_vector(struct gspca_dev *gspca_dev, - const u8 data[][3]) -{ - struct usb_device *dev = gspca_dev->dev; - int ret, i = 0; - - while (data[i][0] != 0) { - ret = reg_write(dev, data[i][0], data[i][2], data[i][1]); - if (ret < 0) - return ret; - i++; - } - return 0; -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - - cam = &gspca_dev->cam; - cam->cam_mode = vga_mode; - sd->subtype = id->driver_info; - if (sd->subtype != IntelPCCameraPro) - cam->nmodes = ARRAY_SIZE(vga_mode); - else /* no 640x480 for IntelPCCameraPro */ - cam->nmodes = ARRAY_SIZE(vga_mode) - 1; - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (write_vector(gspca_dev, - sd->subtype == Nxultra - ? spca505b_init_data - : spca505_init_data)) - return -EIO; - return 0; -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness) -{ - reg_write(gspca_dev->dev, 0x05, 0x00, (255 - brightness) >> 6); - reg_write(gspca_dev->dev, 0x05, 0x01, (255 - brightness) << 2); -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; - int ret, mode; - static u8 mode_tb[][3] = { - /* r00 r06 r07 */ - {0x00, 0x10, 0x10}, /* 640x480 */ - {0x01, 0x1a, 0x1a}, /* 352x288 */ - {0x02, 0x1c, 0x1d}, /* 320x240 */ - {0x04, 0x34, 0x34}, /* 176x144 */ - {0x05, 0x40, 0x40} /* 160x120 */ - }; - - if (sd->subtype == Nxultra) - write_vector(gspca_dev, spca505b_open_data_ccd); - else - write_vector(gspca_dev, spca505_open_data_ccd); - ret = reg_read(gspca_dev, 0x06, 0x16); - - if (ret < 0) { - PDEBUG(D_ERR|D_CONF, - "register read failed err: %d", - ret); - return ret; - } - if (ret != 0x0101) { - pr_err("After vector read returns 0x%04x should be 0x0101\n", - ret); - } - - ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a); - if (ret < 0) - return ret; - reg_write(gspca_dev->dev, 0x05, 0xc2, 0x12); - - /* necessary because without it we can see stream - * only once after loading module */ - /* stopping usb registers Tomasz change */ - reg_write(dev, 0x02, 0x00, 0x00); - - mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; - reg_write(dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]); - reg_write(dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]); - reg_write(dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]); - - return reg_write(dev, SPCA50X_REG_USB, - SPCA50X_USB_CTRL, - SPCA50X_CUSB_ENABLE); -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - /* Disable ISO packet machine */ - reg_write(gspca_dev->dev, 0x02, 0x00, 0x00); -} - -/* called on streamoff with alt 0 and on disconnect */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - if (!gspca_dev->present) - return; - - /* This maybe reset or power control */ - reg_write(gspca_dev->dev, 0x03, 0x03, 0x20); - reg_write(gspca_dev->dev, 0x03, 0x01, 0x00); - reg_write(gspca_dev->dev, 0x03, 0x00, 0x01); - reg_write(gspca_dev->dev, 0x05, 0x10, 0x01); - reg_write(gspca_dev->dev, 0x05, 0x11, 0x0f); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - switch (data[0]) { - case 0: /* start of frame */ - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - data += SPCA50X_OFFSET_DATA; - len -= SPCA50X_OFFSET_DATA; - gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); - break; - case 0xff: /* drop */ - break; - default: - data += 1; - len -= 1; - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); - break; - } -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 5); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init_controls = sd_init_controls, - .init = sd_init, - .start = sd_start, - .stopN = sd_stopN, - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x041e, 0x401d), .driver_info = Nxultra}, - {USB_DEVICE(0x0733, 0x0430), .driver_info = IntelPCCameraPro}, -/*fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */ - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c deleted file mode 100644 index 969bb5a4cd93..000000000000 --- a/drivers/media/video/gspca/spca506.c +++ /dev/null @@ -1,612 +0,0 @@ -/* - * SPCA506 chip based cameras function - * M Xhaard 15/04/2004 based on different work Mark Taylor and others - * and my own snoopy file on a pv-321c donate by a german compagny - * "Firma Frank Gmbh" from Saarbruecken - * - * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define MODULE_NAME "spca506" - -#include "gspca.h" - -MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); -MODULE_DESCRIPTION("GSPCA/SPCA506 USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - char norme; - char channel; -}; - -static const struct v4l2_pix_format vga_mode[] = { - {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 5}, - {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 4}, - {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, - {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; - -#define SPCA50X_OFFSET_DATA 10 - -#define SAA7113_bright 0x0a /* defaults 0x80 */ -#define SAA7113_contrast 0x0b /* defaults 0x47 */ -#define SAA7113_saturation 0x0c /* defaults 0x40 */ -#define SAA7113_hue 0x0d /* defaults 0x00 */ -#define SAA7113_I2C_BASE_WRITE 0x4a - -/* read 'len' bytes to gspca_dev->usb_buf */ -static void reg_r(struct gspca_dev *gspca_dev, - __u16 req, - __u16 index, - __u16 length) -{ - usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, /* value */ - index, gspca_dev->usb_buf, length, - 500); -} - -static void reg_w(struct usb_device *dev, - __u16 req, - __u16 value, - __u16 index) -{ - usb_control_msg(dev, - usb_sndctrlpipe(dev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, - NULL, 0, 500); -} - -static void spca506_Initi2c(struct gspca_dev *gspca_dev) -{ - reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004); -} - -static void spca506_WriteI2c(struct gspca_dev *gspca_dev, __u16 valeur, - __u16 reg) -{ - int retry = 60; - - reg_w(gspca_dev->dev, 0x07, reg, 0x0001); - reg_w(gspca_dev->dev, 0x07, valeur, 0x0000); - while (retry--) { - reg_r(gspca_dev, 0x07, 0x0003, 2); - if ((gspca_dev->usb_buf[0] | gspca_dev->usb_buf[1]) == 0x00) - break; - } -} - -static void spca506_SetNormeInput(struct gspca_dev *gspca_dev, - __u16 norme, - __u16 channel) -{ - struct sd *sd = (struct sd *) gspca_dev; -/* fixme: check if channel == 0..3 and 6..9 (8 values) */ - __u8 setbit0 = 0x00; - __u8 setbit1 = 0x00; - __u8 videomask = 0x00; - - PDEBUG(D_STREAM, "** Open Set Norme **"); - spca506_Initi2c(gspca_dev); - /* NTSC bit0 -> 1(525 l) PAL SECAM bit0 -> 0 (625 l) */ - /* Composite channel bit1 -> 1 S-video bit 1 -> 0 */ - /* and exclude SAA7113 reserved channel set default 0 otherwise */ - if (norme & V4L2_STD_NTSC) - setbit0 = 0x01; - if (channel == 4 || channel == 5 || channel > 9) - channel = 0; - if (channel < 4) - setbit1 = 0x02; - videomask = (0x48 | setbit0 | setbit1); - reg_w(gspca_dev->dev, 0x08, videomask, 0x0000); - spca506_WriteI2c(gspca_dev, (0xc0 | (channel & 0x0F)), 0x02); - - if (norme & V4L2_STD_NTSC) - spca506_WriteI2c(gspca_dev, 0x33, 0x0e); - /* Chrominance Control NTSC N */ - else if (norme & V4L2_STD_SECAM) - spca506_WriteI2c(gspca_dev, 0x53, 0x0e); - /* Chrominance Control SECAM */ - else - spca506_WriteI2c(gspca_dev, 0x03, 0x0e); - /* Chrominance Control PAL BGHIV */ - - sd->norme = norme; - sd->channel = channel; - PDEBUG(D_STREAM, "Set Video Byte to 0x%2x", videomask); - PDEBUG(D_STREAM, "Set Norme: %08x Channel %d", norme, channel); -} - -static void spca506_GetNormeInput(struct gspca_dev *gspca_dev, - __u16 *norme, __u16 *channel) -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* Read the register is not so good value change so - we use your own copy in spca50x struct */ - *norme = sd->norme; - *channel = sd->channel; - PDEBUG(D_STREAM, "Get Norme: %d Channel %d", *norme, *channel); -} - -static void spca506_Setsize(struct gspca_dev *gspca_dev, __u16 code, - __u16 xmult, __u16 ymult) -{ - struct usb_device *dev = gspca_dev->dev; - - PDEBUG(D_STREAM, "** SetSize **"); - reg_w(dev, 0x04, (0x18 | (code & 0x07)), 0x0000); - /* Soft snap 0x40 Hard 0x41 */ - reg_w(dev, 0x04, 0x41, 0x0001); - reg_w(dev, 0x04, 0x00, 0x0002); - /* reserved */ - reg_w(dev, 0x04, 0x00, 0x0003); - - /* reserved */ - reg_w(dev, 0x04, 0x00, 0x0004); - /* reserved */ - reg_w(dev, 0x04, 0x01, 0x0005); - /* reserced */ - reg_w(dev, 0x04, xmult, 0x0006); - /* reserved */ - reg_w(dev, 0x04, ymult, 0x0007); - /* compression 1 */ - reg_w(dev, 0x04, 0x00, 0x0008); - /* T=64 -> 2 */ - reg_w(dev, 0x04, 0x00, 0x0009); - /* threshold2D */ - reg_w(dev, 0x04, 0x21, 0x000a); - /* quantization */ - reg_w(dev, 0x04, 0x00, 0x000b); -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct cam *cam; - - cam = &gspca_dev->cam; - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct usb_device *dev = gspca_dev->dev; - - reg_w(dev, 0x03, 0x00, 0x0004); - reg_w(dev, 0x03, 0xFF, 0x0003); - reg_w(dev, 0x03, 0x00, 0x0000); - reg_w(dev, 0x03, 0x1c, 0x0001); - reg_w(dev, 0x03, 0x18, 0x0001); - /* Init on PAL and composite input0 */ - spca506_SetNormeInput(gspca_dev, 0, 0); - reg_w(dev, 0x03, 0x1c, 0x0001); - reg_w(dev, 0x03, 0x18, 0x0001); - reg_w(dev, 0x05, 0x00, 0x0000); - reg_w(dev, 0x05, 0xef, 0x0001); - reg_w(dev, 0x05, 0x00, 0x00c1); - reg_w(dev, 0x05, 0x00, 0x00c2); - reg_w(dev, 0x06, 0x18, 0x0002); - reg_w(dev, 0x06, 0xf5, 0x0011); - reg_w(dev, 0x06, 0x02, 0x0012); - reg_w(dev, 0x06, 0xfb, 0x0013); - reg_w(dev, 0x06, 0x00, 0x0014); - reg_w(dev, 0x06, 0xa4, 0x0051); - reg_w(dev, 0x06, 0x40, 0x0052); - reg_w(dev, 0x06, 0x71, 0x0053); - reg_w(dev, 0x06, 0x40, 0x0054); - /************************************************/ - reg_w(dev, 0x03, 0x00, 0x0004); - reg_w(dev, 0x03, 0x00, 0x0003); - reg_w(dev, 0x03, 0x00, 0x0004); - reg_w(dev, 0x03, 0xFF, 0x0003); - reg_w(dev, 0x02, 0x00, 0x0000); - reg_w(dev, 0x03, 0x60, 0x0000); - reg_w(dev, 0x03, 0x18, 0x0001); - /* for a better reading mx :) */ - /*sdca506_WriteI2c(value,register) */ - spca506_Initi2c(gspca_dev); - spca506_WriteI2c(gspca_dev, 0x08, 0x01); - spca506_WriteI2c(gspca_dev, 0xc0, 0x02); - /* input composite video */ - spca506_WriteI2c(gspca_dev, 0x33, 0x03); - spca506_WriteI2c(gspca_dev, 0x00, 0x04); - spca506_WriteI2c(gspca_dev, 0x00, 0x05); - spca506_WriteI2c(gspca_dev, 0x0d, 0x06); - spca506_WriteI2c(gspca_dev, 0xf0, 0x07); - spca506_WriteI2c(gspca_dev, 0x98, 0x08); - spca506_WriteI2c(gspca_dev, 0x03, 0x09); - spca506_WriteI2c(gspca_dev, 0x80, 0x0a); - spca506_WriteI2c(gspca_dev, 0x47, 0x0b); - spca506_WriteI2c(gspca_dev, 0x48, 0x0c); - spca506_WriteI2c(gspca_dev, 0x00, 0x0d); - spca506_WriteI2c(gspca_dev, 0x03, 0x0e); /* Chroma Pal adjust */ - spca506_WriteI2c(gspca_dev, 0x2a, 0x0f); - spca506_WriteI2c(gspca_dev, 0x00, 0x10); - spca506_WriteI2c(gspca_dev, 0x0c, 0x11); - spca506_WriteI2c(gspca_dev, 0xb8, 0x12); - spca506_WriteI2c(gspca_dev, 0x01, 0x13); - spca506_WriteI2c(gspca_dev, 0x00, 0x14); - spca506_WriteI2c(gspca_dev, 0x00, 0x15); - spca506_WriteI2c(gspca_dev, 0x00, 0x16); - spca506_WriteI2c(gspca_dev, 0x00, 0x17); - spca506_WriteI2c(gspca_dev, 0x00, 0x18); - spca506_WriteI2c(gspca_dev, 0x00, 0x19); - spca506_WriteI2c(gspca_dev, 0x00, 0x1a); - spca506_WriteI2c(gspca_dev, 0x00, 0x1b); - spca506_WriteI2c(gspca_dev, 0x00, 0x1c); - spca506_WriteI2c(gspca_dev, 0x00, 0x1d); - spca506_WriteI2c(gspca_dev, 0x00, 0x1e); - spca506_WriteI2c(gspca_dev, 0xa1, 0x1f); - spca506_WriteI2c(gspca_dev, 0x02, 0x40); - spca506_WriteI2c(gspca_dev, 0xff, 0x41); - spca506_WriteI2c(gspca_dev, 0xff, 0x42); - spca506_WriteI2c(gspca_dev, 0xff, 0x43); - spca506_WriteI2c(gspca_dev, 0xff, 0x44); - spca506_WriteI2c(gspca_dev, 0xff, 0x45); - spca506_WriteI2c(gspca_dev, 0xff, 0x46); - spca506_WriteI2c(gspca_dev, 0xff, 0x47); - spca506_WriteI2c(gspca_dev, 0xff, 0x48); - spca506_WriteI2c(gspca_dev, 0xff, 0x49); - spca506_WriteI2c(gspca_dev, 0xff, 0x4a); - spca506_WriteI2c(gspca_dev, 0xff, 0x4b); - spca506_WriteI2c(gspca_dev, 0xff, 0x4c); - spca506_WriteI2c(gspca_dev, 0xff, 0x4d); - spca506_WriteI2c(gspca_dev, 0xff, 0x4e); - spca506_WriteI2c(gspca_dev, 0xff, 0x4f); - spca506_WriteI2c(gspca_dev, 0xff, 0x50); - spca506_WriteI2c(gspca_dev, 0xff, 0x51); - spca506_WriteI2c(gspca_dev, 0xff, 0x52); - spca506_WriteI2c(gspca_dev, 0xff, 0x53); - spca506_WriteI2c(gspca_dev, 0xff, 0x54); - spca506_WriteI2c(gspca_dev, 0xff, 0x55); - spca506_WriteI2c(gspca_dev, 0xff, 0x56); - spca506_WriteI2c(gspca_dev, 0xff, 0x57); - spca506_WriteI2c(gspca_dev, 0x00, 0x58); - spca506_WriteI2c(gspca_dev, 0x54, 0x59); - spca506_WriteI2c(gspca_dev, 0x07, 0x5a); - spca506_WriteI2c(gspca_dev, 0x83, 0x5b); - spca506_WriteI2c(gspca_dev, 0x00, 0x5c); - spca506_WriteI2c(gspca_dev, 0x00, 0x5d); - spca506_WriteI2c(gspca_dev, 0x00, 0x5e); - spca506_WriteI2c(gspca_dev, 0x00, 0x5f); - spca506_WriteI2c(gspca_dev, 0x00, 0x60); - spca506_WriteI2c(gspca_dev, 0x05, 0x61); - spca506_WriteI2c(gspca_dev, 0x9f, 0x62); - PDEBUG(D_STREAM, "** Close Init *"); - return 0; -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct usb_device *dev = gspca_dev->dev; - __u16 norme; - __u16 channel; - - /**************************************/ - reg_w(dev, 0x03, 0x00, 0x0004); - reg_w(dev, 0x03, 0x00, 0x0003); - reg_w(dev, 0x03, 0x00, 0x0004); - reg_w(dev, 0x03, 0xFF, 0x0003); - reg_w(dev, 0x02, 0x00, 0x0000); - reg_w(dev, 0x03, 0x60, 0x0000); - reg_w(dev, 0x03, 0x18, 0x0001); - - /*sdca506_WriteI2c(value,register) */ - spca506_Initi2c(gspca_dev); - spca506_WriteI2c(gspca_dev, 0x08, 0x01); /* Increment Delay */ -/* spca506_WriteI2c(gspca_dev, 0xc0, 0x02); * Analog Input Control 1 */ - spca506_WriteI2c(gspca_dev, 0x33, 0x03); - /* Analog Input Control 2 */ - spca506_WriteI2c(gspca_dev, 0x00, 0x04); - /* Analog Input Control 3 */ - spca506_WriteI2c(gspca_dev, 0x00, 0x05); - /* Analog Input Control 4 */ - spca506_WriteI2c(gspca_dev, 0x0d, 0x06); - /* Horizontal Sync Start 0xe9-0x0d */ - spca506_WriteI2c(gspca_dev, 0xf0, 0x07); - /* Horizontal Sync Stop 0x0d-0xf0 */ - - spca506_WriteI2c(gspca_dev, 0x98, 0x08); /* Sync Control */ -/* Defaults value */ - spca506_WriteI2c(gspca_dev, 0x03, 0x09); /* Luminance Control */ - spca506_WriteI2c(gspca_dev, 0x80, 0x0a); - /* Luminance Brightness */ - spca506_WriteI2c(gspca_dev, 0x47, 0x0b); /* Luminance Contrast */ - spca506_WriteI2c(gspca_dev, 0x48, 0x0c); - /* Chrominance Saturation */ - spca506_WriteI2c(gspca_dev, 0x00, 0x0d); - /* Chrominance Hue Control */ - spca506_WriteI2c(gspca_dev, 0x2a, 0x0f); - /* Chrominance Gain Control */ - /**************************************/ - spca506_WriteI2c(gspca_dev, 0x00, 0x10); - /* Format/Delay Control */ - spca506_WriteI2c(gspca_dev, 0x0c, 0x11); /* Output Control 1 */ - spca506_WriteI2c(gspca_dev, 0xb8, 0x12); /* Output Control 2 */ - spca506_WriteI2c(gspca_dev, 0x01, 0x13); /* Output Control 3 */ - spca506_WriteI2c(gspca_dev, 0x00, 0x14); /* reserved */ - spca506_WriteI2c(gspca_dev, 0x00, 0x15); /* VGATE START */ - spca506_WriteI2c(gspca_dev, 0x00, 0x16); /* VGATE STOP */ - spca506_WriteI2c(gspca_dev, 0x00, 0x17); /* VGATE Control (MSB) */ - spca506_WriteI2c(gspca_dev, 0x00, 0x18); - spca506_WriteI2c(gspca_dev, 0x00, 0x19); - spca506_WriteI2c(gspca_dev, 0x00, 0x1a); - spca506_WriteI2c(gspca_dev, 0x00, 0x1b); - spca506_WriteI2c(gspca_dev, 0x00, 0x1c); - spca506_WriteI2c(gspca_dev, 0x00, 0x1d); - spca506_WriteI2c(gspca_dev, 0x00, 0x1e); - spca506_WriteI2c(gspca_dev, 0xa1, 0x1f); - spca506_WriteI2c(gspca_dev, 0x02, 0x40); - spca506_WriteI2c(gspca_dev, 0xff, 0x41); - spca506_WriteI2c(gspca_dev, 0xff, 0x42); - spca506_WriteI2c(gspca_dev, 0xff, 0x43); - spca506_WriteI2c(gspca_dev, 0xff, 0x44); - spca506_WriteI2c(gspca_dev, 0xff, 0x45); - spca506_WriteI2c(gspca_dev, 0xff, 0x46); - spca506_WriteI2c(gspca_dev, 0xff, 0x47); - spca506_WriteI2c(gspca_dev, 0xff, 0x48); - spca506_WriteI2c(gspca_dev, 0xff, 0x49); - spca506_WriteI2c(gspca_dev, 0xff, 0x4a); - spca506_WriteI2c(gspca_dev, 0xff, 0x4b); - spca506_WriteI2c(gspca_dev, 0xff, 0x4c); - spca506_WriteI2c(gspca_dev, 0xff, 0x4d); - spca506_WriteI2c(gspca_dev, 0xff, 0x4e); - spca506_WriteI2c(gspca_dev, 0xff, 0x4f); - spca506_WriteI2c(gspca_dev, 0xff, 0x50); - spca506_WriteI2c(gspca_dev, 0xff, 0x51); - spca506_WriteI2c(gspca_dev, 0xff, 0x52); - spca506_WriteI2c(gspca_dev, 0xff, 0x53); - spca506_WriteI2c(gspca_dev, 0xff, 0x54); - spca506_WriteI2c(gspca_dev, 0xff, 0x55); - spca506_WriteI2c(gspca_dev, 0xff, 0x56); - spca506_WriteI2c(gspca_dev, 0xff, 0x57); - spca506_WriteI2c(gspca_dev, 0x00, 0x58); - spca506_WriteI2c(gspca_dev, 0x54, 0x59); - spca506_WriteI2c(gspca_dev, 0x07, 0x5a); - spca506_WriteI2c(gspca_dev, 0x83, 0x5b); - spca506_WriteI2c(gspca_dev, 0x00, 0x5c); - spca506_WriteI2c(gspca_dev, 0x00, 0x5d); - spca506_WriteI2c(gspca_dev, 0x00, 0x5e); - spca506_WriteI2c(gspca_dev, 0x00, 0x5f); - spca506_WriteI2c(gspca_dev, 0x00, 0x60); - spca506_WriteI2c(gspca_dev, 0x05, 0x61); - spca506_WriteI2c(gspca_dev, 0x9f, 0x62); - /**************************************/ - reg_w(dev, 0x05, 0x00, 0x0003); - reg_w(dev, 0x05, 0x00, 0x0004); - reg_w(dev, 0x03, 0x10, 0x0001); - reg_w(dev, 0x03, 0x78, 0x0000); - switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { - case 0: - spca506_Setsize(gspca_dev, 0, 0x10, 0x10); - break; - case 1: - spca506_Setsize(gspca_dev, 1, 0x1a, 0x1a); - break; - case 2: - spca506_Setsize(gspca_dev, 2, 0x1c, 0x1c); - break; - case 4: - spca506_Setsize(gspca_dev, 4, 0x34, 0x34); - break; - default: -/* case 5: */ - spca506_Setsize(gspca_dev, 5, 0x40, 0x40); - break; - } - - /* compress setting and size */ - /* set i2c luma */ - reg_w(dev, 0x02, 0x01, 0x0000); - reg_w(dev, 0x03, 0x12, 0x0000); - reg_r(gspca_dev, 0x04, 0x0001, 2); - PDEBUG(D_STREAM, "webcam started"); - spca506_GetNormeInput(gspca_dev, &norme, &channel); - spca506_SetNormeInput(gspca_dev, norme, channel); - return 0; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct usb_device *dev = gspca_dev->dev; - - reg_w(dev, 0x02, 0x00, 0x0000); - reg_w(dev, 0x03, 0x00, 0x0004); - reg_w(dev, 0x03, 0x00, 0x0003); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - switch (data[0]) { - case 0: /* start of frame */ - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - data += SPCA50X_OFFSET_DATA; - len -= SPCA50X_OFFSET_DATA; - gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); - break; - case 0xff: /* drop */ -/* gspca_dev->last_packet_type = DISCARD_PACKET; */ - break; - default: - data += 1; - len -= 1; - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); - break; - } -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 val) -{ - spca506_Initi2c(gspca_dev); - spca506_WriteI2c(gspca_dev, val, SAA7113_bright); - spca506_WriteI2c(gspca_dev, 0x01, 0x09); -} - -static void setcontrast(struct gspca_dev *gspca_dev, s32 val) -{ - spca506_Initi2c(gspca_dev); - spca506_WriteI2c(gspca_dev, val, SAA7113_contrast); - spca506_WriteI2c(gspca_dev, 0x01, 0x09); -} - -static void setcolors(struct gspca_dev *gspca_dev, s32 val) -{ - spca506_Initi2c(gspca_dev); - spca506_WriteI2c(gspca_dev, val, SAA7113_saturation); - spca506_WriteI2c(gspca_dev, 0x01, 0x09); -} - -static void sethue(struct gspca_dev *gspca_dev, s32 val) -{ - spca506_Initi2c(gspca_dev); - spca506_WriteI2c(gspca_dev, val, SAA7113_hue); - spca506_WriteI2c(gspca_dev, 0x01, 0x09); -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_CONTRAST: - setcontrast(gspca_dev, ctrl->val); - break; - case V4L2_CID_SATURATION: - setcolors(gspca_dev, ctrl->val); - break; - case V4L2_CID_HUE: - sethue(gspca_dev, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 4); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 255, 1, 0x47); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SATURATION, 0, 255, 1, 0x40); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_HUE, 0, 255, 1, 0); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] __devinitconst = { - {USB_DEVICE(0x06e1, 0xa190)}, -/*fixme: may be IntelPCCameraPro BRIDGE_SPCA505 - {USB_DEVICE(0x0733, 0x0430)}, */ - {USB_DEVICE(0x0734, 0x043b)}, - {USB_DEVICE(0x99fa, 0x8988)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int __devinit sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c deleted file mode 100644 index 1286b4170b88..000000000000 --- a/drivers/media/video/gspca/spca508.c +++ /dev/null @@ -1,1540 +0,0 @@ -/* - * SPCA508 chip based cameras subdriver - * - * Copyright (C) 2009 Jean-Francois Moine <http://moinejf.free.fr> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "spca508" - -#include "gspca.h" - -MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); -MODULE_DESCRIPTION("GSPCA/SPCA508 USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - u8 subtype; -#define CreativeVista 0 -#define HamaUSBSightcam 1 -#define HamaUSBSightcam2 2 -#define IntelEasyPCCamera 3 -#define MicroInnovationIC200 4 -#define ViewQuestVQ110 5 -}; - -static const struct v4l2_pix_format sif_mode[] = { - {160, 120, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 3}, - {176, 144, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, - {320, 240, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {352, 288, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 3 / 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; - -/* Frame packet header offsets for the spca508 */ -#define SPCA508_OFFSET_DATA 37 - -/* - * Initialization data: this is the first set-up data written to the - * device (before the open data). - */ -static const u16 spca508_init_data[][2] = { - {0x0000, 0x870b}, - - {0x0020, 0x8112}, /* Video drop enable, ISO streaming disable */ - {0x0003, 0x8111}, /* Reset compression & memory */ - {0x0000, 0x8110}, /* Disable all outputs */ - /* READ {0x0000, 0x8114} -> 0000: 00 */ - {0x0000, 0x8114}, /* SW GPIO data */ - {0x0008, 0x8110}, /* Enable charge pump output */ - {0x0002, 0x8116}, /* 200 kHz pump clock */ - /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE:) */ - {0x0003, 0x8111}, /* Reset compression & memory */ - {0x0000, 0x8111}, /* Normal mode (not reset) */ - {0x0098, 0x8110}, - /* Enable charge pump output, sync.serial,external 2x clock */ - {0x000d, 0x8114}, /* SW GPIO data */ - {0x0002, 0x8116}, /* 200 kHz pump clock */ - {0x0020, 0x8112}, /* Video drop enable, ISO streaming disable */ -/* --------------------------------------- */ - {0x000f, 0x8402}, /* memory bank */ - {0x0000, 0x8403}, /* ... address */ -/* --------------------------------------- */ -/* 0x88__ is Synchronous Serial Interface. */ -/* TBD: This table could be expressed more compactly */ -/* using spca508_write_i2c_vector(). */ -/* TBD: Should see if the values in spca50x_i2c_data */ -/* would work with the VQ110 instead of the values */ -/* below. */ - {0x00c0, 0x8804}, /* SSI slave addr */ - {0x0008, 0x8802}, /* 375 Khz SSI clock */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, /* 375 Khz SSI clock */ - {0x0012, 0x8801}, /* SSI reg addr */ - {0x0080, 0x8800}, /* SSI data to write */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, /* 375 Khz SSI clock */ - {0x0012, 0x8801}, /* SSI reg addr */ - {0x0000, 0x8800}, /* SSI data to write */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, /* 375 Khz SSI clock */ - {0x0011, 0x8801}, /* SSI reg addr */ - {0x0040, 0x8800}, /* SSI data to write */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0013, 0x8801}, - {0x0000, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0014, 0x8801}, - {0x0000, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0015, 0x8801}, - {0x0001, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0016, 0x8801}, - {0x0003, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0017, 0x8801}, - {0x0036, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0018, 0x8801}, - {0x00ec, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x001a, 0x8801}, - {0x0094, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x001b, 0x8801}, - {0x0000, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0027, 0x8801}, - {0x00a2, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0028, 0x8801}, - {0x0040, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x002a, 0x8801}, - {0x0084, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x002b, 0x8801}, - {0x00a8, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x002c, 0x8801}, - {0x00fe, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x002d, 0x8801}, - {0x0003, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0038, 0x8801}, - {0x0083, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0033, 0x8801}, - {0x0081, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0034, 0x8801}, - {0x004a, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0039, 0x8801}, - {0x0000, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0010, 0x8801}, - {0x00a8, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0006, 0x8801}, - {0x0058, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0000, 0x8801}, - {0x0004, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0040, 0x8801}, - {0x0080, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0041, 0x8801}, - {0x000c, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0042, 0x8801}, - {0x000c, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0043, 0x8801}, - {0x0028, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0044, 0x8801}, - {0x0080, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0045, 0x8801}, - {0x0020, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0046, 0x8801}, - {0x0020, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0047, 0x8801}, - {0x0080, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0048, 0x8801}, - {0x004c, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x0049, 0x8801}, - {0x0084, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x004a, 0x8801}, - {0x0084, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x0008, 0x8802}, - {0x004b, 0x8801}, - {0x0084, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* --------------------------------------- */ - {0x0012, 0x8700}, /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */ - {0x0000, 0x8701}, /* CKx1 clock delay adj */ - {0x0000, 0x8701}, /* CKx1 clock delay adj */ - {0x0001, 0x870c}, /* CKOx2 output */ - /* --------------------------------------- */ - {0x0080, 0x8600}, /* Line memory read counter (L) */ - {0x0001, 0x8606}, /* reserved */ - {0x0064, 0x8607}, /* Line memory read counter (H) 0x6480=25,728 */ - {0x002a, 0x8601}, /* CDSP sharp interpolation mode, - * line sel for color sep, edge enhance enab */ - {0x0000, 0x8602}, /* optical black level for user settng = 0 */ - {0x0080, 0x8600}, /* Line memory read counter (L) */ - {0x000a, 0x8603}, /* optical black level calc mode: - * auto; optical black offset = 10 */ - {0x00df, 0x865b}, /* Horiz offset for valid pixels (L)=0xdf */ - {0x0012, 0x865c}, /* Vert offset for valid lines (L)=0x12 */ - -/* The following two lines seem to be the "wrong" resolution. */ -/* But perhaps these indicate the actual size of the sensor */ -/* rather than the size of the current video mode. */ - {0x0058, 0x865d}, /* Horiz valid pixels (*4) (L) = 352 */ - {0x0048, 0x865e}, /* Vert valid lines (*4) (L) = 288 */ - - {0x0015, 0x8608}, /* A11 Coef ... */ - {0x0030, 0x8609}, - {0x00fb, 0x860a}, - {0x003e, 0x860b}, - {0x00ce, 0x860c}, - {0x00f4, 0x860d}, - {0x00eb, 0x860e}, - {0x00dc, 0x860f}, - {0x0039, 0x8610}, - {0x0001, 0x8611}, /* R offset for white balance ... */ - {0x0000, 0x8612}, - {0x0001, 0x8613}, - {0x0000, 0x8614}, - {0x005b, 0x8651}, /* R gain for white balance ... */ - {0x0040, 0x8652}, - {0x0060, 0x8653}, - {0x0040, 0x8654}, - {0x0000, 0x8655}, - {0x0001, 0x863f}, /* Fixed gamma correction enable, USB control, - * lum filter disable, lum noise clip disable */ - {0x00a1, 0x8656}, /* Window1 size 256x256, Windows2 size 64x64, - * gamma look-up disable, - * new edge enhancement enable */ - {0x0018, 0x8657}, /* Edge gain high thresh */ - {0x0020, 0x8658}, /* Edge gain low thresh */ - {0x000a, 0x8659}, /* Edge bandwidth high threshold */ - {0x0005, 0x865a}, /* Edge bandwidth low threshold */ - /* -------------------------------- */ - {0x0030, 0x8112}, /* Video drop enable, ISO streaming enable */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0xa908, 0x8802}, - {0x0034, 0x8801}, /* SSI reg addr */ - {0x00ca, 0x8800}, - /* SSI data to write */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0x1f08, 0x8802}, - {0x0006, 0x8801}, - {0x0080, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - -/* ----- Read back coefs we wrote earlier. */ - /* READ { 0x0000, 0x8608 } -> 0000: 15 */ - /* READ { 0x0000, 0x8609 } -> 0000: 30 */ - /* READ { 0x0000, 0x860a } -> 0000: fb */ - /* READ { 0x0000, 0x860b } -> 0000: 3e */ - /* READ { 0x0000, 0x860c } -> 0000: ce */ - /* READ { 0x0000, 0x860d } -> 0000: f4 */ - /* READ { 0x0000, 0x860e } -> 0000: eb */ - /* READ { 0x0000, 0x860f } -> 0000: dc */ - /* READ { 0x0000, 0x8610 } -> 0000: 39 */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 08 */ - {0xb008, 0x8802}, - {0x0006, 0x8801}, - {0x007d, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - - /* This chunk is seemingly redundant with */ - /* earlier commands (A11 Coef...), but if I disable it, */ - /* the image appears too dark. Maybe there was some kind of */ - /* reset since the earlier commands, so this is necessary again. */ - {0x0015, 0x8608}, - {0x0030, 0x8609}, - {0xfffb, 0x860a}, - {0x003e, 0x860b}, - {0xffce, 0x860c}, - {0xfff4, 0x860d}, - {0xffeb, 0x860e}, - {0xffdc, 0x860f}, - {0x0039, 0x8610}, - {0x0018, 0x8657}, - - {0x0000, 0x8508}, /* Disable compression. */ - /* Previous line was: - {0x0021, 0x8508}, * Enable compression. */ - {0x0032, 0x850b}, /* compression stuff */ - {0x0003, 0x8509}, /* compression stuff */ - {0x0011, 0x850a}, /* compression stuff */ - {0x0021, 0x850d}, /* compression stuff */ - {0x0010, 0x850c}, /* compression stuff */ - {0x0003, 0x8500}, /* *** Video mode: 160x120 */ - {0x0001, 0x8501}, /* Hardware-dominated snap control */ - {0x0061, 0x8656}, /* Window1 size 128x128, Windows2 size 128x128, - * gamma look-up disable, - * new edge enhancement enable */ - {0x0018, 0x8617}, /* Window1 start X (*2) */ - {0x0008, 0x8618}, /* Window1 start Y (*2) */ - {0x0061, 0x8656}, /* Window1 size 128x128, Windows2 size 128x128, - * gamma look-up disable, - * new edge enhancement enable */ - {0x0058, 0x8619}, /* Window2 start X (*2) */ - {0x0008, 0x861a}, /* Window2 start Y (*2) */ - {0x00ff, 0x8615}, /* High lum thresh for white balance */ - {0x0000, 0x8616}, /* Low lum thresh for white balance */ - {0x0012, 0x8700}, /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */ - {0x0012, 0x8700}, /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */ - /* READ { 0x0000, 0x8656 } -> 0000: 61 */ - {0x0028, 0x8802}, /* 375 Khz SSI clock, SSI r/w sync with VSYNC */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 28 */ - {0x1f28, 0x8802}, /* 375 Khz SSI clock, SSI r/w sync with VSYNC */ - {0x0010, 0x8801}, /* SSI reg addr */ - {0x003e, 0x8800}, /* SSI data to write */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - {0x0028, 0x8802}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 28 */ - {0x1f28, 0x8802}, - {0x0000, 0x8801}, - {0x001f, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - {0x0001, 0x8602}, /* optical black level for user settning = 1 */ - - /* Original: */ - {0x0023, 0x8700}, /* Clock speed 48Mhz/(3+2)/4= 2.4 Mhz */ - {0x000f, 0x8602}, /* optical black level for user settning = 15 */ - - {0x0028, 0x8802}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 28 */ - {0x1f28, 0x8802}, - {0x0010, 0x8801}, - {0x007b, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - {0x002f, 0x8651}, /* R gain for white balance ... */ - {0x0080, 0x8653}, - /* READ { 0x0000, 0x8655 } -> 0000: 00 */ - {0x0000, 0x8655}, - - {0x0030, 0x8112}, /* Video drop enable, ISO streaming enable */ - {0x0020, 0x8112}, /* Video drop enable, ISO streaming disable */ - /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE: (ALT=0) ) */ - {} -}; - -/* - * Initialization data for Intel EasyPC Camera CS110 - */ -static const u16 spca508cs110_init_data[][2] = { - {0x0000, 0x870b}, /* Reset CTL3 */ - {0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */ - {0x0000, 0x8111}, /* Normal operation on reset */ - {0x0090, 0x8110}, - /* External Clock 2x & Synchronous Serial Interface Output */ - {0x0020, 0x8112}, /* Video Drop packet enable */ - {0x0000, 0x8114}, /* Software GPIO output data */ - {0x0001, 0x8114}, - {0x0001, 0x8114}, - {0x0001, 0x8114}, - {0x0003, 0x8114}, - - /* Initial sequence Synchronous Serial Interface */ - {0x000f, 0x8402}, /* Memory bank Address */ - {0x0000, 0x8403}, /* Memory bank Address */ - {0x00ba, 0x8804}, /* SSI Slave address */ - {0x0010, 0x8802}, /* 93.75kHz SSI Clock Two DataByte */ - {0x0010, 0x8802}, /* 93.75kHz SSI Clock two DataByte */ - - {0x0001, 0x8801}, - {0x000a, 0x8805}, /* a - NWG: Dunno what this is about */ - {0x0000, 0x8800}, - {0x0010, 0x8802}, - - {0x0002, 0x8801}, - {0x0000, 0x8805}, - {0x0000, 0x8800}, - {0x0010, 0x8802}, - - {0x0003, 0x8801}, - {0x0027, 0x8805}, - {0x0001, 0x8800}, - {0x0010, 0x8802}, - - {0x0004, 0x8801}, - {0x0065, 0x8805}, - {0x0001, 0x8800}, - {0x0010, 0x8802}, - - {0x0005, 0x8801}, - {0x0003, 0x8805}, - {0x0000, 0x8800}, - {0x0010, 0x8802}, - - {0x0006, 0x8801}, - {0x001c, 0x8805}, - {0x0000, 0x8800}, - {0x0010, 0x8802}, - - {0x0007, 0x8801}, - {0x002a, 0x8805}, - {0x0000, 0x8800}, - {0x0010, 0x8802}, - - {0x0002, 0x8704}, /* External input CKIx1 */ - {0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */ - {0x009a, 0x8600}, /* Line memory Read Counter (L) */ - {0x0001, 0x865b}, /* 1 Horizontal Offset for Valid Pixel(L) */ - {0x0003, 0x865c}, /* 3 Vertical Offset for Valid Lines(L) */ - {0x0058, 0x865d}, /* 58 Horizontal Valid Pixel Window(L) */ - - {0x0006, 0x8660}, /* Nibble data + input order */ - - {0x000a, 0x8602}, /* Optical black level set to 0x0a */ - {0x0000, 0x8603}, /* Optical black level Offset */ - -/* {0x0000, 0x8611}, * 0 R Offset for white Balance */ -/* {0x0000, 0x8612}, * 1 Gr Offset for white Balance */ -/* {0x0000, 0x8613}, * 1f B Offset for white Balance */ -/* {0x0000, 0x8614}, * f0 Gb Offset for white Balance */ - - {0x0040, 0x8651}, /* 2b BLUE gain for white balance good at all 60 */ - {0x0030, 0x8652}, /* 41 Gr Gain for white Balance (L) */ - {0x0035, 0x8653}, /* 26 RED gain for white balance */ - {0x0035, 0x8654}, /* 40Gb Gain for white Balance (L) */ - {0x0041, 0x863f}, - /* Fixed Gamma correction enabled (makes colours look better) */ - - {0x0000, 0x8655}, - /* High bits for white balance*****brightness control*** */ - {} -}; - -static const u16 spca508_sightcam_init_data[][2] = { -/* This line seems to setup the frame/canvas */ - {0x000f, 0x8402}, - -/* These 6 lines are needed to startup the webcam */ - {0x0090, 0x8110}, - {0x0001, 0x8114}, - {0x0001, 0x8114}, - {0x0001, 0x8114}, - {0x0003, 0x8114}, - {0x0080, 0x8804}, - -/* This part seems to make the pictures darker? (autobrightness?) */ - {0x0001, 0x8801}, - {0x0004, 0x8800}, - {0x0003, 0x8801}, - {0x00e0, 0x8800}, - {0x0004, 0x8801}, - {0x00b4, 0x8800}, - {0x0005, 0x8801}, - {0x0000, 0x8800}, - - {0x0006, 0x8801}, - {0x00e0, 0x8800}, - {0x0007, 0x8801}, - {0x000c, 0x8800}, - -/* This section is just needed, it probably - * does something like the previous section, - * but the cam won't start if it's not included. - */ - {0x0014, 0x8801}, - {0x0008, 0x8800}, - {0x0015, 0x8801}, - {0x0067, 0x8800}, - {0x0016, 0x8801}, - {0x0000, 0x8800}, - {0x0017, 0x8801}, - {0x0020, 0x8800}, - {0x0018, 0x8801}, - {0x0044, 0x8800}, - -/* Makes the picture darker - and the - * cam won't start if not included - */ - {0x001e, 0x8801}, - {0x00ea, 0x8800}, - {0x001f, 0x8801}, - {0x0001, 0x8800}, - {0x0003, 0x8801}, - {0x00e0, 0x8800}, - -/* seems to place the colors ontop of each other #1 */ - {0x0006, 0x8704}, - {0x0001, 0x870c}, - {0x0016, 0x8600}, - {0x0002, 0x8606}, - -/* if not included the pictures becomes _very_ dark */ - {0x0064, 0x8607}, - {0x003a, 0x8601}, - {0x0000, 0x8602}, - -/* seems to place the colors ontop of each other #2 */ - {0x0016, 0x8600}, - {0x0018, 0x8617}, - {0x0008, 0x8618}, - {0x00a1, 0x8656}, - -/* webcam won't start if not included */ - {0x0007, 0x865b}, - {0x0001, 0x865c}, - {0x0058, 0x865d}, - {0x0048, 0x865e}, - -/* adjusts the colors */ - {0x0049, 0x8651}, - {0x0040, 0x8652}, - {0x004c, 0x8653}, - {0x0040, 0x8654}, - {} -}; - -static const u16 spca508_sightcam2_init_data[][2] = { - {0x0020, 0x8112}, - - {0x000f, 0x8402}, - {0x0000, 0x8403}, - - {0x0008, 0x8201}, - {0x0008, 0x8200}, - {0x0001, 0x8200}, - {0x0009, 0x8201}, - {0x0008, 0x8200}, - {0x0001, 0x8200}, - {0x000a, 0x8201}, - {0x0008, 0x8200}, - {0x0001, 0x8200}, - {0x000b, 0x8201}, - {0x0008, 0x8200}, - {0x0001, 0x8200}, - {0x000c, 0x8201}, - {0x0008, 0x8200}, - {0x0001, 0x8200}, - {0x000d, 0x8201}, - {0x0008, 0x8200}, - {0x0001, 0x8200}, - {0x000e, 0x8201}, - {0x0008, 0x8200}, - {0x0001, 0x8200}, - {0x0007, 0x8201}, - {0x0008, 0x8200}, - {0x0001, 0x8200}, - {0x000f, 0x8201}, - {0x0008, 0x8200}, - {0x0001, 0x8200}, - - {0x0018, 0x8660}, - {0x0010, 0x8201}, - - {0x0008, 0x8200}, - {0x0001, 0x8200}, - {0x0011, 0x8201}, - {0x0008, 0x8200}, - {0x0001, 0x8200}, - - {0x0000, 0x86b0}, - {0x0034, 0x86b1}, - {0x0000, 0x86b2}, - {0x0049, 0x86b3}, - {0x0000, 0x86b4}, - {0x0000, 0x86b4}, - - {0x0012, 0x8201}, - {0x0008, 0x8200}, - {0x0001, 0x8200}, - {0x0013, 0x8201}, - {0x0008, 0x8200}, - {0x0001, 0x8200}, - - {0x0001, 0x86b0}, - {0x00aa, 0x86b1}, - {0x0000, 0x86b2}, - {0x00e4, 0x86b3}, - {0x0000, 0x86b4}, - {0x0000, 0x86b4}, - - {0x0018, 0x8660}, - - {0x0090, 0x8110}, - {0x0001, 0x8114}, - {0x0001, 0x8114}, - {0x0001, 0x8114}, - {0x0003, 0x8114}, - - {0x0080, 0x8804}, - {0x0003, 0x8801}, - {0x0012, 0x8800}, - {0x0004, 0x8801}, - {0x0005, 0x8800}, - {0x0005, 0x8801}, - {0x0000, 0x8800}, - {0x0006, 0x8801}, - {0x0000, 0x8800}, - {0x0007, 0x8801}, - {0x0000, 0x8800}, - {0x0008, 0x8801}, - {0x0005, 0x8800}, - {0x000a, 0x8700}, - {0x000e, 0x8801}, - {0x0004, 0x8800}, - {0x0005, 0x8801}, - {0x0047, 0x8800}, - {0x0006, 0x8801}, - {0x0000, 0x8800}, - {0x0007, 0x8801}, - {0x00c0, 0x8800}, - {0x0008, 0x8801}, - {0x0003, 0x8800}, - {0x0013, 0x8801}, - {0x0001, 0x8800}, - {0x0009, 0x8801}, - {0x0000, 0x8800}, - {0x000a, 0x8801}, - {0x0000, 0x8800}, - {0x000b, 0x8801}, - {0x0000, 0x8800}, - {0x000c, 0x8801}, - {0x0000, 0x8800}, - {0x000e, 0x8801}, - {0x0004, 0x8800}, - {0x000f, 0x8801}, - {0x0000, 0x8800}, - {0x0010, 0x8801}, - {0x0006, 0x8800}, - {0x0011, 0x8801}, - {0x0006, 0x8800}, - {0x0012, 0x8801}, - {0x0000, 0x8800}, - {0x0013, 0x8801}, - {0x0001, 0x8800}, - - {0x000a, 0x8700}, - {0x0000, 0x8702}, - {0x0000, 0x8703}, - {0x00c2, 0x8704}, - {0x0001, 0x870c}, - - {0x0044, 0x8600}, - {0x0002, 0x8606}, - {0x0064, 0x8607}, - {0x003a, 0x8601}, - {0x0008, 0x8602}, - {0x0044, 0x8600}, - {0x0018, 0x8617}, - {0x0008, 0x8618}, - {0x00a1, 0x8656}, - {0x0004, 0x865b}, - {0x0002, 0x865c}, - {0x0058, 0x865d}, - {0x0048, 0x865e}, - {0x0012, 0x8608}, - {0x002c, 0x8609}, - {0x0002, 0x860a}, - {0x002c, 0x860b}, - {0x00db, 0x860c}, - {0x00f9, 0x860d}, - {0x00f1, 0x860e}, - {0x00e3, 0x860f}, - {0x002c, 0x8610}, - {0x006c, 0x8651}, - {0x0041, 0x8652}, - {0x0059, 0x8653}, - {0x0040, 0x8654}, - {0x00fa, 0x8611}, - {0x00ff, 0x8612}, - {0x00f8, 0x8613}, - {0x0000, 0x8614}, - {0x0001, 0x863f}, - {0x0000, 0x8640}, - {0x0026, 0x8641}, - {0x0045, 0x8642}, - {0x0060, 0x8643}, - {0x0075, 0x8644}, - {0x0088, 0x8645}, - {0x009b, 0x8646}, - {0x00b0, 0x8647}, - {0x00c5, 0x8648}, - {0x00d2, 0x8649}, - {0x00dc, 0x864a}, - {0x00e5, 0x864b}, - {0x00eb, 0x864c}, - {0x00f0, 0x864d}, - {0x00f6, 0x864e}, - {0x00fa, 0x864f}, - {0x00ff, 0x8650}, - {0x0060, 0x8657}, - {0x0010, 0x8658}, - {0x0018, 0x8659}, - {0x0005, 0x865a}, - {0x0018, 0x8660}, - {0x0003, 0x8509}, - {0x0011, 0x850a}, - {0x0032, 0x850b}, - {0x0010, 0x850c}, - {0x0021, 0x850d}, - {0x0001, 0x8500}, - {0x0000, 0x8508}, - {0x0012, 0x8608}, - {0x002c, 0x8609}, - {0x0002, 0x860a}, - {0x0039, 0x860b}, - {0x00d0, 0x860c}, - {0x00f7, 0x860d}, - {0x00ed, 0x860e}, - {0x00db, 0x860f}, - {0x0039, 0x8610}, - {0x0012, 0x8657}, - {0x000c, 0x8619}, - {0x0004, 0x861a}, - {0x00a1, 0x8656}, - {0x00c8, 0x8615}, - {0x0032, 0x8616}, - - {0x0030, 0x8112}, - {0x0020, 0x8112}, - {0x0020, 0x8112}, - {0x000f, 0x8402}, - {0x0000, 0x8403}, - - {0x0090, 0x8110}, - {0x0001, 0x8114}, - {0x0001, 0x8114}, - {0x0001, 0x8114}, - {0x0003, 0x8114}, - {0x0080, 0x8804}, - - {0x0003, 0x8801}, - {0x0012, 0x8800}, - {0x0004, 0x8801}, - {0x0005, 0x8800}, - {0x0005, 0x8801}, - {0x0047, 0x8800}, - {0x0006, 0x8801}, - {0x0000, 0x8800}, - {0x0007, 0x8801}, - {0x00c0, 0x8800}, - {0x0008, 0x8801}, - {0x0003, 0x8800}, - {0x000a, 0x8700}, - {0x000e, 0x8801}, - {0x0004, 0x8800}, - {0x0005, 0x8801}, - {0x0047, 0x8800}, - {0x0006, 0x8801}, - {0x0000, 0x8800}, - {0x0007, 0x8801}, - {0x00c0, 0x8800}, - {0x0008, 0x8801}, - {0x0003, 0x8800}, - {0x0013, 0x8801}, - {0x0001, 0x8800}, - {0x0009, 0x8801}, - {0x0000, 0x8800}, - {0x000a, 0x8801}, - {0x0000, 0x8800}, - {0x000b, 0x8801}, - {0x0000, 0x8800}, - {0x000c, 0x8801}, - {0x0000, 0x8800}, - {0x000e, 0x8801}, - {0x0004, 0x8800}, - {0x000f, 0x8801}, - {0x0000, 0x8800}, - {0x0010, 0x8801}, - {0x0006, 0x8800}, - {0x0011, 0x8801}, - {0x0006, 0x8800}, - {0x0012, 0x8801}, - {0x0000, 0x8800}, - {0x0013, 0x8801}, - {0x0001, 0x8800}, - {0x000a, 0x8700}, - {0x0000, 0x8702}, - {0x0000, 0x8703}, - {0x00c2, 0x8704}, - {0x0001, 0x870c}, - {0x0044, 0x8600}, - {0x0002, 0x8606}, - {0x0064, 0x8607}, - {0x003a, 0x8601}, - {0x0008, 0x8602}, - {0x0044, 0x8600}, - {0x0018, 0x8617}, - {0x0008, 0x8618}, - {0x00a1, 0x8656}, - {0x0004, 0x865b}, - {0x0002, 0x865c}, - {0x0058, 0x865d}, - {0x0048, 0x865e}, - {0x0012, 0x8608}, - {0x002c, 0x8609}, - {0x0002, 0x860a}, - {0x002c, 0x860b}, - {0x00db, 0x860c}, - {0x00f9, 0x860d}, - {0x00f1, 0x860e}, - {0x00e3, 0x860f}, - {0x002c, 0x8610}, - {0x006c, 0x8651}, - {0x0041, 0x8652}, - {0x0059, 0x8653}, - {0x0040, 0x8654}, - {0x00fa, 0x8611}, - {0x00ff, 0x8612}, - {0x00f8, 0x8613}, - {0x0000, 0x8614}, - {0x0001, 0x863f}, - {0x0000, 0x8640}, - {0x0026, 0x8641}, - {0x0045, 0x8642}, - {0x0060, 0x8643}, - {0x0075, 0x8644}, - {0x0088, 0x8645}, - {0x009b, 0x8646}, - {0x00b0, 0x8647}, - {0x00c5, 0x8648}, - {0x00d2, 0x8649}, - {0x00dc, 0x864a}, - {0x00e5, 0x864b}, - {0x00eb, 0x864c}, - {0x00f0, 0x864d}, - {0x00f6, 0x864e}, - {0x00fa, 0x864f}, - {0x00ff, 0x8650}, - {0x0060, 0x8657}, - {0x0010, 0x8658}, - {0x0018, 0x8659}, - {0x0005, 0x865a}, - {0x0018, 0x8660}, - {0x0003, 0x8509}, - {0x0011, 0x850a}, - {0x0032, 0x850b}, - {0x0010, 0x850c}, - {0x0021, 0x850d}, - {0x0001, 0x8500}, - {0x0000, 0x8508}, - - {0x0012, 0x8608}, - {0x002c, 0x8609}, - {0x0002, 0x860a}, - {0x0039, 0x860b}, - {0x00d0, 0x860c}, - {0x00f7, 0x860d}, - {0x00ed, 0x860e}, - {0x00db, 0x860f}, - {0x0039, 0x8610}, - {0x0012, 0x8657}, - {0x0064, 0x8619}, - -/* This line starts it all, it is not needed here */ -/* since it has been build into the driver */ -/* jfm: don't start now */ -/* {0x0030, 0x8112}, */ - {} -}; - -/* - * Initialization data for Creative Webcam Vista - */ -static const u16 spca508_vista_init_data[][2] = { - {0x0008, 0x8200}, /* Clear register */ - {0x0000, 0x870b}, /* Reset CTL3 */ - {0x0020, 0x8112}, /* Video Drop packet enable */ - {0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */ - {0x0000, 0x8110}, /* Disable everything */ - {0x0000, 0x8114}, /* Software GPIO output data */ - {0x0000, 0x8114}, - - {0x0003, 0x8111}, - {0x0000, 0x8111}, - {0x0090, 0x8110}, /* Enable: SSI output, External 2X clock output */ - {0x0020, 0x8112}, - {0x0000, 0x8114}, - {0x0001, 0x8114}, - {0x0001, 0x8114}, - {0x0001, 0x8114}, - {0x0003, 0x8114}, - - {0x000f, 0x8402}, /* Memory bank Address */ - {0x0000, 0x8403}, /* Memory bank Address */ - {0x00ba, 0x8804}, /* SSI Slave address */ - {0x0010, 0x8802}, /* 93.75kHz SSI Clock Two DataByte */ - - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 10 */ - {0x0010, 0x8802}, /* Will write 2 bytes (DATA1+DATA2) */ - {0x0020, 0x8801}, /* Register address for SSI read/write */ - {0x0044, 0x8805}, /* DATA2 */ - {0x0004, 0x8800}, /* DATA1 -> write triggered */ - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 10 */ - {0x0010, 0x8802}, - {0x0009, 0x8801}, - {0x0042, 0x8805}, - {0x0001, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 10 */ - {0x0010, 0x8802}, - {0x003c, 0x8801}, - {0x0001, 0x8805}, - {0x0000, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 10 */ - {0x0010, 0x8802}, - {0x0001, 0x8801}, - {0x000a, 0x8805}, - {0x0000, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 10 */ - {0x0010, 0x8802}, - {0x0002, 0x8801}, - {0x0000, 0x8805}, - {0x0000, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 10 */ - {0x0010, 0x8802}, - {0x0003, 0x8801}, - {0x0027, 0x8805}, - {0x0001, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 10 */ - {0x0010, 0x8802}, - {0x0004, 0x8801}, - {0x0065, 0x8805}, - {0x0001, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 10 */ - {0x0010, 0x8802}, - {0x0005, 0x8801}, - {0x0003, 0x8805}, - {0x0000, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 10 */ - {0x0010, 0x8802}, - {0x0006, 0x8801}, - {0x001c, 0x8805}, - {0x0000, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 10 */ - {0x0010, 0x8802}, - {0x0007, 0x8801}, - {0x002a, 0x8805}, - {0x0000, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 10 */ - {0x0010, 0x8802}, - {0x000e, 0x8801}, - {0x0000, 0x8805}, - {0x0000, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 10 */ - {0x0010, 0x8802}, - {0x0028, 0x8801}, - {0x002e, 0x8805}, - {0x0000, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 10 */ - {0x0010, 0x8802}, - {0x0039, 0x8801}, - {0x0013, 0x8805}, - {0x0000, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 10 */ - {0x0010, 0x8802}, - {0x003b, 0x8801}, - {0x000c, 0x8805}, - {0x0000, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 10 */ - {0x0010, 0x8802}, - {0x0035, 0x8801}, - {0x0028, 0x8805}, - {0x0000, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - /* READ { 0x0001, 0x8802 } -> 0000: 10 */ - {0x0010, 0x8802}, - {0x0009, 0x8801}, - {0x0042, 0x8805}, - {0x0001, 0x8800}, - /* READ { 0x0001, 0x8803 } -> 0000: 00 */ - - {0x0050, 0x8703}, - {0x0002, 0x8704}, /* External input CKIx1 */ - {0x0001, 0x870c}, /* Select CKOx2 output */ - {0x009a, 0x8600}, /* Line memory Read Counter (L) */ - {0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */ - {0x0023, 0x8601}, - {0x0010, 0x8602}, - {0x000a, 0x8603}, - {0x009a, 0x8600}, - {0x0001, 0x865b}, /* 1 Horizontal Offset for Valid Pixel(L) */ - {0x0003, 0x865c}, /* Vertical offset for valid lines (L) */ - {0x0058, 0x865d}, /* Horizontal valid pixels window (L) */ - {0x0048, 0x865e}, /* Vertical valid lines window (L) */ - {0x0000, 0x865f}, - - {0x0006, 0x8660}, - /* Enable nibble data input, select nibble input order */ - - {0x0013, 0x8608}, /* A11 Coeficients for color correction */ - {0x0028, 0x8609}, - /* Note: these values are confirmed at the end of array */ - {0x0005, 0x860a}, /* ... */ - {0x0025, 0x860b}, - {0x00e1, 0x860c}, - {0x00fa, 0x860d}, - {0x00f4, 0x860e}, - {0x00e8, 0x860f}, - {0x0025, 0x8610}, /* A33 Coef. */ - {0x00fc, 0x8611}, /* White balance offset: R */ - {0x0001, 0x8612}, /* White balance offset: Gr */ - {0x00fe, 0x8613}, /* White balance offset: B */ - {0x0000, 0x8614}, /* White balance offset: Gb */ - - {0x0064, 0x8651}, /* R gain for white balance (L) */ - {0x0040, 0x8652}, /* Gr gain for white balance (L) */ - {0x0066, 0x8653}, /* B gain for white balance (L) */ - {0x0040, 0x8654}, /* Gb gain for white balance (L) */ - {0x0001, 0x863f}, /* Enable fixed gamma correction */ - - {0x00a1, 0x8656}, /* Size - Window1: 256x256, Window2: 128x128, - * UV division: UV no change, - * Enable New edge enhancement */ - {0x0018, 0x8657}, /* Edge gain high threshold */ - {0x0020, 0x8658}, /* Edge gain low threshold */ - {0x000a, 0x8659}, /* Edge bandwidth high threshold */ - {0x0005, 0x865a}, /* Edge bandwidth low threshold */ - {0x0064, 0x8607}, /* UV filter enable */ - - {0x0016, 0x8660}, - {0x0000, 0x86b0}, /* Bad pixels compensation address */ - {0x00dc, 0x86b1}, /* X coord for bad pixels compensation (L) */ - {0x0000, 0x86b2}, - {0x0009, 0x86b3}, /* Y coord for bad pixels compensation (L) */ - {0x0000, 0x86b4}, - - {0x0001, 0x86b0}, - {0x00f5, 0x86b1}, - {0x0000, 0x86b2}, - {0x00c6, 0x86b3}, - {0x0000, 0x86b4}, - - {0x0002, 0x86b0}, - {0x001c, 0x86b1}, - {0x0001, 0x86b2}, - {0x00d7, 0x86b3}, - {0x0000, 0x86b4}, - - {0x0003, 0x86b0}, - {0x001c, 0x86b1}, - {0x0001, 0x86b2}, - {0x00d8, 0x86b3}, - {0x0000, 0x86b4}, - - {0x0004, 0x86b0}, - {0x001d, 0x86b1}, - {0x0001, 0x86b2}, - {0x00d8, 0x86b3}, - {0x0000, 0x86b4}, - {0x001e, 0x8660}, - - /* READ { 0x0000, 0x8608 } -> 0000: 13 */ - /* READ { 0x0000, 0x8609 } -> 0000: 28 */ - /* READ { 0x0000, 0x8610 } -> 0000: 05 */ - /* READ { 0x0000, 0x8611 } -> 0000: 25 */ - /* READ { 0x0000, 0x8612 } -> 0000: e1 */ - /* READ { 0x0000, 0x8613 } -> 0000: fa */ - /* READ { 0x0000, 0x8614 } -> 0000: f4 */ - /* READ { 0x0000, 0x8615 } -> 0000: e8 */ - /* READ { 0x0000, 0x8616 } -> 0000: 25 */ - {} -}; - -static int reg_write(struct usb_device *dev, - u16 index, u16 value) -{ - int ret; - - ret = usb_control_msg(dev, - usb_sndctrlpipe(dev, 0), - 0, /* request */ - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, NULL, 0, 500); - PDEBUG(D_USBO, "reg write i:0x%04x = 0x%02x", - index, value); - if (ret < 0) - pr_err("reg write: error %d\n", ret); - return ret; -} - -/* read 1 byte */ -/* returns: negative is error, pos or zero is data */ -static int reg_read(struct gspca_dev *gspca_dev, - u16 index) /* wIndex */ -{ - int ret; - - ret = usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - 0, /* register */ - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, /* value */ - index, - gspca_dev->usb_buf, 1, - 500); /* timeout */ - PDEBUG(D_USBI, "reg read i:%04x --> %02x", - index, gspca_dev->usb_buf[0]); - if (ret < 0) { - pr_err("reg_read err %d\n", ret); - return ret; - } - return gspca_dev->usb_buf[0]; -} - -/* send 1 or 2 bytes to the sensor via the Synchronous Serial Interface */ -static int ssi_w(struct gspca_dev *gspca_dev, - u16 reg, u16 val) -{ - struct usb_device *dev = gspca_dev->dev; - int ret, retry; - - ret = reg_write(dev, 0x8802, reg >> 8); - if (ret < 0) - goto out; - ret = reg_write(dev, 0x8801, reg & 0x00ff); - if (ret < 0) - goto out; - if ((reg & 0xff00) == 0x1000) { /* if 2 bytes */ - ret = reg_write(dev, 0x8805, val & 0x00ff); - if (ret < 0) - goto out; - val >>= 8; - } - ret = reg_write(dev, 0x8800, val); - if (ret < 0) - goto out; - - /* poll until not busy */ - retry = 10; - for (;;) { - ret = reg_read(gspca_dev, 0x8803); - if (ret < 0) - break; - if (gspca_dev->usb_buf[0] == 0) - break; - if (--retry <= 0) { - PDEBUG(D_ERR, "ssi_w busy %02x", - gspca_dev->usb_buf[0]); - ret = -1; - break; - } - msleep(8); - } - -out: - return ret; -} - -static int write_vector(struct gspca_dev *gspca_dev, - const u16 (*data)[2]) -{ - struct usb_device *dev = gspca_dev->dev; - int ret = 0; - - while ((*data)[1] != 0) { - if ((*data)[1] & 0x8000) { - if ((*data)[1] == 0xdd00) /* delay */ - msleep((*data)[0]); - else - ret = reg_write(dev, (*data)[1], (*data)[0]); - } else { - ret = ssi_w(gspca_dev, (*data)[1], (*data)[0]); - } - if (ret < 0) - break; - data++; - } - return ret; -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - const u16 (*init_data)[2]; - static const u16 (*(init_data_tb[]))[2] = { - spca508_vista_init_data, /* CreativeVista 0 */ - spca508_sightcam_init_data, /* HamaUSBSightcam 1 */ - spca508_sightcam2_init_data, /* HamaUSBSightcam2 2 */ - spca508cs110_init_data, /* IntelEasyPCCamera 3 */ - spca508cs110_init_data, /* MicroInnovationIC200 4 */ - spca508_init_data, /* ViewQuestVQ110 5 */ - }; - -#ifdef GSPCA_DEBUG - int data1, data2; - - /* Read from global register the USB product and vendor IDs, just to - * prove that we can communicate with the device. This works, which - * confirms at we are communicating properly and that the device - * is a 508. */ - data1 = reg_read(gspca_dev, 0x8104); - data2 = reg_read(gspca_dev, 0x8105); - PDEBUG(D_PROBE, "Webcam Vendor ID: 0x%02x%02x", data2, data1); - - data1 = reg_read(gspca_dev, 0x8106); - data2 = reg_read(gspca_dev, 0x8107); - PDEBUG(D_PROBE, "Webcam Product ID: 0x%02x%02x", data2, data1); - - data1 = reg_read(gspca_dev, 0x8621); - PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1); -#endif - - cam = &gspca_dev->cam; - cam->cam_mode = sif_mode; - cam->nmodes = ARRAY_SIZE(sif_mode); - - sd->subtype = id->driver_info; - - init_data = init_data_tb[sd->subtype]; - return write_vector(gspca_dev, init_data); -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - return 0; -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - int mode; - - mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - reg_write(gspca_dev->dev, 0x8500, mode); - switch (mode) { - case 0: - case 1: - reg_write(gspca_dev->dev, 0x8700, 0x28); /* clock */ - break; - default: -/* case 2: */ -/* case 3: */ - reg_write(gspca_dev->dev, 0x8700, 0x23); /* clock */ - break; - } - reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20); - return 0; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - /* Video ISO disable, Video Drop Packet enable: */ - reg_write(gspca_dev->dev, 0x8112, 0x20); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - switch (data[0]) { - case 0: /* start of frame */ - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - data += SPCA508_OFFSET_DATA; - len -= SPCA508_OFFSET_DATA; - gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); - break; - case 0xff: /* drop */ - break; - default: - data += 1; - len -= 1; - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); - break; - } -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness) -{ - /* MX seem contrast */ - reg_write(gspca_dev->dev, 0x8651, brightness); - reg_write(gspca_dev->dev, 0x8652, brightness); - reg_write(gspca_dev->dev, 0x8653, brightness); - reg_write(gspca_dev->dev, 0x8654, brightness); -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 5); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam}, - {USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista}, - {USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110}, - {USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam}, - {USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2}, - {USB_DEVICE(0x8086, 0x0110), .driver_info = IntelEasyPCCamera}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c deleted file mode 100644 index cfe71dd6747d..000000000000 --- a/drivers/media/video/gspca/spca561.c +++ /dev/null @@ -1,936 +0,0 @@ -/* - * Sunplus spca561 subdriver - * - * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr - * - * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "spca561" - -#include <linux/input.h> -#include "gspca.h" - -MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); -MODULE_DESCRIPTION("GSPCA/SPCA561 USB Camera Driver"); -MODULE_LICENSE("GPL"); - -#define EXPOSURE_MAX (2047 + 325) - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - struct { /* hue/contrast control cluster */ - struct v4l2_ctrl *contrast; - struct v4l2_ctrl *hue; - }; - struct v4l2_ctrl *autogain; - -#define EXPO12A_DEF 3 - __u8 expo12a; /* expo/gain? for rev 12a */ - - __u8 chip_revision; -#define Rev012A 0 -#define Rev072A 1 - - signed char ag_cnt; -#define AG_CNT_START 13 -}; - -static const struct v4l2_pix_format sif_012a_mode[] = { - {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 3}, - {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, - {320, 240, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 4 / 8, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {352, 288, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 4 / 8, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; - -static const struct v4l2_pix_format sif_072a_mode[] = { - {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 3}, - {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, - {320, 240, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {352, 288, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; - -/* - * Initialization data - * I'm not very sure how to split initialization from open data - * chunks. For now, we'll consider everything as initialization - */ -/* Frame packet header offsets for the spca561 */ -#define SPCA561_OFFSET_SNAP 1 -#define SPCA561_OFFSET_TYPE 2 -#define SPCA561_OFFSET_COMPRESS 3 -#define SPCA561_OFFSET_FRAMSEQ 4 -#define SPCA561_OFFSET_GPIO 5 -#define SPCA561_OFFSET_USBBUFF 6 -#define SPCA561_OFFSET_WIN2GRAVE 7 -#define SPCA561_OFFSET_WIN2RAVE 8 -#define SPCA561_OFFSET_WIN2BAVE 9 -#define SPCA561_OFFSET_WIN2GBAVE 10 -#define SPCA561_OFFSET_WIN1GRAVE 11 -#define SPCA561_OFFSET_WIN1RAVE 12 -#define SPCA561_OFFSET_WIN1BAVE 13 -#define SPCA561_OFFSET_WIN1GBAVE 14 -#define SPCA561_OFFSET_FREQ 15 -#define SPCA561_OFFSET_VSYNC 16 -#define SPCA561_INDEX_I2C_BASE 0x8800 -#define SPCA561_SNAPBIT 0x20 -#define SPCA561_SNAPCTRL 0x40 - -static const u16 rev72a_reset[][2] = { - {0x0000, 0x8114}, /* Software GPIO output data */ - {0x0001, 0x8114}, /* Software GPIO output data */ - {0x0000, 0x8112}, /* Some kind of reset */ - {} -}; -static const __u16 rev72a_init_data1[][2] = { - {0x0003, 0x8701}, /* PCLK clock delay adjustment */ - {0x0001, 0x8703}, /* HSYNC from cmos inverted */ - {0x0011, 0x8118}, /* Enable and conf sensor */ - {0x0001, 0x8118}, /* Conf sensor */ - {0x0092, 0x8804}, /* I know nothing about these */ - {0x0010, 0x8802}, /* 0x88xx registers, so I won't */ - {} -}; -static const u16 rev72a_init_sensor1[][2] = { - {0x0001, 0x000d}, - {0x0002, 0x0018}, - {0x0004, 0x0165}, - {0x0005, 0x0021}, - {0x0007, 0x00aa}, - {0x0020, 0x1504}, - {0x0039, 0x0002}, - {0x0035, 0x0010}, - {0x0009, 0x1049}, - {0x0028, 0x000b}, - {0x003b, 0x000f}, - {0x003c, 0x0000}, - {} -}; -static const __u16 rev72a_init_data2[][2] = { - {0x0018, 0x8601}, /* Pixel/line selection for color separation */ - {0x0000, 0x8602}, /* Optical black level for user setting */ - {0x0060, 0x8604}, /* Optical black horizontal offset */ - {0x0002, 0x8605}, /* Optical black vertical offset */ - {0x0000, 0x8603}, /* Non-automatic optical black level */ - {0x0002, 0x865b}, /* Horizontal offset for valid pixels */ - {0x0000, 0x865f}, /* Vertical valid pixels window (x2) */ - {0x00b0, 0x865d}, /* Horizontal valid pixels window (x2) */ - {0x0090, 0x865e}, /* Vertical valid lines window (x2) */ - {0x00e0, 0x8406}, /* Memory buffer threshold */ - {0x0000, 0x8660}, /* Compensation memory stuff */ - {0x0002, 0x8201}, /* Output address for r/w serial EEPROM */ - {0x0008, 0x8200}, /* Clear valid bit for serial EEPROM */ - {0x0001, 0x8200}, /* OprMode to be executed by hardware */ -/* from ms-win */ - {0x0000, 0x8611}, /* R offset for white balance */ - {0x00fd, 0x8612}, /* Gr offset for white balance */ - {0x0003, 0x8613}, /* B offset for white balance */ - {0x0000, 0x8614}, /* Gb offset for white balance */ -/* from ms-win */ - {0x0035, 0x8651}, /* R gain for white balance */ - {0x0040, 0x8652}, /* Gr gain for white balance */ - {0x005f, 0x8653}, /* B gain for white balance */ - {0x0040, 0x8654}, /* Gb gain for white balance */ - {0x0002, 0x8502}, /* Maximum average bit rate stuff */ - {0x0011, 0x8802}, - - {0x0087, 0x8700}, /* Set master clock (96Mhz????) */ - {0x0081, 0x8702}, /* Master clock output enable */ - - {0x0000, 0x8500}, /* Set image type (352x288 no compression) */ - /* Originally was 0x0010 (352x288 compression) */ - - {0x0002, 0x865b}, /* Horizontal offset for valid pixels */ - {0x0003, 0x865c}, /* Vertical offset for valid lines */ - {} -}; -static const u16 rev72a_init_sensor2[][2] = { - {0x0003, 0x0121}, - {0x0004, 0x0165}, - {0x0005, 0x002f}, /* blanking control column */ - {0x0006, 0x0000}, /* blanking mode row*/ - {0x000a, 0x0002}, - {0x0009, 0x1061}, /* setexposure times && pixel clock - * 0001 0 | 000 0110 0001 */ - {0x0035, 0x0014}, - {} -}; - -/******************** QC Express etch2 stuff ********************/ -static const __u16 Pb100_1map8300[][2] = { - /* reg, value */ - {0x8320, 0x3304}, - - {0x8303, 0x0125}, /* image area */ - {0x8304, 0x0169}, - {0x8328, 0x000b}, - {0x833c, 0x0001}, /*fixme: win:07*/ - - {0x832f, 0x1904}, /*fixme: was 0419*/ - {0x8307, 0x00aa}, - {0x8301, 0x0003}, - {0x8302, 0x000e}, - {} -}; -static const __u16 Pb100_2map8300[][2] = { - /* reg, value */ - {0x8339, 0x0000}, - {0x8307, 0x00aa}, - {} -}; - -static const __u16 spca561_161rev12A_data1[][2] = { - {0x29, 0x8118}, /* Control register (various enable bits) */ - {0x08, 0x8114}, /* GPIO: Led off */ - {0x0e, 0x8112}, /* 0x0e stream off 0x3e stream on */ - {0x00, 0x8102}, /* white balance - new */ - {0x92, 0x8804}, - {0x04, 0x8802}, /* windows uses 08 */ - {} -}; -static const __u16 spca561_161rev12A_data2[][2] = { - {0x21, 0x8118}, - {0x10, 0x8500}, - {0x07, 0x8601}, - {0x07, 0x8602}, - {0x04, 0x8501}, - - {0x07, 0x8201}, /* windows uses 02 */ - {0x08, 0x8200}, - {0x01, 0x8200}, - - {0x90, 0x8604}, - {0x00, 0x8605}, - {0xb0, 0x8603}, - - /* sensor gains */ - {0x07, 0x8601}, /* white balance - new */ - {0x07, 0x8602}, /* white balance - new */ - {0x00, 0x8610}, /* *red */ - {0x00, 0x8611}, /* 3f *green */ - {0x00, 0x8612}, /* green *blue */ - {0x00, 0x8613}, /* blue *green */ - {0x43, 0x8614}, /* green *red - white balance - was 0x35 */ - {0x40, 0x8615}, /* 40 *green - white balance - was 0x35 */ - {0x71, 0x8616}, /* 7a *blue - white balance - was 0x35 */ - {0x40, 0x8617}, /* 40 *green - white balance - was 0x35 */ - - {0x0c, 0x8620}, /* 0c */ - {0xc8, 0x8631}, /* c8 */ - {0xc8, 0x8634}, /* c8 */ - {0x23, 0x8635}, /* 23 */ - {0x1f, 0x8636}, /* 1f */ - {0xdd, 0x8637}, /* dd */ - {0xe1, 0x8638}, /* e1 */ - {0x1d, 0x8639}, /* 1d */ - {0x21, 0x863a}, /* 21 */ - {0xe3, 0x863b}, /* e3 */ - {0xdf, 0x863c}, /* df */ - {0xf0, 0x8505}, - {0x32, 0x850a}, -/* {0x99, 0x8700}, * - white balance - new (removed) */ - /* HDG we used to do this in stop0, making the init state and the state - after a start / stop different, so do this here instead. */ - {0x29, 0x8118}, - {} -}; - -static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value) -{ - int ret; - - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, NULL, 0, 500); - PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value); - if (ret < 0) - pr_err("reg write: error %d\n", ret); -} - -static void write_vector(struct gspca_dev *gspca_dev, - const __u16 data[][2]) -{ - struct usb_device *dev = gspca_dev->dev; - int i; - - i = 0; - while (data[i][1] != 0) { - reg_w_val(dev, data[i][1], data[i][0]); - i++; - } -} - -/* read 'len' bytes to gspca_dev->usb_buf */ -static void reg_r(struct gspca_dev *gspca_dev, - __u16 index, __u16 length) -{ - usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - 0, /* request */ - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, /* value */ - index, gspca_dev->usb_buf, length, 500); -} - -/* write 'len' bytes from gspca_dev->usb_buf */ -static void reg_w_buf(struct gspca_dev *gspca_dev, - __u16 index, __u16 len) -{ - usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, /* value */ - index, gspca_dev->usb_buf, len, 500); -} - -static void i2c_write(struct gspca_dev *gspca_dev, __u16 value, __u16 reg) -{ - int retry = 60; - - reg_w_val(gspca_dev->dev, 0x8801, reg); - reg_w_val(gspca_dev->dev, 0x8805, value); - reg_w_val(gspca_dev->dev, 0x8800, value >> 8); - do { - reg_r(gspca_dev, 0x8803, 1); - if (!gspca_dev->usb_buf[0]) - return; - msleep(10); - } while (--retry); -} - -static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode) -{ - int retry = 60; - __u8 value; - - reg_w_val(gspca_dev->dev, 0x8804, 0x92); - reg_w_val(gspca_dev->dev, 0x8801, reg); - reg_w_val(gspca_dev->dev, 0x8802, mode | 0x01); - do { - reg_r(gspca_dev, 0x8803, 1); - if (!gspca_dev->usb_buf[0]) { - reg_r(gspca_dev, 0x8800, 1); - value = gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8805, 1); - return ((int) value << 8) | gspca_dev->usb_buf[0]; - } - msleep(10); - } while (--retry); - return -1; -} - -static void sensor_mapwrite(struct gspca_dev *gspca_dev, - const __u16 (*sensormap)[2]) -{ - while ((*sensormap)[0]) { - gspca_dev->usb_buf[0] = (*sensormap)[1]; - gspca_dev->usb_buf[1] = (*sensormap)[1] >> 8; - reg_w_buf(gspca_dev, (*sensormap)[0], 2); - sensormap++; - } -} - -static void write_sensor_72a(struct gspca_dev *gspca_dev, - const __u16 (*sensor)[2]) -{ - while ((*sensor)[0]) { - i2c_write(gspca_dev, (*sensor)[1], (*sensor)[0]); - sensor++; - } -} - -static void init_161rev12A(struct gspca_dev *gspca_dev) -{ - write_vector(gspca_dev, spca561_161rev12A_data1); - sensor_mapwrite(gspca_dev, Pb100_1map8300); -/*fixme: should be in sd_start*/ - write_vector(gspca_dev, spca561_161rev12A_data2); - sensor_mapwrite(gspca_dev, Pb100_2map8300); -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - __u16 vendor, product; - __u8 data1, data2; - - /* Read frm global register the USB product and vendor IDs, just to - * prove that we can communicate with the device. This works, which - * confirms at we are communicating properly and that the device - * is a 561. */ - reg_r(gspca_dev, 0x8104, 1); - data1 = gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8105, 1); - data2 = gspca_dev->usb_buf[0]; - vendor = (data2 << 8) | data1; - reg_r(gspca_dev, 0x8106, 1); - data1 = gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8107, 1); - data2 = gspca_dev->usb_buf[0]; - product = (data2 << 8) | data1; - if (vendor != id->idVendor || product != id->idProduct) { - PDEBUG(D_PROBE, "Bad vendor / product from device"); - return -EINVAL; - } - - cam = &gspca_dev->cam; - cam->needs_full_bandwidth = 1; - - sd->chip_revision = id->driver_info; - if (sd->chip_revision == Rev012A) { - cam->cam_mode = sif_012a_mode; - cam->nmodes = ARRAY_SIZE(sif_012a_mode); - } else { - cam->cam_mode = sif_072a_mode; - cam->nmodes = ARRAY_SIZE(sif_072a_mode); - } - sd->expo12a = EXPO12A_DEF; - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init_12a(struct gspca_dev *gspca_dev) -{ - PDEBUG(D_STREAM, "Chip revision: 012a"); - init_161rev12A(gspca_dev); - return 0; -} -static int sd_init_72a(struct gspca_dev *gspca_dev) -{ - PDEBUG(D_STREAM, "Chip revision: 072a"); - write_vector(gspca_dev, rev72a_reset); - msleep(200); - write_vector(gspca_dev, rev72a_init_data1); - write_sensor_72a(gspca_dev, rev72a_init_sensor1); - write_vector(gspca_dev, rev72a_init_data2); - write_sensor_72a(gspca_dev, rev72a_init_sensor2); - reg_w_val(gspca_dev->dev, 0x8112, 0x30); - return 0; -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; - __u16 reg; - - if (sd->chip_revision == Rev012A) - reg = 0x8610; - else - reg = 0x8611; - - reg_w_val(dev, reg + 0, val); /* R */ - reg_w_val(dev, reg + 1, val); /* Gr */ - reg_w_val(dev, reg + 2, val); /* B */ - reg_w_val(dev, reg + 3, val); /* Gb */ -} - -static void setwhite(struct gspca_dev *gspca_dev, s32 white, s32 contrast) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; - __u8 blue, red; - __u16 reg; - - /* try to emulate MS-win as possible */ - red = 0x20 + white * 3 / 8; - blue = 0x90 - white * 5 / 8; - if (sd->chip_revision == Rev012A) { - reg = 0x8614; - } else { - reg = 0x8651; - red += contrast - 0x20; - blue += contrast - 0x20; - reg_w_val(dev, 0x8652, contrast + 0x20); /* Gr */ - reg_w_val(dev, 0x8654, contrast + 0x20); /* Gb */ - } - reg_w_val(dev, reg, red); - reg_w_val(dev, reg + 2, blue); -} - -/* rev 12a only */ -static void setexposure(struct gspca_dev *gspca_dev, s32 val) -{ - int i, expo = 0; - - /* Register 0x8309 controls exposure for the spca561, - the basic exposure setting goes from 1-2047, where 1 is completely - dark and 2047 is very bright. It not only influences exposure but - also the framerate (to allow for longer exposure) from 1 - 300 it - only raises the exposure time then from 300 - 600 it halves the - framerate to be able to further raise the exposure time and for every - 300 more it halves the framerate again. This allows for a maximum - exposure time of circa 0.2 - 0.25 seconds (30 / (2000/3000) fps). - Sometimes this is not enough, the 1-2047 uses bits 0-10, bits 11-12 - configure a divider for the base framerate which us used at the - exposure setting of 1-300. These bits configure the base framerate - according to the following formula: fps = 60 / (value + 2) */ - - /* We choose to use the high bits setting the fixed framerate divisor - asap, as setting high basic exposure setting without the fixed - divider in combination with high gains makes the cam stop */ - int table[] = { 0, 450, 550, 625, EXPOSURE_MAX }; - - for (i = 0; i < ARRAY_SIZE(table) - 1; i++) { - if (val <= table[i + 1]) { - expo = val - table[i]; - if (i) - expo += 300; - expo |= i << 11; - break; - } - } - - gspca_dev->usb_buf[0] = expo; - gspca_dev->usb_buf[1] = expo >> 8; - reg_w_buf(gspca_dev, 0x8309, 2); -} - -/* rev 12a only */ -static void setgain(struct gspca_dev *gspca_dev, s32 val) -{ - /* gain reg low 6 bits 0-63 gain, bit 6 and 7, both double the - sensitivity when set, so 31 + one of them set == 63, and 15 - with both of them set == 63 */ - if (val < 64) - gspca_dev->usb_buf[0] = val; - else if (val < 128) - gspca_dev->usb_buf[0] = (val / 2) | 0x40; - else - gspca_dev->usb_buf[0] = (val / 4) | 0xc0; - - gspca_dev->usb_buf[1] = 0; - reg_w_buf(gspca_dev, 0x8335, 2); -} - -static void setautogain(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (val) - sd->ag_cnt = AG_CNT_START; - else - sd->ag_cnt = -1; -} - -static int sd_start_12a(struct gspca_dev *gspca_dev) -{ - struct usb_device *dev = gspca_dev->dev; - int mode; - static const __u8 Reg8391[8] = - {0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00}; - - mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; - if (mode <= 1) { - /* Use compression on 320x240 and above */ - reg_w_val(dev, 0x8500, 0x10 | mode); - } else { - /* I couldn't get the compression to work below 320x240 - * Fortunately at these resolutions the bandwidth - * is sufficient to push raw frames at ~20fps */ - reg_w_val(dev, 0x8500, mode); - } /* -- qq@kuku.eu.org */ - - gspca_dev->usb_buf[0] = 0xaa; - gspca_dev->usb_buf[1] = 0x00; - reg_w_buf(gspca_dev, 0x8307, 2); - /* clock - lower 0x8X values lead to fps > 30 */ - reg_w_val(gspca_dev->dev, 0x8700, 0x8a); - /* 0x8f 0x85 0x27 clock */ - reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20); - reg_w_val(gspca_dev->dev, 0x850b, 0x03); - memcpy(gspca_dev->usb_buf, Reg8391, 8); - reg_w_buf(gspca_dev, 0x8391, 8); - reg_w_buf(gspca_dev, 0x8390, 8); - - /* Led ON (bit 3 -> 0 */ - reg_w_val(gspca_dev->dev, 0x8114, 0x00); - return 0; -} -static int sd_start_72a(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; - int Clck; - int mode; - - write_vector(gspca_dev, rev72a_reset); - msleep(200); - write_vector(gspca_dev, rev72a_init_data1); - write_sensor_72a(gspca_dev, rev72a_init_sensor1); - - mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; - switch (mode) { - default: - case 0: - Clck = 0x27; /* ms-win 0x87 */ - break; - case 1: - Clck = 0x25; - break; - case 2: - Clck = 0x22; - break; - case 3: - Clck = 0x21; - break; - } - reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */ - reg_w_val(dev, 0x8702, 0x81); - reg_w_val(dev, 0x8500, mode); /* mode */ - write_sensor_72a(gspca_dev, rev72a_init_sensor2); - setwhite(gspca_dev, v4l2_ctrl_g_ctrl(sd->hue), - v4l2_ctrl_g_ctrl(sd->contrast)); -/* setbrightness(gspca_dev); * fixme: bad values */ - setautogain(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain)); - reg_w_val(dev, 0x8112, 0x10 | 0x20); - return 0; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->chip_revision == Rev012A) { - reg_w_val(gspca_dev->dev, 0x8112, 0x0e); - /* Led Off (bit 3 -> 1 */ - reg_w_val(gspca_dev->dev, 0x8114, 0x08); - } else { - reg_w_val(gspca_dev->dev, 0x8112, 0x20); -/* reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */ - } -} - -static void do_autogain(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int expotimes; - int pixelclk; - int gainG; - __u8 R, Gr, Gb, B; - int y; - __u8 luma_mean = 110; - __u8 luma_delta = 20; - __u8 spring = 4; - - if (sd->ag_cnt < 0) - return; - if (--sd->ag_cnt >= 0) - return; - sd->ag_cnt = AG_CNT_START; - - switch (sd->chip_revision) { - case Rev072A: - reg_r(gspca_dev, 0x8621, 1); - Gr = gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8622, 1); - R = gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8623, 1); - B = gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8624, 1); - Gb = gspca_dev->usb_buf[0]; - y = (77 * R + 75 * (Gr + Gb) + 29 * B) >> 8; - /* u= (128*B-(43*(Gr+Gb+R))) >> 8; */ - /* v= (128*R-(53*(Gr+Gb))-21*B) >> 8; */ - /* PDEBUG(D_CONF,"reading Y %d U %d V %d ",y,u,v); */ - - if (y < luma_mean - luma_delta || - y > luma_mean + luma_delta) { - expotimes = i2c_read(gspca_dev, 0x09, 0x10); - pixelclk = 0x0800; - expotimes = expotimes & 0x07ff; - /* PDEBUG(D_PACK, - "Exposition Times 0x%03X Clock 0x%04X ", - expotimes,pixelclk); */ - gainG = i2c_read(gspca_dev, 0x35, 0x10); - /* PDEBUG(D_PACK, - "reading Gain register %d", gainG); */ - - expotimes += (luma_mean - y) >> spring; - gainG += (luma_mean - y) / 50; - /* PDEBUG(D_PACK, - "compute expotimes %d gain %d", - expotimes,gainG); */ - - if (gainG > 0x3f) - gainG = 0x3f; - else if (gainG < 3) - gainG = 3; - i2c_write(gspca_dev, gainG, 0x35); - - if (expotimes > 0x0256) - expotimes = 0x0256; - else if (expotimes < 3) - expotimes = 3; - i2c_write(gspca_dev, expotimes | pixelclk, 0x09); - } - break; - } -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - - len--; - switch (*data++) { /* sequence number */ - case 0: /* start of frame */ - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - - /* This should never happen */ - if (len < 2) { - PDEBUG(D_ERR, "Short SOF packet, ignoring"); - gspca_dev->last_packet_type = DISCARD_PACKET; - return; - } - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - if (data[0] & 0x20) { - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); - input_sync(gspca_dev->input_dev); - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); - input_sync(gspca_dev->input_dev); - } -#endif - - if (data[1] & 0x10) { - /* compressed bayer */ - gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); - } else { - /* raw bayer (with a header, which we skip) */ - if (sd->chip_revision == Rev012A) { - data += 20; - len -= 20; - } else { - data += 16; - len -= 16; - } - gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); - } - return; - case 0xff: /* drop (empty mpackets) */ - return; - } - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_CONTRAST: - /* hue/contrast control cluster for 72a */ - setwhite(gspca_dev, sd->hue->val, ctrl->val); - break; - case V4L2_CID_HUE: - /* just plain hue control for 12a */ - setwhite(gspca_dev, ctrl->val, 0); - break; - case V4L2_CID_EXPOSURE: - setexposure(gspca_dev, ctrl->val); - break; - case V4L2_CID_GAIN: - setgain(gspca_dev, ctrl->val); - break; - case V4L2_CID_AUTOGAIN: - setautogain(gspca_dev, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls_12a(struct gspca_dev *gspca_dev) -{ - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 3); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_HUE, 1, 0x7f, 1, 0x40); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, 1, EXPOSURE_MAX, 1, 700); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 255, 1, 63); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -static int sd_init_controls_72a(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 4); - sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 0x3f, 1, 0x20); - sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_HUE, 1, 0x7f, 1, 0x40); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 0x3f, 1, 0x20); - sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - v4l2_ctrl_cluster(2, &sd->contrast); - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc_12a = { - .name = MODULE_NAME, - .init_controls = sd_init_controls_12a, - .config = sd_config, - .init = sd_init_12a, - .start = sd_start_12a, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .other_input = 1, -#endif -}; -static const struct sd_desc sd_desc_72a = { - .name = MODULE_NAME, - .init_controls = sd_init_controls_72a, - .config = sd_config, - .init = sd_init_72a, - .start = sd_start_72a, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, - .dq_callback = do_autogain, -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .other_input = 1, -#endif -}; -static const struct sd_desc *sd_desc[2] = { - &sd_desc_12a, - &sd_desc_72a -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A}, - {USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A}, - {USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A}, - {USB_DEVICE(0x0461, 0x0815), .driver_info = Rev072A}, - {USB_DEVICE(0x046d, 0x0928), .driver_info = Rev012A}, - {USB_DEVICE(0x046d, 0x0929), .driver_info = Rev012A}, - {USB_DEVICE(0x046d, 0x092a), .driver_info = Rev012A}, - {USB_DEVICE(0x046d, 0x092b), .driver_info = Rev012A}, - {USB_DEVICE(0x046d, 0x092c), .driver_info = Rev012A}, - {USB_DEVICE(0x046d, 0x092d), .driver_info = Rev012A}, - {USB_DEVICE(0x046d, 0x092e), .driver_info = Rev012A}, - {USB_DEVICE(0x046d, 0x092f), .driver_info = Rev012A}, - {USB_DEVICE(0x04fc, 0x0561), .driver_info = Rev072A}, - {USB_DEVICE(0x060b, 0xa001), .driver_info = Rev072A}, - {USB_DEVICE(0x10fd, 0x7e50), .driver_info = Rev072A}, - {USB_DEVICE(0xabcd, 0xcdee), .driver_info = Rev072A}, - {} -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, - sd_desc[id->driver_info], - sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c deleted file mode 100644 index a8ac97931ad6..000000000000 --- a/drivers/media/video/gspca/sq905.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * SQ905 subdriver - * - * Copyright (C) 2008, 2009 Adam Baker and Theodore Kilgore - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * History and Acknowledgments - * - * The original Linux driver for SQ905 based cameras was written by - * Marcell Lengyel and furter developed by many other contributors - * and is available from http://sourceforge.net/projects/sqcam/ - * - * This driver takes advantage of the reverse engineering work done for - * that driver and for libgphoto2 but shares no code with them. - * - * This driver has used as a base the finepix driver and other gspca - * based drivers and may still contain code fragments taken from those - * drivers. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "sq905" - -#include <linux/workqueue.h> -#include <linux/slab.h> -#include "gspca.h" - -MODULE_AUTHOR("Adam Baker <linux@baker-net.org.uk>, " - "Theodore Kilgore <kilgota@auburn.edu>"); -MODULE_DESCRIPTION("GSPCA/SQ905 USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* Default timeouts, in ms */ -#define SQ905_CMD_TIMEOUT 500 -#define SQ905_DATA_TIMEOUT 1000 - -/* Maximum transfer size to use. */ -#define SQ905_MAX_TRANSFER 0x8000 -#define FRAME_HEADER_LEN 64 - -/* The known modes, or registers. These go in the "value" slot. */ - -/* 00 is "none" obviously */ - -#define SQ905_BULK_READ 0x03 /* precedes any bulk read */ -#define SQ905_COMMAND 0x06 /* precedes the command codes below */ -#define SQ905_PING 0x07 /* when reading an "idling" command */ -#define SQ905_READ_DONE 0xc0 /* ack bulk read completed */ - -/* Any non-zero value in the bottom 2 bits of the 2nd byte of - * the ID appears to indicate the camera can do 640*480. If the - * LSB of that byte is set the image is just upside down, otherwise - * it is rotated 180 degrees. */ -#define SQ905_HIRES_MASK 0x00000300 -#define SQ905_ORIENTATION_MASK 0x00000100 - -/* Some command codes. These go in the "index" slot. */ - -#define SQ905_ID 0xf0 /* asks for model string */ -#define SQ905_CONFIG 0x20 /* gets photo alloc. table, not used here */ -#define SQ905_DATA 0x30 /* accesses photo data, not used here */ -#define SQ905_CLEAR 0xa0 /* clear everything */ -#define SQ905_CAPTURE_LOW 0x60 /* Starts capture at 160x120 */ -#define SQ905_CAPTURE_MED 0x61 /* Starts capture at 320x240 */ -#define SQ905_CAPTURE_HIGH 0x62 /* Starts capture at 640x480 (some cams only) */ -/* note that the capture command also controls the output dimensions */ - -/* Structure to hold all of our device specific stuff */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - /* - * Driver stuff - */ - struct work_struct work_struct; - struct workqueue_struct *work_thread; -}; - -static struct v4l2_pix_format sq905_mode[] = { - { 160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, - { 320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, - { 640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0} -}; - -/* - * Send a command to the camera. - */ -static int sq905_command(struct gspca_dev *gspca_dev, u16 index) -{ - int ret; - - gspca_dev->usb_buf[0] = '\0'; - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - USB_REQ_SYNCH_FRAME, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - SQ905_COMMAND, index, gspca_dev->usb_buf, 1, - SQ905_CMD_TIMEOUT); - if (ret < 0) { - pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret); - return ret; - } - - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - USB_REQ_SYNCH_FRAME, /* request */ - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - SQ905_PING, 0, gspca_dev->usb_buf, 1, - SQ905_CMD_TIMEOUT); - if (ret < 0) { - pr_err("%s: usb_control_msg failed 2 (%d)\n", __func__, ret); - return ret; - } - - return 0; -} - -/* - * Acknowledge the end of a frame - see warning on sq905_command. - */ -static int sq905_ack_frame(struct gspca_dev *gspca_dev) -{ - int ret; - - gspca_dev->usb_buf[0] = '\0'; - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - USB_REQ_SYNCH_FRAME, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - SQ905_READ_DONE, 0, gspca_dev->usb_buf, 1, - SQ905_CMD_TIMEOUT); - if (ret < 0) { - pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret); - return ret; - } - - return 0; -} - -/* - * request and read a block of data - see warning on sq905_command. - */ -static int -sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock) -{ - int ret; - int act_len; - - gspca_dev->usb_buf[0] = '\0'; - if (need_lock) - mutex_lock(&gspca_dev->usb_lock); - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - USB_REQ_SYNCH_FRAME, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - SQ905_BULK_READ, size, gspca_dev->usb_buf, - 1, SQ905_CMD_TIMEOUT); - if (need_lock) - mutex_unlock(&gspca_dev->usb_lock); - if (ret < 0) { - pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret); - return ret; - } - ret = usb_bulk_msg(gspca_dev->dev, - usb_rcvbulkpipe(gspca_dev->dev, 0x81), - data, size, &act_len, SQ905_DATA_TIMEOUT); - - /* successful, it returns 0, otherwise negative */ - if (ret < 0 || act_len != size) { - pr_err("bulk read fail (%d) len %d/%d\n", ret, act_len, size); - return -EIO; - } - return 0; -} - -/* This function is called as a workqueue function and runs whenever the camera - * is streaming data. Because it is a workqueue function it is allowed to sleep - * so we can use synchronous USB calls. To avoid possible collisions with other - * threads attempting to use the camera's USB interface we take the gspca - * usb_lock when performing USB operations. In practice the only thing we need - * to protect against is the usb_set_interface call that gspca makes during - * stream_off as the camera doesn't provide any controls that the user could try - * to change. - */ -static void sq905_dostream(struct work_struct *work) -{ - struct sd *dev = container_of(work, struct sd, work_struct); - struct gspca_dev *gspca_dev = &dev->gspca_dev; - int bytes_left; /* bytes remaining in current frame. */ - int data_len; /* size to use for the next read. */ - int header_read; /* true if we have already read the frame header. */ - int packet_type; - int frame_sz; - int ret; - u8 *data; - u8 *buffer; - - buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); - if (!buffer) { - pr_err("Couldn't allocate USB buffer\n"); - goto quit_stream; - } - - frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage - + FRAME_HEADER_LEN; - - while (gspca_dev->dev && gspca_dev->streaming) { -#ifdef CONFIG_PM - if (gspca_dev->frozen) - break; -#endif - /* request some data and then read it until we have - * a complete frame. */ - bytes_left = frame_sz; - header_read = 0; - - /* Note we do not check for gspca_dev->streaming here, as - we must finish reading an entire frame, otherwise the - next time we stream we start reading in the middle of a - frame. */ - while (bytes_left > 0 && gspca_dev->dev) { - data_len = bytes_left > SQ905_MAX_TRANSFER ? - SQ905_MAX_TRANSFER : bytes_left; - ret = sq905_read_data(gspca_dev, buffer, data_len, 1); - if (ret < 0) - goto quit_stream; - PDEBUG(D_PACK, - "Got %d bytes out of %d for frame", - data_len, bytes_left); - bytes_left -= data_len; - data = buffer; - if (!header_read) { - packet_type = FIRST_PACKET; - /* The first 64 bytes of each frame are - * a header full of FF 00 bytes */ - data += FRAME_HEADER_LEN; - data_len -= FRAME_HEADER_LEN; - header_read = 1; - } else if (bytes_left == 0) { - packet_type = LAST_PACKET; - } else { - packet_type = INTER_PACKET; - } - gspca_frame_add(gspca_dev, packet_type, - data, data_len); - /* If entire frame fits in one packet we still - need to add a LAST_PACKET */ - if (packet_type == FIRST_PACKET && - bytes_left == 0) - gspca_frame_add(gspca_dev, LAST_PACKET, - NULL, 0); - } - if (gspca_dev->dev) { - /* acknowledge the frame */ - mutex_lock(&gspca_dev->usb_lock); - ret = sq905_ack_frame(gspca_dev); - mutex_unlock(&gspca_dev->usb_lock); - if (ret < 0) - goto quit_stream; - } - } -quit_stream: - if (gspca_dev->dev) { - mutex_lock(&gspca_dev->usb_lock); - sq905_command(gspca_dev, SQ905_CLEAR); - mutex_unlock(&gspca_dev->usb_lock); - } - kfree(buffer); -} - -/* This function is called at probe time just before sd_init */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct cam *cam = &gspca_dev->cam; - struct sd *dev = (struct sd *) gspca_dev; - - /* We don't use the buffer gspca allocates so make it small. */ - cam->bulk = 1; - cam->bulk_size = 64; - - INIT_WORK(&dev->work_struct, sq905_dostream); - - return 0; -} - -/* called on streamoff with alt==0 and on disconnect */ -/* the usb_lock is held at entry - restore on exit */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct sd *dev = (struct sd *) gspca_dev; - - /* wait for the work queue to terminate */ - mutex_unlock(&gspca_dev->usb_lock); - /* This waits for sq905_dostream to finish */ - destroy_workqueue(dev->work_thread); - dev->work_thread = NULL; - mutex_lock(&gspca_dev->usb_lock); -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - u32 ident; - int ret; - - /* connect to the camera and read - * the model ID and process that and put it away. - */ - ret = sq905_command(gspca_dev, SQ905_CLEAR); - if (ret < 0) - return ret; - ret = sq905_command(gspca_dev, SQ905_ID); - if (ret < 0) - return ret; - ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4, 0); - if (ret < 0) - return ret; - /* usb_buf is allocated with kmalloc so is aligned. - * Camera model number is the right way round if we assume this - * reverse engineered ID is supposed to be big endian. */ - ident = be32_to_cpup((__be32 *)gspca_dev->usb_buf); - ret = sq905_command(gspca_dev, SQ905_CLEAR); - if (ret < 0) - return ret; - PDEBUG(D_CONF, "SQ905 camera ID %08x detected", ident); - gspca_dev->cam.cam_mode = sq905_mode; - gspca_dev->cam.nmodes = ARRAY_SIZE(sq905_mode); - if (!(ident & SQ905_HIRES_MASK)) - gspca_dev->cam.nmodes--; - - if (ident & SQ905_ORIENTATION_MASK) - gspca_dev->cam.input_flags = V4L2_IN_ST_VFLIP; - else - gspca_dev->cam.input_flags = V4L2_IN_ST_VFLIP | - V4L2_IN_ST_HFLIP; - return 0; -} - -/* Set up for getting frames. */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *dev = (struct sd *) gspca_dev; - int ret; - - /* "Open the shutter" and set size, to start capture */ - switch (gspca_dev->curr_mode) { - default: -/* case 2: */ - PDEBUG(D_STREAM, "Start streaming at high resolution"); - ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_HIGH); - break; - case 1: - PDEBUG(D_STREAM, "Start streaming at medium resolution"); - ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_MED); - break; - case 0: - PDEBUG(D_STREAM, "Start streaming at low resolution"); - ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_LOW); - } - - if (ret < 0) { - PDEBUG(D_ERR, "Start streaming command failed"); - return ret; - } - /* Start the workqueue function to do the streaming */ - dev->work_thread = create_singlethread_workqueue(MODULE_NAME); - queue_work(dev->work_thread, &dev->work_struct); - - return 0; -} - -/* Table of supported USB devices */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x2770, 0x9120)}, - {} -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .start = sd_start, - .stop0 = sd_stop0, -}; - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, - &sd_desc, - sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c deleted file mode 100644 index 70fae6982e96..000000000000 --- a/drivers/media/video/gspca/sq905c.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * SQ905C subdriver - * - * Copyright (C) 2009 Theodore Kilgore - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * - * This driver uses work done in - * libgphoto2/camlibs/digigr8, Copyright (C) Theodore Kilgore. - * - * This driver has also used as a base the sq905c driver - * and may contain code fragments from it. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "sq905c" - -#include <linux/workqueue.h> -#include <linux/slab.h> -#include "gspca.h" - -MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>"); -MODULE_DESCRIPTION("GSPCA/SQ905C USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* Default timeouts, in ms */ -#define SQ905C_CMD_TIMEOUT 500 -#define SQ905C_DATA_TIMEOUT 1000 - -/* Maximum transfer size to use. */ -#define SQ905C_MAX_TRANSFER 0x8000 - -#define FRAME_HEADER_LEN 0x50 - -/* Commands. These go in the "value" slot. */ -#define SQ905C_CLEAR 0xa0 /* clear everything */ -#define SQ905C_GET_ID 0x14f4 /* Read version number */ -#define SQ905C_CAPTURE_LOW 0xa040 /* Starts capture at 160x120 */ -#define SQ905C_CAPTURE_MED 0x1440 /* Starts capture at 320x240 */ -#define SQ905C_CAPTURE_HI 0x2840 /* Starts capture at 320x240 */ - -/* For capture, this must go in the "index" slot. */ -#define SQ905C_CAPTURE_INDEX 0x110f - -/* Structure to hold all of our device specific stuff */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - const struct v4l2_pix_format *cap_mode; - /* Driver stuff */ - struct work_struct work_struct; - struct workqueue_struct *work_thread; -}; - -/* - * Most of these cameras will do 640x480 and 320x240. 160x120 works - * in theory but gives very poor output. Therefore, not supported. - * The 0x2770:0x9050 cameras have max resolution of 320x240. - */ -static struct v4l2_pix_format sq905c_mode[] = { - { 320, 240, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, - { 640, 480, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0} -}; - -/* Send a command to the camera. */ -static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index) -{ - int ret; - - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - USB_REQ_SYNCH_FRAME, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - command, index, NULL, 0, - SQ905C_CMD_TIMEOUT); - if (ret < 0) { - pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret); - return ret; - } - - return 0; -} - -static int sq905c_read(struct gspca_dev *gspca_dev, u16 command, u16 index, - int size) -{ - int ret; - - ret = usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - USB_REQ_SYNCH_FRAME, /* request */ - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - command, index, gspca_dev->usb_buf, size, - SQ905C_CMD_TIMEOUT); - if (ret < 0) { - pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret); - return ret; - } - - return 0; -} - -/* This function is called as a workqueue function and runs whenever the camera - * is streaming data. Because it is a workqueue function it is allowed to sleep - * so we can use synchronous USB calls. To avoid possible collisions with other - * threads attempting to use the camera's USB interface the gspca usb_lock is - * used when performing the one USB control operation inside the workqueue, - * which tells the camera to close the stream. In practice the only thing - * which needs to be protected against is the usb_set_interface call that - * gspca makes during stream_off. Otherwise the camera doesn't provide any - * controls that the user could try to change. - */ -static void sq905c_dostream(struct work_struct *work) -{ - struct sd *dev = container_of(work, struct sd, work_struct); - struct gspca_dev *gspca_dev = &dev->gspca_dev; - int bytes_left; /* bytes remaining in current frame. */ - int data_len; /* size to use for the next read. */ - int act_len; - int packet_type; - int ret; - u8 *buffer; - - buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); - if (!buffer) { - pr_err("Couldn't allocate USB buffer\n"); - goto quit_stream; - } - - while (gspca_dev->dev && gspca_dev->streaming) { -#ifdef CONFIG_PM - if (gspca_dev->frozen) - break; -#endif - /* Request the header, which tells the size to download */ - ret = usb_bulk_msg(gspca_dev->dev, - usb_rcvbulkpipe(gspca_dev->dev, 0x81), - buffer, FRAME_HEADER_LEN, &act_len, - SQ905C_DATA_TIMEOUT); - PDEBUG(D_STREAM, - "Got %d bytes out of %d for header", - act_len, FRAME_HEADER_LEN); - if (ret < 0 || act_len < FRAME_HEADER_LEN) - goto quit_stream; - /* size is read from 4 bytes starting 0x40, little endian */ - bytes_left = buffer[0x40]|(buffer[0x41]<<8)|(buffer[0x42]<<16) - |(buffer[0x43]<<24); - PDEBUG(D_STREAM, "bytes_left = 0x%x", bytes_left); - /* We keep the header. It has other information, too. */ - packet_type = FIRST_PACKET; - gspca_frame_add(gspca_dev, packet_type, - buffer, FRAME_HEADER_LEN); - while (bytes_left > 0 && gspca_dev->dev) { - data_len = bytes_left > SQ905C_MAX_TRANSFER ? - SQ905C_MAX_TRANSFER : bytes_left; - ret = usb_bulk_msg(gspca_dev->dev, - usb_rcvbulkpipe(gspca_dev->dev, 0x81), - buffer, data_len, &act_len, - SQ905C_DATA_TIMEOUT); - if (ret < 0 || act_len < data_len) - goto quit_stream; - PDEBUG(D_STREAM, - "Got %d bytes out of %d for frame", - data_len, bytes_left); - bytes_left -= data_len; - if (bytes_left == 0) - packet_type = LAST_PACKET; - else - packet_type = INTER_PACKET; - gspca_frame_add(gspca_dev, packet_type, - buffer, data_len); - } - } -quit_stream: - if (gspca_dev->dev) { - mutex_lock(&gspca_dev->usb_lock); - sq905c_command(gspca_dev, SQ905C_CLEAR, 0); - mutex_unlock(&gspca_dev->usb_lock); - } - kfree(buffer); -} - -/* This function is called at probe time just before sd_init */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct cam *cam = &gspca_dev->cam; - struct sd *dev = (struct sd *) gspca_dev; - int ret; - - PDEBUG(D_PROBE, - "SQ9050 camera detected" - " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); - - ret = sq905c_command(gspca_dev, SQ905C_GET_ID, 0); - if (ret < 0) { - PDEBUG(D_ERR, "Get version command failed"); - return ret; - } - - ret = sq905c_read(gspca_dev, 0xf5, 0, 20); - if (ret < 0) { - PDEBUG(D_ERR, "Reading version command failed"); - return ret; - } - /* Note we leave out the usb id and the manufacturing date */ - PDEBUG(D_PROBE, - "SQ9050 ID string: %02x - %*ph", - gspca_dev->usb_buf[3], 6, gspca_dev->usb_buf + 14); - - cam->cam_mode = sq905c_mode; - cam->nmodes = 2; - if (gspca_dev->usb_buf[15] == 0) - cam->nmodes = 1; - /* We don't use the buffer gspca allocates so make it small. */ - cam->bulk_size = 32; - cam->bulk = 1; - INIT_WORK(&dev->work_struct, sq905c_dostream); - return 0; -} - -/* called on streamoff with alt==0 and on disconnect */ -/* the usb_lock is held at entry - restore on exit */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct sd *dev = (struct sd *) gspca_dev; - - /* wait for the work queue to terminate */ - mutex_unlock(&gspca_dev->usb_lock); - /* This waits for sq905c_dostream to finish */ - destroy_workqueue(dev->work_thread); - dev->work_thread = NULL; - mutex_lock(&gspca_dev->usb_lock); -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - int ret; - - /* connect to the camera and reset it. */ - ret = sq905c_command(gspca_dev, SQ905C_CLEAR, 0); - return ret; -} - -/* Set up for getting frames. */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *dev = (struct sd *) gspca_dev; - int ret; - - dev->cap_mode = gspca_dev->cam.cam_mode; - /* "Open the shutter" and set size, to start capture */ - switch (gspca_dev->width) { - case 640: - PDEBUG(D_STREAM, "Start streaming at high resolution"); - dev->cap_mode++; - ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_HI, - SQ905C_CAPTURE_INDEX); - break; - default: /* 320 */ - PDEBUG(D_STREAM, "Start streaming at medium resolution"); - ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_MED, - SQ905C_CAPTURE_INDEX); - } - - if (ret < 0) { - PDEBUG(D_ERR, "Start streaming command failed"); - return ret; - } - /* Start the workqueue function to do the streaming */ - dev->work_thread = create_singlethread_workqueue(MODULE_NAME); - queue_work(dev->work_thread, &dev->work_struct); - - return 0; -} - -/* Table of supported USB devices */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x2770, 0x905c)}, - {USB_DEVICE(0x2770, 0x9050)}, - {USB_DEVICE(0x2770, 0x9051)}, - {USB_DEVICE(0x2770, 0x9052)}, - {USB_DEVICE(0x2770, 0x913d)}, - {} -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .start = sd_start, - .stop0 = sd_stop0, -}; - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, - &sd_desc, - sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/sq930x.c b/drivers/media/video/gspca/sq930x.c deleted file mode 100644 index 7e8748b31e85..000000000000 --- a/drivers/media/video/gspca/sq930x.c +++ /dev/null @@ -1,1164 +0,0 @@ -/* - * SQ930x subdriver - * - * Copyright (C) 2010 Jean-François Moine <http://moinejf.free.fr> - * Copyright (C) 2006 -2008 Gerard Klaver <gerard at gkall dot hobby dot nl> - * Copyright (C) 2007 Sam Revitch <samr7@cs.washington.edu> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "sq930x" - -#include "gspca.h" - -MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>\n" - "Gerard Klaver <gerard at gkall dot hobby dot nl\n" - "Sam Revitch <samr7@cs.washington.edu>"); -MODULE_DESCRIPTION("GSPCA/SQ930x USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* Structure to hold all of our device specific stuff */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - struct { /* exposure/gain control cluster */ - struct v4l2_ctrl *exposure; - struct v4l2_ctrl *gain; - }; - - u8 do_ctrl; - u8 gpio[2]; - u8 sensor; - u8 type; -#define Generic 0 -#define Creative_live_motion 1 -}; -enum sensors { - SENSOR_ICX098BQ, - SENSOR_LZ24BP, - SENSOR_MI0360, - SENSOR_MT9V111, /* = MI360SOC */ - SENSOR_OV7660, - SENSOR_OV9630, -}; - -static struct v4l2_pix_format vga_mode[] = { - {320, 240, V4L2_PIX_FMT_SRGGB8, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, - {640, 480, V4L2_PIX_FMT_SRGGB8, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, -}; - -/* sq930x registers */ -#define SQ930_CTRL_UCBUS_IO 0x0001 -#define SQ930_CTRL_I2C_IO 0x0002 -#define SQ930_CTRL_GPIO 0x0005 -#define SQ930_CTRL_CAP_START 0x0010 -#define SQ930_CTRL_CAP_STOP 0x0011 -#define SQ930_CTRL_SET_EXPOSURE 0x001d -#define SQ930_CTRL_RESET 0x001e -#define SQ930_CTRL_GET_DEV_INFO 0x001f - -/* gpio 1 (8..15) */ -#define SQ930_GPIO_DFL_I2C_SDA 0x0001 -#define SQ930_GPIO_DFL_I2C_SCL 0x0002 -#define SQ930_GPIO_RSTBAR 0x0004 -#define SQ930_GPIO_EXTRA1 0x0040 -#define SQ930_GPIO_EXTRA2 0x0080 -/* gpio 3 (24..31) */ -#define SQ930_GPIO_POWER 0x0200 -#define SQ930_GPIO_DFL_LED 0x1000 - -struct ucbus_write_cmd { - u16 bw_addr; - u8 bw_data; -}; -struct i2c_write_cmd { - u8 reg; - u16 val; -}; - -static const struct ucbus_write_cmd icx098bq_start_0[] = { - {0x0354, 0x00}, {0x03fa, 0x00}, {0xf800, 0x02}, {0xf801, 0xce}, - {0xf802, 0xc1}, {0xf804, 0x00}, {0xf808, 0x00}, {0xf809, 0x0e}, - {0xf80a, 0x01}, {0xf80b, 0xee}, {0xf807, 0x60}, {0xf80c, 0x02}, - {0xf80d, 0xf0}, {0xf80e, 0x03}, {0xf80f, 0x0a}, {0xf81c, 0x02}, - {0xf81d, 0xf0}, {0xf81e, 0x03}, {0xf81f, 0x0a}, {0xf83a, 0x00}, - {0xf83b, 0x10}, {0xf83c, 0x00}, {0xf83d, 0x4e}, {0xf810, 0x04}, - {0xf811, 0x00}, {0xf812, 0x02}, {0xf813, 0x10}, {0xf803, 0x00}, - {0xf814, 0x01}, {0xf815, 0x18}, {0xf816, 0x00}, {0xf817, 0x48}, - {0xf818, 0x00}, {0xf819, 0x25}, {0xf81a, 0x00}, {0xf81b, 0x3c}, - {0xf82f, 0x03}, {0xf820, 0xff}, {0xf821, 0x0d}, {0xf822, 0xff}, - {0xf823, 0x07}, {0xf824, 0xff}, {0xf825, 0x03}, {0xf826, 0xff}, - {0xf827, 0x06}, {0xf828, 0xff}, {0xf829, 0x03}, {0xf82a, 0xff}, - {0xf82b, 0x0c}, {0xf82c, 0xfd}, {0xf82d, 0x01}, {0xf82e, 0x00}, - {0xf830, 0x00}, {0xf831, 0x47}, {0xf832, 0x00}, {0xf833, 0x00}, - {0xf850, 0x00}, {0xf851, 0x00}, {0xf852, 0x00}, {0xf853, 0x24}, - {0xf854, 0x00}, {0xf855, 0x18}, {0xf856, 0x00}, {0xf857, 0x3c}, - {0xf858, 0x00}, {0xf859, 0x0c}, {0xf85a, 0x00}, {0xf85b, 0x30}, - {0xf85c, 0x00}, {0xf85d, 0x0c}, {0xf85e, 0x00}, {0xf85f, 0x30}, - {0xf860, 0x00}, {0xf861, 0x48}, {0xf862, 0x01}, {0xf863, 0xdc}, - {0xf864, 0xff}, {0xf865, 0x98}, {0xf866, 0xff}, {0xf867, 0xc0}, - {0xf868, 0xff}, {0xf869, 0x70}, {0xf86c, 0xff}, {0xf86d, 0x00}, - {0xf86a, 0xff}, {0xf86b, 0x48}, {0xf86e, 0xff}, {0xf86f, 0x00}, - {0xf870, 0x01}, {0xf871, 0xdb}, {0xf872, 0x01}, {0xf873, 0xfa}, - {0xf874, 0x01}, {0xf875, 0xdb}, {0xf876, 0x01}, {0xf877, 0xfa}, - {0xf878, 0x0f}, {0xf879, 0x0f}, {0xf87a, 0xff}, {0xf87b, 0xff}, - {0xf800, 0x03} -}; -static const struct ucbus_write_cmd icx098bq_start_1[] = { - {0xf5f0, 0x00}, {0xf5f1, 0xcd}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, - {0xf5f4, 0xc0}, - {0xf5f0, 0x49}, {0xf5f1, 0xcd}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, - {0xf5f4, 0xc0}, - {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00}, - {0xf5f9, 0x00} -}; - -static const struct ucbus_write_cmd icx098bq_start_2[] = { - {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x82}, {0xf806, 0x00}, - {0xf807, 0x7f}, {0xf800, 0x03}, - {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x40}, {0xf806, 0x00}, - {0xf807, 0x7f}, {0xf800, 0x03}, - {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0xcf}, {0xf806, 0xd0}, - {0xf807, 0x7f}, {0xf800, 0x03}, - {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x00}, {0xf806, 0x00}, - {0xf807, 0x7f}, {0xf800, 0x03} -}; - -static const struct ucbus_write_cmd lz24bp_start_0[] = { - {0x0354, 0x00}, {0x03fa, 0x00}, {0xf800, 0x02}, {0xf801, 0xbe}, - {0xf802, 0xc6}, {0xf804, 0x00}, {0xf808, 0x00}, {0xf809, 0x06}, - {0xf80a, 0x01}, {0xf80b, 0xfe}, {0xf807, 0x84}, {0xf80c, 0x02}, - {0xf80d, 0xf7}, {0xf80e, 0x03}, {0xf80f, 0x0b}, {0xf81c, 0x00}, - {0xf81d, 0x49}, {0xf81e, 0x03}, {0xf81f, 0x0b}, {0xf83a, 0x00}, - {0xf83b, 0x01}, {0xf83c, 0x00}, {0xf83d, 0x6b}, {0xf810, 0x03}, - {0xf811, 0x10}, {0xf812, 0x02}, {0xf813, 0x6f}, {0xf803, 0x00}, - {0xf814, 0x00}, {0xf815, 0x44}, {0xf816, 0x00}, {0xf817, 0x48}, - {0xf818, 0x00}, {0xf819, 0x25}, {0xf81a, 0x00}, {0xf81b, 0x3c}, - {0xf82f, 0x03}, {0xf820, 0xff}, {0xf821, 0x0d}, {0xf822, 0xff}, - {0xf823, 0x07}, {0xf824, 0xfd}, {0xf825, 0x07}, {0xf826, 0xf0}, - {0xf827, 0x0c}, {0xf828, 0xff}, {0xf829, 0x03}, {0xf82a, 0xff}, - {0xf82b, 0x0c}, {0xf82c, 0xfc}, {0xf82d, 0x01}, {0xf82e, 0x00}, - {0xf830, 0x00}, {0xf831, 0x47}, {0xf832, 0x00}, {0xf833, 0x00}, - {0xf850, 0x00}, {0xf851, 0x00}, {0xf852, 0x00}, {0xf853, 0x24}, - {0xf854, 0x00}, {0xf855, 0x0c}, {0xf856, 0x00}, {0xf857, 0x30}, - {0xf858, 0x00}, {0xf859, 0x18}, {0xf85a, 0x00}, {0xf85b, 0x3c}, - {0xf85c, 0x00}, {0xf85d, 0x18}, {0xf85e, 0x00}, {0xf85f, 0x3c}, - {0xf860, 0xff}, {0xf861, 0x37}, {0xf862, 0xff}, {0xf863, 0x1d}, - {0xf864, 0xff}, {0xf865, 0x98}, {0xf866, 0xff}, {0xf867, 0xc0}, - {0xf868, 0x00}, {0xf869, 0x37}, {0xf86c, 0x02}, {0xf86d, 0x1d}, - {0xf86a, 0x00}, {0xf86b, 0x37}, {0xf86e, 0x02}, {0xf86f, 0x1d}, - {0xf870, 0x01}, {0xf871, 0xc6}, {0xf872, 0x02}, {0xf873, 0x04}, - {0xf874, 0x01}, {0xf875, 0xc6}, {0xf876, 0x02}, {0xf877, 0x04}, - {0xf878, 0x0f}, {0xf879, 0x0f}, {0xf87a, 0xff}, {0xf87b, 0xff}, - {0xf800, 0x03} -}; -static const struct ucbus_write_cmd lz24bp_start_1_gen[] = { - {0xf5f0, 0x00}, {0xf5f1, 0xff}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, - {0xf5f4, 0xb3}, - {0xf5f0, 0x40}, {0xf5f1, 0xff}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, - {0xf5f4, 0xb3}, - {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00}, - {0xf5f9, 0x00} -}; - -static const struct ucbus_write_cmd lz24bp_start_1_clm[] = { - {0xf5f0, 0x00}, {0xf5f1, 0xff}, {0xf5f2, 0x88}, {0xf5f3, 0x88}, - {0xf5f4, 0xc0}, - {0xf5f0, 0x40}, {0xf5f1, 0xff}, {0xf5f2, 0x88}, {0xf5f3, 0x88}, - {0xf5f4, 0xc0}, - {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00}, - {0xf5f9, 0x00} -}; - -static const struct ucbus_write_cmd lz24bp_start_2[] = { - {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x80}, {0xf806, 0x00}, - {0xf807, 0x7f}, {0xf800, 0x03}, - {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x4e}, {0xf806, 0x00}, - {0xf807, 0x7f}, {0xf800, 0x03}, - {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0xc0}, {0xf806, 0x48}, - {0xf807, 0x7f}, {0xf800, 0x03}, - {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x00}, {0xf806, 0x00}, - {0xf807, 0x7f}, {0xf800, 0x03} -}; - -static const struct ucbus_write_cmd mi0360_start_0[] = { - {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0xcc}, {0xf333, 0xcc}, - {0xf334, 0xcc}, {0xf335, 0xcc}, {0xf33f, 0x00} -}; -static const struct i2c_write_cmd mi0360_init_23[] = { - {0x30, 0x0040}, /* reserved - def 0x0005 */ - {0x31, 0x0000}, /* reserved - def 0x002a */ - {0x34, 0x0100}, /* reserved - def 0x0100 */ - {0x3d, 0x068f}, /* reserved - def 0x068f */ -}; -static const struct i2c_write_cmd mi0360_init_24[] = { - {0x03, 0x01e5}, /* window height */ - {0x04, 0x0285}, /* window width */ -}; -static const struct i2c_write_cmd mi0360_init_25[] = { - {0x35, 0x0020}, /* global gain */ - {0x2b, 0x0020}, /* green1 gain */ - {0x2c, 0x002a}, /* blue gain */ - {0x2d, 0x0028}, /* red gain */ - {0x2e, 0x0020}, /* green2 gain */ -}; -static const struct ucbus_write_cmd mi0360_start_1[] = { - {0xf5f0, 0x11}, {0xf5f1, 0x99}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, - {0xf5f4, 0xa6}, - {0xf5f0, 0x51}, {0xf5f1, 0x99}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, - {0xf5f4, 0xa6}, - {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00}, - {0xf5f9, 0x00} -}; -static const struct i2c_write_cmd mi0360_start_2[] = { - {0x62, 0x041d}, /* reserved - def 0x0418 */ -}; -static const struct i2c_write_cmd mi0360_start_3[] = { - {0x05, 0x007b}, /* horiz blanking */ -}; -static const struct i2c_write_cmd mi0360_start_4[] = { - {0x05, 0x03f5}, /* horiz blanking */ -}; - -static const struct i2c_write_cmd mt9v111_init_0[] = { - {0x01, 0x0001}, /* select IFP/SOC registers */ - {0x06, 0x300c}, /* operating mode control */ - {0x08, 0xcc00}, /* output format control (RGB) */ - {0x01, 0x0004}, /* select sensor core registers */ -}; -static const struct i2c_write_cmd mt9v111_init_1[] = { - {0x03, 0x01e5}, /* window height */ - {0x04, 0x0285}, /* window width */ -}; -static const struct i2c_write_cmd mt9v111_init_2[] = { - {0x30, 0x7800}, - {0x31, 0x0000}, - {0x07, 0x3002}, /* output control */ - {0x35, 0x0020}, /* global gain */ - {0x2b, 0x0020}, /* green1 gain */ - {0x2c, 0x0020}, /* blue gain */ - {0x2d, 0x0020}, /* red gain */ - {0x2e, 0x0020}, /* green2 gain */ -}; -static const struct ucbus_write_cmd mt9v111_start_1[] = { - {0xf5f0, 0x11}, {0xf5f1, 0x96}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, - {0xf5f4, 0xaa}, - {0xf5f0, 0x51}, {0xf5f1, 0x96}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, - {0xf5f4, 0xaa}, - {0xf5fa, 0x00}, {0xf5f6, 0x0a}, {0xf5f7, 0x0a}, {0xf5f8, 0x0a}, - {0xf5f9, 0x0a} -}; -static const struct i2c_write_cmd mt9v111_init_3[] = { - {0x62, 0x0405}, -}; -static const struct i2c_write_cmd mt9v111_init_4[] = { -/* {0x05, 0x00ce}, */ - {0x05, 0x005d}, /* horizontal blanking */ -}; - -static const struct ucbus_write_cmd ov7660_start_0[] = { - {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0x00}, {0xf333, 0xc0}, - {0xf334, 0x39}, {0xf335, 0xe7}, {0xf33f, 0x03} -}; - -static const struct ucbus_write_cmd ov9630_start_0[] = { - {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0x00}, {0xf333, 0x00}, - {0xf334, 0x3e}, {0xf335, 0xf8}, {0xf33f, 0x03} -}; - -/* start parameters indexed by [sensor][mode] */ -static const struct cap_s { - u8 cc_sizeid; - u8 cc_bytes[32]; -} capconfig[4][2] = { - [SENSOR_ICX098BQ] = { - {2, /* Bayer 320x240 */ - {0x05, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee, - 0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, - {4, /* Bayer 640x480 */ - {0x01, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee, - 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, - }, - [SENSOR_LZ24BP] = { - {2, /* Bayer 320x240 */ - {0x05, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee, - 0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, - {4, /* Bayer 640x480 */ - {0x01, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee, - 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, - }, - [SENSOR_MI0360] = { - {2, /* Bayer 320x240 */ - {0x05, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1, - 0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, - {4, /* Bayer 640x480 */ - {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1, - 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, - }, - [SENSOR_MT9V111] = { - {2, /* Bayer 320x240 */ - {0x05, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1, - 0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, - {4, /* Bayer 640x480 */ - {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1, - 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, - }, -}; - -struct sensor_s { - const char *name; - u8 i2c_addr; - u8 i2c_dum; - u8 gpio[5]; - u8 cmd_len; - const struct ucbus_write_cmd *cmd; -}; - -static const struct sensor_s sensor_tb[] = { - [SENSOR_ICX098BQ] = { - "icx098bp", - 0x00, 0x00, - {0, - SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, - SQ930_GPIO_DFL_I2C_SDA, - 0, - SQ930_GPIO_RSTBAR - }, - 8, icx098bq_start_0 - }, - [SENSOR_LZ24BP] = { - "lz24bp", - 0x00, 0x00, - {0, - SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, - SQ930_GPIO_DFL_I2C_SDA, - 0, - SQ930_GPIO_RSTBAR - }, - 8, lz24bp_start_0 - }, - [SENSOR_MI0360] = { - "mi0360", - 0x5d, 0x80, - {SQ930_GPIO_RSTBAR, - SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, - SQ930_GPIO_DFL_I2C_SDA, - 0, - 0 - }, - 7, mi0360_start_0 - }, - [SENSOR_MT9V111] = { - "mt9v111", - 0x5c, 0x7f, - {SQ930_GPIO_RSTBAR, - SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, - SQ930_GPIO_DFL_I2C_SDA, - 0, - 0 - }, - 7, mi0360_start_0 - }, - [SENSOR_OV7660] = { - "ov7660", - 0x21, 0x00, - {0, - SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, - SQ930_GPIO_DFL_I2C_SDA, - 0, - SQ930_GPIO_RSTBAR - }, - 7, ov7660_start_0 - }, - [SENSOR_OV9630] = { - "ov9630", - 0x30, 0x00, - {0, - SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, - SQ930_GPIO_DFL_I2C_SDA, - 0, - SQ930_GPIO_RSTBAR - }, - 7, ov9630_start_0 - }, -}; - -static void reg_r(struct gspca_dev *gspca_dev, - u16 value, int len) -{ - int ret; - - if (gspca_dev->usb_err < 0) - return; - ret = usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - 0x0c, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, 0, gspca_dev->usb_buf, len, - 500); - if (ret < 0) { - pr_err("reg_r %04x failed %d\n", value, ret); - gspca_dev->usb_err = ret; - } -} - -static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index) -{ - int ret; - - if (gspca_dev->usb_err < 0) - return; - PDEBUG(D_USBO, "reg_w v: %04x i: %04x", value, index); - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x0c, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, NULL, 0, - 500); - msleep(30); - if (ret < 0) { - pr_err("reg_w %04x %04x failed %d\n", value, index, ret); - gspca_dev->usb_err = ret; - } -} - -static void reg_wb(struct gspca_dev *gspca_dev, u16 value, u16 index, - const u8 *data, int len) -{ - int ret; - - if (gspca_dev->usb_err < 0) - return; - PDEBUG(D_USBO, "reg_wb v: %04x i: %04x %02x...%02x", - value, index, *data, data[len - 1]); - memcpy(gspca_dev->usb_buf, data, len); - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x0c, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, gspca_dev->usb_buf, len, - 1000); - msleep(30); - if (ret < 0) { - pr_err("reg_wb %04x %04x failed %d\n", value, index, ret); - gspca_dev->usb_err = ret; - } -} - -static void i2c_write(struct sd *sd, - const struct i2c_write_cmd *cmd, - int ncmds) -{ - struct gspca_dev *gspca_dev = &sd->gspca_dev; - const struct sensor_s *sensor; - u16 val, idx; - u8 *buf; - int ret; - - if (gspca_dev->usb_err < 0) - return; - - sensor = &sensor_tb[sd->sensor]; - - val = (sensor->i2c_addr << 8) | SQ930_CTRL_I2C_IO; - idx = (cmd->val & 0xff00) | cmd->reg; - - buf = gspca_dev->usb_buf; - *buf++ = sensor->i2c_dum; - *buf++ = cmd->val; - - while (--ncmds > 0) { - cmd++; - *buf++ = cmd->reg; - *buf++ = cmd->val >> 8; - *buf++ = sensor->i2c_dum; - *buf++ = cmd->val; - } - - PDEBUG(D_USBO, "i2c_w v: %04x i: %04x %02x...%02x", - val, idx, gspca_dev->usb_buf[0], buf[-1]); - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x0c, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - val, idx, - gspca_dev->usb_buf, buf - gspca_dev->usb_buf, - 500); - if (ret < 0) { - pr_err("i2c_write failed %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -static void ucbus_write(struct gspca_dev *gspca_dev, - const struct ucbus_write_cmd *cmd, - int ncmds, - int batchsize) -{ - u8 *buf; - u16 val, idx; - int len, ret; - - if (gspca_dev->usb_err < 0) - return; - -#ifdef GSPCA_DEBUG - if ((batchsize - 1) * 3 > USB_BUF_SZ) { - pr_err("Bug: usb_buf overflow\n"); - gspca_dev->usb_err = -ENOMEM; - return; - } -#endif - - for (;;) { - len = ncmds; - if (len > batchsize) - len = batchsize; - ncmds -= len; - - val = (cmd->bw_addr << 8) | SQ930_CTRL_UCBUS_IO; - idx = (cmd->bw_data << 8) | (cmd->bw_addr >> 8); - - buf = gspca_dev->usb_buf; - while (--len > 0) { - cmd++; - *buf++ = cmd->bw_addr; - *buf++ = cmd->bw_addr >> 8; - *buf++ = cmd->bw_data; - } - if (buf != gspca_dev->usb_buf) - PDEBUG(D_USBO, "ucbus v: %04x i: %04x %02x...%02x", - val, idx, - gspca_dev->usb_buf[0], buf[-1]); - else - PDEBUG(D_USBO, "ucbus v: %04x i: %04x", - val, idx); - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x0c, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - val, idx, - gspca_dev->usb_buf, buf - gspca_dev->usb_buf, - 500); - if (ret < 0) { - pr_err("ucbus_write failed %d\n", ret); - gspca_dev->usb_err = ret; - return; - } - msleep(30); - if (ncmds <= 0) - break; - cmd++; - } -} - -static void gpio_set(struct sd *sd, u16 val, u16 mask) -{ - struct gspca_dev *gspca_dev = &sd->gspca_dev; - - if (mask & 0x00ff) { - sd->gpio[0] &= ~mask; - sd->gpio[0] |= val; - reg_w(gspca_dev, 0x0100 | SQ930_CTRL_GPIO, - ~sd->gpio[0] << 8); - } - mask >>= 8; - val >>= 8; - if (mask) { - sd->gpio[1] &= ~mask; - sd->gpio[1] |= val; - reg_w(gspca_dev, 0x0300 | SQ930_CTRL_GPIO, - ~sd->gpio[1] << 8); - } -} - -static void gpio_init(struct sd *sd, - const u8 *gpio) -{ - gpio_set(sd, *gpio++, 0x000f); - gpio_set(sd, *gpio++, 0x000f); - gpio_set(sd, *gpio++, 0x000f); - gpio_set(sd, *gpio++, 0x000f); - gpio_set(sd, *gpio, 0x000f); -} - -static void bridge_init(struct sd *sd) -{ - static const struct ucbus_write_cmd clkfreq_cmd = { - 0xf031, 0 /* SQ930_CLKFREQ_60MHZ */ - }; - - ucbus_write(&sd->gspca_dev, &clkfreq_cmd, 1, 1); - - gpio_set(sd, SQ930_GPIO_POWER, 0xff00); -} - -static void cmos_probe(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i; - const struct sensor_s *sensor; - static const u8 probe_order[] = { -/* SENSOR_LZ24BP, (tested as ccd) */ - SENSOR_OV9630, - SENSOR_MI0360, - SENSOR_OV7660, - SENSOR_MT9V111, - }; - - for (i = 0; i < ARRAY_SIZE(probe_order); i++) { - sensor = &sensor_tb[probe_order[i]]; - ucbus_write(&sd->gspca_dev, sensor->cmd, sensor->cmd_len, 8); - gpio_init(sd, sensor->gpio); - msleep(100); - reg_r(gspca_dev, (sensor->i2c_addr << 8) | 0x001c, 1); - msleep(100); - if (gspca_dev->usb_buf[0] != 0) - break; - } - if (i >= ARRAY_SIZE(probe_order)) { - pr_err("Unknown sensor\n"); - gspca_dev->usb_err = -EINVAL; - return; - } - sd->sensor = probe_order[i]; - switch (sd->sensor) { - case SENSOR_OV7660: - case SENSOR_OV9630: - pr_err("Sensor %s not yet treated\n", - sensor_tb[sd->sensor].name); - gspca_dev->usb_err = -EINVAL; - break; - } -} - -static void mt9v111_init(struct gspca_dev *gspca_dev) -{ - int i, nwait; - static const u8 cmd_001b[] = { - 0x00, 0x3b, 0xf6, 0x01, 0x03, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00 - }; - static const u8 cmd_011b[][7] = { - {0x10, 0x01, 0x66, 0x08, 0x00, 0x00, 0x00}, - {0x01, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x00}, - {0x20, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00}, - {0x02, 0x01, 0xae, 0x01, 0x00, 0x00, 0x00}, - }; - - reg_wb(gspca_dev, 0x001b, 0x0000, cmd_001b, sizeof cmd_001b); - for (i = 0; i < ARRAY_SIZE(cmd_011b); i++) { - reg_wb(gspca_dev, 0x001b, 0x0000, cmd_011b[i], - ARRAY_SIZE(cmd_011b[0])); - msleep(400); - nwait = 20; - for (;;) { - reg_r(gspca_dev, 0x031b, 1); - if (gspca_dev->usb_buf[0] == 0 - || gspca_dev->usb_err != 0) - break; - if (--nwait < 0) { - PDEBUG(D_PROBE, "mt9v111_init timeout"); - gspca_dev->usb_err = -ETIME; - return; - } - msleep(50); - } - } -} - -static void global_init(struct sd *sd, int first_time) -{ - switch (sd->sensor) { - case SENSOR_ICX098BQ: - if (first_time) - ucbus_write(&sd->gspca_dev, - icx098bq_start_0, - 8, 8); - gpio_init(sd, sensor_tb[sd->sensor].gpio); - break; - case SENSOR_LZ24BP: - if (sd->type != Creative_live_motion) - gpio_set(sd, SQ930_GPIO_EXTRA1, 0x00ff); - else - gpio_set(sd, 0, 0x00ff); - msleep(50); - if (first_time) - ucbus_write(&sd->gspca_dev, - lz24bp_start_0, - 8, 8); - gpio_init(sd, sensor_tb[sd->sensor].gpio); - break; - case SENSOR_MI0360: - if (first_time) - ucbus_write(&sd->gspca_dev, - mi0360_start_0, - ARRAY_SIZE(mi0360_start_0), - 8); - gpio_init(sd, sensor_tb[sd->sensor].gpio); - gpio_set(sd, SQ930_GPIO_EXTRA2, SQ930_GPIO_EXTRA2); - break; - default: -/* case SENSOR_MT9V111: */ - if (first_time) - mt9v111_init(&sd->gspca_dev); - else - gpio_init(sd, sensor_tb[sd->sensor].gpio); - break; - } -} - -static void lz24bp_ppl(struct sd *sd, u16 ppl) -{ - struct ucbus_write_cmd cmds[2] = { - {0xf810, ppl >> 8}, - {0xf811, ppl} - }; - - ucbus_write(&sd->gspca_dev, cmds, ARRAY_SIZE(cmds), 2); -} - -static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 gain) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i, integclks, intstartclk, frameclks, min_frclk; - const struct sensor_s *sensor; - u16 cmd; - u8 buf[15]; - - integclks = expo; - i = 0; - cmd = SQ930_CTRL_SET_EXPOSURE; - - switch (sd->sensor) { - case SENSOR_ICX098BQ: /* ccd */ - case SENSOR_LZ24BP: - min_frclk = sd->sensor == SENSOR_ICX098BQ ? 0x210 : 0x26f; - if (integclks >= min_frclk) { - intstartclk = 0; - frameclks = integclks; - } else { - intstartclk = min_frclk - integclks; - frameclks = min_frclk; - } - buf[i++] = intstartclk >> 8; - buf[i++] = intstartclk; - buf[i++] = frameclks >> 8; - buf[i++] = frameclks; - buf[i++] = gain; - break; - default: /* cmos */ -/* case SENSOR_MI0360: */ -/* case SENSOR_MT9V111: */ - cmd |= 0x0100; - sensor = &sensor_tb[sd->sensor]; - buf[i++] = sensor->i2c_addr; /* i2c_slave_addr */ - buf[i++] = 0x08; /* 2 * ni2c */ - buf[i++] = 0x09; /* reg = shutter width */ - buf[i++] = integclks >> 8; /* val H */ - buf[i++] = sensor->i2c_dum; - buf[i++] = integclks; /* val L */ - buf[i++] = 0x35; /* reg = global gain */ - buf[i++] = 0x00; /* val H */ - buf[i++] = sensor->i2c_dum; - buf[i++] = 0x80 + gain / 2; /* val L */ - buf[i++] = 0x00; - buf[i++] = 0x00; - buf[i++] = 0x00; - buf[i++] = 0x00; - buf[i++] = 0x83; - break; - } - reg_wb(gspca_dev, cmd, 0, buf, i); -} - -/* This function is called at probe time just before sd_init */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam = &gspca_dev->cam; - - sd->sensor = id->driver_info >> 8; - sd->type = id->driver_info; - - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - - cam->bulk = 1; - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->gpio[0] = sd->gpio[1] = 0xff; /* force gpio rewrite */ - -/*fixme: is this needed for icx098bp and mi0360? - if (sd->sensor != SENSOR_LZ24BP) - reg_w(gspca_dev, SQ930_CTRL_RESET, 0x0000); - */ - - reg_r(gspca_dev, SQ930_CTRL_GET_DEV_INFO, 8); - if (gspca_dev->usb_err < 0) - return gspca_dev->usb_err; - -/* it returns: - * 03 00 12 93 0b f6 c9 00 live! ultra - * 03 00 07 93 0b f6 ca 00 live! ultra for notebook - * 03 00 12 93 0b fe c8 00 Trust WB-3500T - * 02 00 06 93 0b fe c8 00 Joy-IT 318S - * 03 00 12 93 0b f6 cf 00 icam tracer - sensor icx098bq - * 02 00 12 93 0b fe cf 00 ProQ Motion Webcam - * - * byte - * 0: 02 = usb 1.0 (12Mbit) / 03 = usb2.0 (480Mbit) - * 1: 00 - * 2: 06 / 07 / 12 = mode webcam? firmware?? - * 3: 93 chip = 930b (930b or 930c) - * 4: 0b - * 5: f6 = cdd (icx098bq, lz24bp) / fe or de = cmos (i2c) (other sensors) - * 6: c8 / c9 / ca / cf = mode webcam?, sensor? webcam? - * 7: 00 - */ - PDEBUG(D_PROBE, "info: %*ph", 8, gspca_dev->usb_buf); - - bridge_init(sd); - - if (sd->sensor == SENSOR_MI0360) { - - /* no sensor probe for icam tracer */ - if (gspca_dev->usb_buf[5] == 0xf6) /* if ccd */ - sd->sensor = SENSOR_ICX098BQ; - else - cmos_probe(gspca_dev); - } - if (gspca_dev->usb_err >= 0) { - PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name); - global_init(sd, 1); - } - return gspca_dev->usb_err; -} - -/* send the start/stop commands to the webcam */ -static void send_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - const struct cap_s *cap; - int mode; - - mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - cap = &capconfig[sd->sensor][mode]; - reg_wb(gspca_dev, 0x0900 | SQ930_CTRL_CAP_START, - 0x0a00 | cap->cc_sizeid, - cap->cc_bytes, 32); -} - -static void send_stop(struct gspca_dev *gspca_dev) -{ - reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0); -} - -/* function called at start time before URB creation */ -static int sd_isoc_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - gspca_dev->cam.bulk_nurbs = 1; /* there must be one URB only */ - sd->do_ctrl = 0; - gspca_dev->cam.bulk_size = gspca_dev->width * gspca_dev->height + 8; - return 0; -} - -/* start the capture */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int mode; - - bridge_init(sd); - global_init(sd, 0); - msleep(100); - - switch (sd->sensor) { - case SENSOR_ICX098BQ: - ucbus_write(gspca_dev, icx098bq_start_0, - ARRAY_SIZE(icx098bq_start_0), - 8); - ucbus_write(gspca_dev, icx098bq_start_1, - ARRAY_SIZE(icx098bq_start_1), - 5); - ucbus_write(gspca_dev, icx098bq_start_2, - ARRAY_SIZE(icx098bq_start_2), - 6); - msleep(50); - - /* 1st start */ - send_start(gspca_dev); - gpio_set(sd, SQ930_GPIO_EXTRA2 | SQ930_GPIO_RSTBAR, 0x00ff); - msleep(70); - reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0x0000); - gpio_set(sd, 0x7f, 0x00ff); - - /* 2nd start */ - send_start(gspca_dev); - gpio_set(sd, SQ930_GPIO_EXTRA2 | SQ930_GPIO_RSTBAR, 0x00ff); - goto out; - case SENSOR_LZ24BP: - ucbus_write(gspca_dev, lz24bp_start_0, - ARRAY_SIZE(lz24bp_start_0), - 8); - if (sd->type != Creative_live_motion) - ucbus_write(gspca_dev, lz24bp_start_1_gen, - ARRAY_SIZE(lz24bp_start_1_gen), - 5); - else - ucbus_write(gspca_dev, lz24bp_start_1_clm, - ARRAY_SIZE(lz24bp_start_1_clm), - 5); - ucbus_write(gspca_dev, lz24bp_start_2, - ARRAY_SIZE(lz24bp_start_2), - 6); - mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - lz24bp_ppl(sd, mode == 1 ? 0x0564 : 0x0310); - msleep(10); - break; - case SENSOR_MI0360: - ucbus_write(gspca_dev, mi0360_start_0, - ARRAY_SIZE(mi0360_start_0), - 8); - i2c_write(sd, mi0360_init_23, - ARRAY_SIZE(mi0360_init_23)); - i2c_write(sd, mi0360_init_24, - ARRAY_SIZE(mi0360_init_24)); - i2c_write(sd, mi0360_init_25, - ARRAY_SIZE(mi0360_init_25)); - ucbus_write(gspca_dev, mi0360_start_1, - ARRAY_SIZE(mi0360_start_1), - 5); - i2c_write(sd, mi0360_start_2, - ARRAY_SIZE(mi0360_start_2)); - i2c_write(sd, mi0360_start_3, - ARRAY_SIZE(mi0360_start_3)); - - /* 1st start */ - send_start(gspca_dev); - msleep(60); - send_stop(gspca_dev); - - i2c_write(sd, - mi0360_start_4, ARRAY_SIZE(mi0360_start_4)); - break; - default: -/* case SENSOR_MT9V111: */ - ucbus_write(gspca_dev, mi0360_start_0, - ARRAY_SIZE(mi0360_start_0), - 8); - i2c_write(sd, mt9v111_init_0, - ARRAY_SIZE(mt9v111_init_0)); - i2c_write(sd, mt9v111_init_1, - ARRAY_SIZE(mt9v111_init_1)); - i2c_write(sd, mt9v111_init_2, - ARRAY_SIZE(mt9v111_init_2)); - ucbus_write(gspca_dev, mt9v111_start_1, - ARRAY_SIZE(mt9v111_start_1), - 5); - i2c_write(sd, mt9v111_init_3, - ARRAY_SIZE(mt9v111_init_3)); - i2c_write(sd, mt9v111_init_4, - ARRAY_SIZE(mt9v111_init_4)); - break; - } - - send_start(gspca_dev); -out: - msleep(1000); - - if (sd->sensor == SENSOR_MT9V111) - gpio_set(sd, SQ930_GPIO_DFL_LED, SQ930_GPIO_DFL_LED); - - sd->do_ctrl = 1; /* set the exposure */ - - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_MT9V111) - gpio_set(sd, 0, SQ930_GPIO_DFL_LED); - send_stop(gspca_dev); -} - -/* function called when the application gets a new frame */ -/* It sets the exposure if required and restart the bulk transfer. */ -static void sd_dq_callback(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret; - - if (!sd->do_ctrl || gspca_dev->cam.bulk_nurbs != 0) - return; - sd->do_ctrl = 0; - - setexposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure), - v4l2_ctrl_g_ctrl(sd->gain)); - - gspca_dev->cam.bulk_nurbs = 1; - ret = usb_submit_urb(gspca_dev->urb[0], GFP_ATOMIC); - if (ret < 0) - pr_err("sd_dq_callback() err %d\n", ret); - - /* wait a little time, otherwise the webcam crashes */ - msleep(100); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->do_ctrl) - gspca_dev->cam.bulk_nurbs = 0; - gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); - gspca_frame_add(gspca_dev, INTER_PACKET, data, len - 8); - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *) gspca_dev; - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - setexposure(gspca_dev, ctrl->val, sd->gain->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - struct sd *sd = (struct sd *) gspca_dev; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 2); - sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, 1, 0xfff, 1, 0x356); - sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 1, 255, 1, 0x8d); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - v4l2_ctrl_cluster(2, &sd->exposure); - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .isoc_init = sd_isoc_init, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, - .dq_callback = sd_dq_callback, -}; - -/* Table of supported USB devices */ -#define ST(sensor, type) \ - .driver_info = (SENSOR_ ## sensor << 8) \ - | (type) -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x041e, 0x4038), ST(MI0360, 0)}, - {USB_DEVICE(0x041e, 0x403c), ST(LZ24BP, 0)}, - {USB_DEVICE(0x041e, 0x403d), ST(LZ24BP, 0)}, - {USB_DEVICE(0x041e, 0x4041), ST(LZ24BP, Creative_live_motion)}, - {USB_DEVICE(0x2770, 0x930b), ST(MI0360, 0)}, - {USB_DEVICE(0x2770, 0x930c), ST(MI0360, 0)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c deleted file mode 100644 index 8c0982607f25..000000000000 --- a/drivers/media/video/gspca/stk014.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Syntek DV4000 (STK014) subdriver - * - * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr) - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "stk014" - -#include "gspca.h" -#include "jpeg.h" - -MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); -MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver"); -MODULE_LICENSE("GPL"); - -#define QUALITY 50 - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - u8 jpeg_hdr[JPEG_HDR_SZ]; -}; - -static const struct v4l2_pix_format vga_mode[] = { - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; - -/* -- read a register -- */ -static u8 reg_r(struct gspca_dev *gspca_dev, - __u16 index) -{ - struct usb_device *dev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return 0; - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - 0x00, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x00, - index, - gspca_dev->usb_buf, 1, - 500); - if (ret < 0) { - pr_err("reg_r err %d\n", ret); - gspca_dev->usb_err = ret; - return 0; - } - return gspca_dev->usb_buf[0]; -} - -/* -- write a register -- */ -static void reg_w(struct gspca_dev *gspca_dev, - __u16 index, __u16 value) -{ - struct usb_device *dev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return; - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x01, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - NULL, - 0, - 500); - if (ret < 0) { - pr_err("reg_w err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -/* -- get a bulk value (4 bytes) -- */ -static void rcv_val(struct gspca_dev *gspca_dev, - int ads) -{ - struct usb_device *dev = gspca_dev->dev; - int alen, ret; - - reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff); - reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff); - reg_w(gspca_dev, 0x636, ads & 0xff); - reg_w(gspca_dev, 0x637, 0); - reg_w(gspca_dev, 0x638, 4); /* len & 0xff */ - reg_w(gspca_dev, 0x639, 0); /* len >> 8 */ - reg_w(gspca_dev, 0x63a, 0); - reg_w(gspca_dev, 0x63b, 0); - reg_w(gspca_dev, 0x630, 5); - if (gspca_dev->usb_err < 0) - return; - ret = usb_bulk_msg(dev, - usb_rcvbulkpipe(dev, 0x05), - gspca_dev->usb_buf, - 4, /* length */ - &alen, - 500); /* timeout in milliseconds */ - if (ret < 0) { - pr_err("rcv_val err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -/* -- send a bulk value -- */ -static void snd_val(struct gspca_dev *gspca_dev, - int ads, - unsigned int val) -{ - struct usb_device *dev = gspca_dev->dev; - int alen, ret; - __u8 seq = 0; - - if (ads == 0x003f08) { - reg_r(gspca_dev, 0x0704); - seq = reg_r(gspca_dev, 0x0705); - reg_r(gspca_dev, 0x0650); - reg_w(gspca_dev, 0x654, seq); - } else { - reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff); - } - reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff); - reg_w(gspca_dev, 0x656, ads & 0xff); - reg_w(gspca_dev, 0x657, 0); - reg_w(gspca_dev, 0x658, 0x04); /* size */ - reg_w(gspca_dev, 0x659, 0); - reg_w(gspca_dev, 0x65a, 0); - reg_w(gspca_dev, 0x65b, 0); - reg_w(gspca_dev, 0x650, 5); - if (gspca_dev->usb_err < 0) - return; - gspca_dev->usb_buf[0] = val >> 24; - gspca_dev->usb_buf[1] = val >> 16; - gspca_dev->usb_buf[2] = val >> 8; - gspca_dev->usb_buf[3] = val; - ret = usb_bulk_msg(dev, - usb_sndbulkpipe(dev, 6), - gspca_dev->usb_buf, - 4, - &alen, - 500); /* timeout in milliseconds */ - if (ret < 0) { - pr_err("snd_val err %d\n", ret); - gspca_dev->usb_err = ret; - } else { - if (ads == 0x003f08) { - seq += 4; - seq &= 0x3f; - reg_w(gspca_dev, 0x705, seq); - } - } -} - -/* set a camera parameter */ -static void set_par(struct gspca_dev *gspca_dev, - int parval) -{ - snd_val(gspca_dev, 0x003f08, parval); -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 val) -{ - int parval; - - parval = 0x06000000 /* whiteness */ - + (val << 16); - set_par(gspca_dev, parval); -} - -static void setcontrast(struct gspca_dev *gspca_dev, s32 val) -{ - int parval; - - parval = 0x07000000 /* contrast */ - + (val << 16); - set_par(gspca_dev, parval); -} - -static void setcolors(struct gspca_dev *gspca_dev, s32 val) -{ - int parval; - - parval = 0x08000000 /* saturation */ - + (val << 16); - set_par(gspca_dev, parval); -} - -static void setlightfreq(struct gspca_dev *gspca_dev, s32 val) -{ - set_par(gspca_dev, val == 1 - ? 0x33640000 /* 50 Hz */ - : 0x33780000); /* 60 Hz */ -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - gspca_dev->cam.cam_mode = vga_mode; - gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - u8 ret; - - /* check if the device responds */ - usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); - ret = reg_r(gspca_dev, 0x0740); - if (gspca_dev->usb_err >= 0) { - if (ret != 0xff) { - pr_err("init reg: 0x%02x\n", ret); - gspca_dev->usb_err = -EIO; - } - } - return gspca_dev->usb_err; -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret, value; - - /* create the JPEG header */ - jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, - 0x22); /* JPEG 411 */ - jpeg_set_qual(sd->jpeg_hdr, QUALITY); - - /* work on alternate 1 */ - usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); - - set_par(gspca_dev, 0x10000000); - set_par(gspca_dev, 0x00000000); - set_par(gspca_dev, 0x8002e001); - set_par(gspca_dev, 0x14000000); - if (gspca_dev->width > 320) - value = 0x8002e001; /* 640x480 */ - else - value = 0x4001f000; /* 320x240 */ - set_par(gspca_dev, value); - ret = usb_set_interface(gspca_dev->dev, - gspca_dev->iface, - gspca_dev->alt); - if (ret < 0) { - pr_err("set intf %d %d failed\n", - gspca_dev->iface, gspca_dev->alt); - gspca_dev->usb_err = ret; - goto out; - } - reg_r(gspca_dev, 0x0630); - rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */ - reg_r(gspca_dev, 0x0650); - snd_val(gspca_dev, 0x000020, 0xffffffff); - reg_w(gspca_dev, 0x0620, 0); - reg_w(gspca_dev, 0x0630, 0); - reg_w(gspca_dev, 0x0640, 0); - reg_w(gspca_dev, 0x0650, 0); - reg_w(gspca_dev, 0x0660, 0); - set_par(gspca_dev, 0x09800000); /* Red ? */ - set_par(gspca_dev, 0x0a800000); /* Green ? */ - set_par(gspca_dev, 0x0b800000); /* Blue ? */ - set_par(gspca_dev, 0x0d030000); /* Gamma ? */ - - /* start the video flow */ - set_par(gspca_dev, 0x01000000); - set_par(gspca_dev, 0x01000000); - if (gspca_dev->usb_err >= 0) - PDEBUG(D_STREAM, "camera started alt: 0x%02x", - gspca_dev->alt); -out: - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct usb_device *dev = gspca_dev->dev; - - set_par(gspca_dev, 0x02000000); - set_par(gspca_dev, 0x02000000); - usb_set_interface(dev, gspca_dev->iface, 1); - reg_r(gspca_dev, 0x0630); - rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */ - reg_r(gspca_dev, 0x0650); - snd_val(gspca_dev, 0x000020, 0xffffffff); - reg_w(gspca_dev, 0x0620, 0); - reg_w(gspca_dev, 0x0630, 0); - reg_w(gspca_dev, 0x0640, 0); - reg_w(gspca_dev, 0x0650, 0); - reg_w(gspca_dev, 0x0660, 0); - PDEBUG(D_STREAM, "camera stopped"); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - static unsigned char ffd9[] = {0xff, 0xd9}; - - /* a frame starts with: - * - 0xff 0xfe - * - 0x08 0x00 - length (little endian ?!) - * - 4 bytes = size of whole frame (BE - including header) - * - 0x00 0x0c - * - 0xff 0xd8 - * - .. JPEG image with escape sequences (ff 00) - * (without ending - ff d9) - */ - if (data[0] == 0xff && data[1] == 0xfe) { - gspca_frame_add(gspca_dev, LAST_PACKET, - ffd9, 2); - - /* put the JPEG 411 header */ - gspca_frame_add(gspca_dev, FIRST_PACKET, - sd->jpeg_hdr, JPEG_HDR_SZ); - - /* beginning of the frame */ -#define STKHDRSZ 12 - data += STKHDRSZ; - len -= STKHDRSZ; - } - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_CONTRAST: - setcontrast(gspca_dev, ctrl->val); - break; - case V4L2_CID_SATURATION: - setcolors(gspca_dev, ctrl->val); - break; - case V4L2_CID_POWER_LINE_FREQUENCY: - setlightfreq(gspca_dev, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 4); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 255, 1, 127); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SATURATION, 0, 255, 1, 127); - v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, - V4L2_CID_POWER_LINE_FREQUENCY, - V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1, - V4L2_CID_POWER_LINE_FREQUENCY_50HZ); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x05e1, 0x0893)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/stv0680.c b/drivers/media/video/gspca/stv0680.c deleted file mode 100644 index 67605272aaa8..000000000000 --- a/drivers/media/video/gspca/stv0680.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * STV0680 USB Camera Driver - * - * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> - * - * This module is adapted from the in kernel v4l1 stv680 driver: - * - * STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net) - * - * Thanks to STMicroelectronics for information on the usb commands, and - * to Steve Miller at STM for his help and encouragement while I was - * writing this driver. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "stv0680" - -#include "gspca.h" - -MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); -MODULE_DESCRIPTION("STV0680 USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - struct v4l2_pix_format mode; - u8 orig_mode; - u8 video_mode; - u8 current_mode; -}; - -static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val, - int size) -{ - int ret = -1; - u8 req_type = 0; - unsigned int pipe = 0; - - switch (set) { - case 0: /* 0xc1 */ - req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; - pipe = usb_rcvctrlpipe(gspca_dev->dev, 0); - break; - case 1: /* 0x41 */ - req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; - pipe = usb_sndctrlpipe(gspca_dev->dev, 0); - break; - case 2: /* 0x80 */ - req_type = USB_DIR_IN | USB_RECIP_DEVICE; - pipe = usb_rcvctrlpipe(gspca_dev->dev, 0); - break; - case 3: /* 0x40 */ - req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; - pipe = usb_sndctrlpipe(gspca_dev->dev, 0); - break; - } - - ret = usb_control_msg(gspca_dev->dev, pipe, - req, req_type, - val, 0, gspca_dev->usb_buf, size, 500); - - if ((ret < 0) && (req != 0x0a)) - pr_err("usb_control_msg error %i, request = 0x%x, error = %i\n", - set, req, ret); - - return ret; -} - -static int stv0680_handle_error(struct gspca_dev *gspca_dev, int ret) -{ - stv_sndctrl(gspca_dev, 0, 0x80, 0, 0x02); /* Get Last Error */ - PDEBUG(D_ERR, "last error: %i, command = 0x%x", - gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]); - return ret; -} - -static int stv0680_get_video_mode(struct gspca_dev *gspca_dev) -{ - /* Note not sure if this init of usb_buf is really necessary */ - memset(gspca_dev->usb_buf, 0, 8); - gspca_dev->usb_buf[0] = 0x0f; - - if (stv_sndctrl(gspca_dev, 0, 0x87, 0, 0x08) != 0x08) { - PDEBUG(D_ERR, "Get_Camera_Mode failed"); - return stv0680_handle_error(gspca_dev, -EIO); - } - - return gspca_dev->usb_buf[0]; /* 01 = VGA, 03 = QVGA, 00 = CIF */ -} - -static int stv0680_set_video_mode(struct gspca_dev *gspca_dev, u8 mode) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->current_mode == mode) - return 0; - - memset(gspca_dev->usb_buf, 0, 8); - gspca_dev->usb_buf[0] = mode; - - if (stv_sndctrl(gspca_dev, 3, 0x07, 0x0100, 0x08) != 0x08) { - PDEBUG(D_ERR, "Set_Camera_Mode failed"); - return stv0680_handle_error(gspca_dev, -EIO); - } - - /* Verify we got what we've asked for */ - if (stv0680_get_video_mode(gspca_dev) != mode) { - PDEBUG(D_ERR, "Error setting camera video mode!"); - return -EIO; - } - - sd->current_mode = mode; - - return 0; -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - int ret; - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam = &gspca_dev->cam; - - /* Give the camera some time to settle, otherwise initalization will - fail on hotplug, and yes it really needs a full second. */ - msleep(1000); - - /* ping camera to be sure STV0680 is present */ - if (stv_sndctrl(gspca_dev, 0, 0x88, 0x5678, 0x02) != 0x02 || - gspca_dev->usb_buf[0] != 0x56 || gspca_dev->usb_buf[1] != 0x78) { - PDEBUG(D_ERR, "STV(e): camera ping failed!!"); - return stv0680_handle_error(gspca_dev, -ENODEV); - } - - /* get camera descriptor */ - if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x09) != 0x09) - return stv0680_handle_error(gspca_dev, -ENODEV); - - if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x22) != 0x22 || - gspca_dev->usb_buf[7] != 0xa0 || gspca_dev->usb_buf[8] != 0x23) { - PDEBUG(D_ERR, "Could not get descriptor 0200."); - return stv0680_handle_error(gspca_dev, -ENODEV); - } - if (stv_sndctrl(gspca_dev, 0, 0x8a, 0, 0x02) != 0x02) - return stv0680_handle_error(gspca_dev, -ENODEV); - if (stv_sndctrl(gspca_dev, 0, 0x8b, 0, 0x24) != 0x24) - return stv0680_handle_error(gspca_dev, -ENODEV); - if (stv_sndctrl(gspca_dev, 0, 0x85, 0, 0x10) != 0x10) - return stv0680_handle_error(gspca_dev, -ENODEV); - - if (!(gspca_dev->usb_buf[7] & 0x09)) { - PDEBUG(D_ERR, "Camera supports neither CIF nor QVGA mode"); - return -ENODEV; - } - if (gspca_dev->usb_buf[7] & 0x01) - PDEBUG(D_PROBE, "Camera supports CIF mode"); - if (gspca_dev->usb_buf[7] & 0x02) - PDEBUG(D_PROBE, "Camera supports VGA mode"); - if (gspca_dev->usb_buf[7] & 0x04) - PDEBUG(D_PROBE, "Camera supports QCIF mode"); - if (gspca_dev->usb_buf[7] & 0x08) - PDEBUG(D_PROBE, "Camera supports QVGA mode"); - - if (gspca_dev->usb_buf[7] & 0x01) - sd->video_mode = 0x00; /* CIF */ - else - sd->video_mode = 0x03; /* QVGA */ - - /* FW rev, ASIC rev, sensor ID */ - PDEBUG(D_PROBE, "Firmware rev is %i.%i", - gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]); - PDEBUG(D_PROBE, "ASIC rev is %i.%i", - gspca_dev->usb_buf[2], gspca_dev->usb_buf[3]); - PDEBUG(D_PROBE, "Sensor ID is %i", - (gspca_dev->usb_buf[4]*16) + (gspca_dev->usb_buf[5]>>4)); - - - ret = stv0680_get_video_mode(gspca_dev); - if (ret < 0) - return ret; - sd->current_mode = sd->orig_mode = ret; - - ret = stv0680_set_video_mode(gspca_dev, sd->video_mode); - if (ret < 0) - return ret; - - /* Get mode details */ - if (stv_sndctrl(gspca_dev, 0, 0x8f, 0, 0x10) != 0x10) - return stv0680_handle_error(gspca_dev, -EIO); - - cam->bulk = 1; - cam->bulk_nurbs = 1; /* The cam cannot handle more */ - cam->bulk_size = (gspca_dev->usb_buf[0] << 24) | - (gspca_dev->usb_buf[1] << 16) | - (gspca_dev->usb_buf[2] << 8) | - (gspca_dev->usb_buf[3]); - sd->mode.width = (gspca_dev->usb_buf[4] << 8) | - (gspca_dev->usb_buf[5]); /* 322, 356, 644 */ - sd->mode.height = (gspca_dev->usb_buf[6] << 8) | - (gspca_dev->usb_buf[7]); /* 242, 292, 484 */ - sd->mode.pixelformat = V4L2_PIX_FMT_STV0680; - sd->mode.field = V4L2_FIELD_NONE; - sd->mode.bytesperline = sd->mode.width; - sd->mode.sizeimage = cam->bulk_size; - sd->mode.colorspace = V4L2_COLORSPACE_SRGB; - - /* origGain = gspca_dev->usb_buf[12]; */ - - cam->cam_mode = &sd->mode; - cam->nmodes = 1; - - - ret = stv0680_set_video_mode(gspca_dev, sd->orig_mode); - if (ret < 0) - return ret; - - if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0100, 0x12) != 0x12 || - gspca_dev->usb_buf[8] != 0x53 || gspca_dev->usb_buf[9] != 0x05) { - pr_err("Could not get descriptor 0100\n"); - return stv0680_handle_error(gspca_dev, -EIO); - } - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - return 0; -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - int ret; - struct sd *sd = (struct sd *) gspca_dev; - - ret = stv0680_set_video_mode(gspca_dev, sd->video_mode); - if (ret < 0) - return ret; - - if (stv_sndctrl(gspca_dev, 0, 0x85, 0, 0x10) != 0x10) - return stv0680_handle_error(gspca_dev, -EIO); - - /* Start stream at: - 0x0000 = CIF (352x288) - 0x0100 = VGA (640x480) - 0x0300 = QVGA (320x240) */ - if (stv_sndctrl(gspca_dev, 1, 0x09, sd->video_mode << 8, 0x0) != 0x0) - return stv0680_handle_error(gspca_dev, -EIO); - - return 0; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - /* This is a high priority command; it stops all lower order cmds */ - if (stv_sndctrl(gspca_dev, 1, 0x04, 0x0000, 0x0) != 0x0) - stv0680_handle_error(gspca_dev, -EIO); -} - -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (!sd->gspca_dev.present) - return; - - stv0680_set_video_mode(gspca_dev, sd->orig_mode); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, - int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* Every now and then the camera sends a 16 byte packet, no idea - what it contains, but it is not image data, when this - happens the frame received before this packet is corrupt, - so discard it. */ - if (len != sd->mode.sizeimage) { - gspca_dev->last_packet_type = DISCARD_PACKET; - return; - } - - /* Finish the previous frame, we do this upon reception of the next - packet, even though it is already complete so that the strange 16 - byte packets send after a corrupt frame can discard it. */ - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - - /* Store the just received frame */ - gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .start = sd_start, - .stopN = sd_stopN, - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x0553, 0x0202)}, - {USB_DEVICE(0x041e, 0x4007)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/stv06xx/Kconfig b/drivers/media/video/gspca/stv06xx/Kconfig deleted file mode 100644 index 634ad38d9fb8..000000000000 --- a/drivers/media/video/gspca/stv06xx/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -config USB_STV06XX - tristate "STV06XX USB Camera Driver" - depends on USB_GSPCA - help - Say Y here if you want support for cameras based on - the ST STV06XX chip. - - To compile this driver as a module, choose M here: the - module will be called gspca_stv06xx. diff --git a/drivers/media/video/gspca/stv06xx/Makefile b/drivers/media/video/gspca/stv06xx/Makefile deleted file mode 100644 index 38bc41061d83..000000000000 --- a/drivers/media/video/gspca/stv06xx/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -obj-$(CONFIG_USB_STV06XX) += gspca_stv06xx.o - -gspca_stv06xx-objs := stv06xx.o \ - stv06xx_vv6410.o \ - stv06xx_hdcs.o \ - stv06xx_pb0100.o \ - stv06xx_st6422.o - -ccflags-y += -I$(srctree)/drivers/media/video/gspca - diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c deleted file mode 100644 index 999ec7764449..000000000000 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ /dev/null @@ -1,634 +0,0 @@ -/* - * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher - * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland - * Copyright (c) 2002, 2003 Tuukka Toivonen - * Copyright (c) 2008 Erik Andrén - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * P/N 861037: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express - * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam - * P/N 861075-0040: Sensor HDCS1000 ASIC - * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB - * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/input.h> -#include "stv06xx_sensor.h" - -MODULE_AUTHOR("Erik Andrén"); -MODULE_DESCRIPTION("STV06XX USB Camera Driver"); -MODULE_LICENSE("GPL"); - -static bool dump_bridge; -static bool dump_sensor; - -int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data) -{ - int err; - struct usb_device *udev = sd->gspca_dev.dev; - __u8 *buf = sd->gspca_dev.usb_buf; - u8 len = (i2c_data > 0xff) ? 2 : 1; - - buf[0] = i2c_data & 0xff; - buf[1] = (i2c_data >> 8) & 0xff; - - err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x04, 0x40, address, 0, buf, len, - STV06XX_URB_MSG_TIMEOUT); - - PDEBUG(D_CONF, "Written 0x%x to address 0x%x, status: %d", - i2c_data, address, err); - - return (err < 0) ? err : 0; -} - -int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data) -{ - int err; - struct usb_device *udev = sd->gspca_dev.dev; - __u8 *buf = sd->gspca_dev.usb_buf; - - err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - 0x04, 0xc0, address, 0, buf, 1, - STV06XX_URB_MSG_TIMEOUT); - - *i2c_data = buf[0]; - - PDEBUG(D_CONF, "Reading 0x%x from address 0x%x, status %d", - *i2c_data, address, err); - - return (err < 0) ? err : 0; -} - -/* Wraps the normal write sensor bytes / words functions for writing a - single value */ -int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value) -{ - if (sd->sensor->i2c_len == 2) { - u16 data[2] = { address, value }; - return stv06xx_write_sensor_words(sd, data, 1); - } else { - u8 data[2] = { address, value }; - return stv06xx_write_sensor_bytes(sd, data, 1); - } -} - -static int stv06xx_write_sensor_finish(struct sd *sd) -{ - int err = 0; - - if (sd->bridge == BRIDGE_STV610) { - struct usb_device *udev = sd->gspca_dev.dev; - __u8 *buf = sd->gspca_dev.usb_buf; - - buf[0] = 0; - err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x04, 0x40, 0x1704, 0, buf, 1, - STV06XX_URB_MSG_TIMEOUT); - } - - return (err < 0) ? err : 0; -} - -int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len) -{ - int err, i, j; - struct usb_device *udev = sd->gspca_dev.dev; - __u8 *buf = sd->gspca_dev.usb_buf; - - PDEBUG(D_CONF, "I2C: Command buffer contains %d entries", len); - for (i = 0; i < len;) { - /* Build the command buffer */ - memset(buf, 0, I2C_BUFFER_LENGTH); - for (j = 0; j < I2C_MAX_BYTES && i < len; j++, i++) { - buf[j] = data[2*i]; - buf[0x10 + j] = data[2*i+1]; - PDEBUG(D_CONF, "I2C: Writing 0x%02x to reg 0x%02x", - data[2*i+1], data[2*i]); - } - buf[0x20] = sd->sensor->i2c_addr; - buf[0x21] = j - 1; /* Number of commands to send - 1 */ - buf[0x22] = I2C_WRITE_CMD; - err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x04, 0x40, 0x0400, 0, buf, - I2C_BUFFER_LENGTH, - STV06XX_URB_MSG_TIMEOUT); - if (err < 0) - return err; - } - return stv06xx_write_sensor_finish(sd); -} - -int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len) -{ - int err, i, j; - struct usb_device *udev = sd->gspca_dev.dev; - __u8 *buf = sd->gspca_dev.usb_buf; - - PDEBUG(D_CONF, "I2C: Command buffer contains %d entries", len); - - for (i = 0; i < len;) { - /* Build the command buffer */ - memset(buf, 0, I2C_BUFFER_LENGTH); - for (j = 0; j < I2C_MAX_WORDS && i < len; j++, i++) { - buf[j] = data[2*i]; - buf[0x10 + j * 2] = data[2*i+1]; - buf[0x10 + j * 2 + 1] = data[2*i+1] >> 8; - PDEBUG(D_CONF, "I2C: Writing 0x%04x to reg 0x%02x", - data[2*i+1], data[2*i]); - } - buf[0x20] = sd->sensor->i2c_addr; - buf[0x21] = j - 1; /* Number of commands to send - 1 */ - buf[0x22] = I2C_WRITE_CMD; - err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x04, 0x40, 0x0400, 0, buf, - I2C_BUFFER_LENGTH, - STV06XX_URB_MSG_TIMEOUT); - if (err < 0) - return err; - } - return stv06xx_write_sensor_finish(sd); -} - -int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value) -{ - int err; - struct usb_device *udev = sd->gspca_dev.dev; - __u8 *buf = sd->gspca_dev.usb_buf; - - err = stv06xx_write_bridge(sd, STV_I2C_FLUSH, sd->sensor->i2c_flush); - if (err < 0) - return err; - - /* Clear mem */ - memset(buf, 0, I2C_BUFFER_LENGTH); - - buf[0] = address; - buf[0x20] = sd->sensor->i2c_addr; - buf[0x21] = 0; - - /* Read I2C register */ - buf[0x22] = I2C_READ_CMD; - - err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x04, 0x40, 0x1400, 0, buf, I2C_BUFFER_LENGTH, - STV06XX_URB_MSG_TIMEOUT); - if (err < 0) { - pr_err("I2C: Read error writing address: %d\n", err); - return err; - } - - err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - 0x04, 0xc0, 0x1410, 0, buf, sd->sensor->i2c_len, - STV06XX_URB_MSG_TIMEOUT); - if (sd->sensor->i2c_len == 2) - *value = buf[0] | (buf[1] << 8); - else - *value = buf[0]; - - PDEBUG(D_CONF, "I2C: Read 0x%x from address 0x%x, status: %d", - *value, address, err); - - return (err < 0) ? err : 0; -} - -/* Dumps all bridge registers */ -static void stv06xx_dump_bridge(struct sd *sd) -{ - int i; - u8 data, buf; - - pr_info("Dumping all stv06xx bridge registers\n"); - for (i = 0x1400; i < 0x160f; i++) { - stv06xx_read_bridge(sd, i, &data); - - pr_info("Read 0x%x from address 0x%x\n", data, i); - } - - pr_info("Testing stv06xx bridge registers for writability\n"); - for (i = 0x1400; i < 0x160f; i++) { - stv06xx_read_bridge(sd, i, &data); - buf = data; - - stv06xx_write_bridge(sd, i, 0xff); - stv06xx_read_bridge(sd, i, &data); - if (data == 0xff) - pr_info("Register 0x%x is read/write\n", i); - else if (data != buf) - pr_info("Register 0x%x is read/write, but only partially\n", - i); - else - pr_info("Register 0x%x is read-only\n", i); - - stv06xx_write_bridge(sd, i, buf); - } -} - -/* this function is called at probe and resume time */ -static int stv06xx_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int err; - - PDEBUG(D_PROBE, "Initializing camera"); - - /* Let the usb init settle for a bit - before performing the initialization */ - msleep(250); - - err = sd->sensor->init(sd); - - if (dump_sensor && sd->sensor->dump) - sd->sensor->dump(sd); - - return (err < 0) ? err : 0; -} - -/* this function is called at probe time */ -static int stv06xx_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - PDEBUG(D_PROBE, "Initializing controls"); - - gspca_dev->vdev.ctrl_handler = &gspca_dev->ctrl_handler; - return sd->sensor->init_controls(sd); -} - -/* Start the camera */ -static int stv06xx_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct usb_host_interface *alt; - struct usb_interface *intf; - int err, packet_size; - - intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); - alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); - if (!alt) { - PDEBUG(D_ERR, "Couldn't get altsetting"); - return -EIO; - } - - packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); - err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size); - if (err < 0) - return err; - - /* Prepare the sensor for start */ - err = sd->sensor->start(sd); - if (err < 0) - goto out; - - /* Start isochronous streaming */ - err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 1); - -out: - if (err < 0) - PDEBUG(D_STREAM, "Starting stream failed"); - else - PDEBUG(D_STREAM, "Started streaming"); - - return (err < 0) ? err : 0; -} - -static int stv06xx_isoc_init(struct gspca_dev *gspca_dev) -{ - struct usb_host_interface *alt; - struct sd *sd = (struct sd *) gspca_dev; - - /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ - alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; - alt->endpoint[0].desc.wMaxPacketSize = - cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]); - - return 0; -} - -static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev) -{ - int ret, packet_size, min_packet_size; - struct usb_host_interface *alt; - struct sd *sd = (struct sd *) gspca_dev; - - alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; - packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); - min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode]; - if (packet_size <= min_packet_size) - return -EIO; - - packet_size -= 100; - if (packet_size < min_packet_size) - packet_size = min_packet_size; - alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size); - - ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); - if (ret < 0) - PDEBUG(D_ERR|D_STREAM, "set alt 1 err %d", ret); - - return ret; -} - -static void stv06xx_stopN(struct gspca_dev *gspca_dev) -{ - int err; - struct sd *sd = (struct sd *) gspca_dev; - - /* stop ISO-streaming */ - err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 0); - if (err < 0) - goto out; - - err = sd->sensor->stop(sd); - -out: - if (err < 0) - PDEBUG(D_STREAM, "Failed to stop stream"); - else - PDEBUG(D_STREAM, "Stopped streaming"); -} - -/* - * Analyse an USB packet of the data stream and store it appropriately. - * Each packet contains an integral number of chunks. Each chunk has - * 2-bytes identification, followed by 2-bytes that describe the chunk - * length. Known/guessed chunk identifications are: - * 8001/8005/C001/C005 - Begin new frame - * 8002/8006/C002/C006 - End frame - * 0200/4200 - Contains actual image data, bayer or compressed - * 0005 - 11 bytes of unknown data - * 0100 - 2 bytes of unknown data - * The 0005 and 0100 chunks seem to appear only in compressed stream. - */ -static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - - PDEBUG(D_PACK, "Packet of length %d arrived", len); - - /* A packet may contain several frames - loop until the whole packet is reached */ - while (len) { - int id, chunk_len; - - if (len < 4) { - PDEBUG(D_PACK, "Packet is smaller than 4 bytes"); - return; - } - - /* Capture the id */ - id = (data[0] << 8) | data[1]; - - /* Capture the chunk length */ - chunk_len = (data[2] << 8) | data[3]; - PDEBUG(D_PACK, "Chunk id: %x, length: %d", id, chunk_len); - - data += 4; - len -= 4; - - if (len < chunk_len) { - PDEBUG(D_ERR, "URB packet length is smaller" - " than the specified chunk length"); - gspca_dev->last_packet_type = DISCARD_PACKET; - return; - } - - /* First byte seem to be 02=data 2nd byte is unknown??? */ - if (sd->bridge == BRIDGE_ST6422 && (id & 0xff00) == 0x0200) - goto frame_data; - - switch (id) { - case 0x0200: - case 0x4200: -frame_data: - PDEBUG(D_PACK, "Frame data packet detected"); - - if (sd->to_skip) { - int skip = (sd->to_skip < chunk_len) ? - sd->to_skip : chunk_len; - data += skip; - len -= skip; - chunk_len -= skip; - sd->to_skip -= skip; - } - - gspca_frame_add(gspca_dev, INTER_PACKET, - data, chunk_len); - break; - - case 0x8001: - case 0x8005: - case 0xc001: - case 0xc005: - PDEBUG(D_PACK, "Starting new frame"); - - /* Create a new frame, chunk length should be zero */ - gspca_frame_add(gspca_dev, FIRST_PACKET, - NULL, 0); - - if (sd->bridge == BRIDGE_ST6422) - sd->to_skip = gspca_dev->width * 4; - - if (chunk_len) - PDEBUG(D_ERR, "Chunk length is " - "non-zero on a SOF"); - break; - - case 0x8002: - case 0x8006: - case 0xc002: - PDEBUG(D_PACK, "End of frame detected"); - - /* Complete the last frame (if any) */ - gspca_frame_add(gspca_dev, LAST_PACKET, - NULL, 0); - - if (chunk_len) - PDEBUG(D_ERR, "Chunk length is " - "non-zero on a EOF"); - break; - - case 0x0005: - PDEBUG(D_PACK, "Chunk 0x005 detected"); - /* Unknown chunk with 11 bytes of data, - occurs just before end of each frame - in compressed mode */ - break; - - case 0x0100: - PDEBUG(D_PACK, "Chunk 0x0100 detected"); - /* Unknown chunk with 2 bytes of data, - occurs 2-3 times per USB interrupt */ - break; - case 0x42ff: - PDEBUG(D_PACK, "Chunk 0x42ff detected"); - /* Special chunk seen sometimes on the ST6422 */ - break; - default: - PDEBUG(D_PACK, "Unknown chunk 0x%04x detected", id); - /* Unknown chunk */ - } - data += chunk_len; - len -= chunk_len; - } -} - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) -static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* interrupt packet data */ - int len) /* interrupt packet length */ -{ - int ret = -EINVAL; - - if (len == 1 && data[0] == 0x80) { - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); - input_sync(gspca_dev->input_dev); - ret = 0; - } - - if (len == 1 && data[0] == 0x88) { - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); - input_sync(gspca_dev->input_dev); - ret = 0; - } - - return ret; -} -#endif - -static int stv06xx_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id); - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = stv06xx_config, - .init = stv06xx_init, - .init_controls = stv06xx_init_controls, - .start = stv06xx_start, - .stopN = stv06xx_stopN, - .pkt_scan = stv06xx_pkt_scan, - .isoc_init = stv06xx_isoc_init, - .isoc_nego = stv06xx_isoc_nego, -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .int_pkt_scan = sd_int_pkt_scan, -#endif -}; - -/* This function is called at probe time */ -static int stv06xx_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - - PDEBUG(D_PROBE, "Configuring camera"); - - sd->bridge = id->driver_info; - gspca_dev->sd_desc = &sd_desc; - - if (dump_bridge) - stv06xx_dump_bridge(sd); - - sd->sensor = &stv06xx_sensor_st6422; - if (!sd->sensor->probe(sd)) - return 0; - - sd->sensor = &stv06xx_sensor_vv6410; - if (!sd->sensor->probe(sd)) - return 0; - - sd->sensor = &stv06xx_sensor_hdcs1x00; - if (!sd->sensor->probe(sd)) - return 0; - - sd->sensor = &stv06xx_sensor_hdcs1020; - if (!sd->sensor->probe(sd)) - return 0; - - sd->sensor = &stv06xx_sensor_pb0100; - if (!sd->sensor->probe(sd)) - return 0; - - sd->sensor = NULL; - return -ENODEV; -} - - - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - /* QuickCam Express */ - {USB_DEVICE(0x046d, 0x0840), .driver_info = BRIDGE_STV600 }, - /* LEGO cam / QuickCam Web */ - {USB_DEVICE(0x046d, 0x0850), .driver_info = BRIDGE_STV610 }, - /* Dexxa WebCam USB */ - {USB_DEVICE(0x046d, 0x0870), .driver_info = BRIDGE_STV602 }, - /* QuickCam Messenger */ - {USB_DEVICE(0x046D, 0x08F0), .driver_info = BRIDGE_ST6422 }, - /* QuickCam Communicate */ - {USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 }, - /* QuickCam Messenger (new) */ - {USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 }, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - PDEBUG(D_PROBE, "Probing for a stv06xx device"); - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static void sd_disconnect(struct usb_interface *intf) -{ - struct gspca_dev *gspca_dev = usb_get_intfdata(intf); - struct sd *sd = (struct sd *) gspca_dev; - void *priv = sd->sensor_priv; - PDEBUG(D_PROBE, "Disconnecting the stv06xx device"); - - sd->sensor = NULL; - gspca_disconnect(intf); - kfree(priv); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = sd_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); - -module_param(dump_bridge, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup"); - -module_param(dump_sensor, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(dump_sensor, "Dumps all sensor registers at startup"); diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.h b/drivers/media/video/gspca/stv06xx/stv06xx.h deleted file mode 100644 index 34957a4ec150..000000000000 --- a/drivers/media/video/gspca/stv06xx/stv06xx.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher - * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland - * Copyright (c) 2002, 2003 Tuukka Toivonen - * Copyright (c) 2008 Erik Andrén - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * P/N 861037: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express - * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam - * P/N 861075-0040: Sensor HDCS1000 ASIC - * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB - * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web - */ - -#ifndef STV06XX_H_ -#define STV06XX_H_ - -#include <linux/slab.h> -#include "gspca.h" - -#define MODULE_NAME "STV06xx" - -#define STV_ISOC_ENDPOINT_ADDR 0x81 - -#define STV_R 0x0509 - -#define STV_REG23 0x0423 - -/* Control registers of the STV0600 ASIC */ -#define STV_I2C_PARTNER 0x1420 -#define STV_I2C_VAL_REG_VAL_PAIRS_MIN1 0x1421 -#define STV_I2C_READ_WRITE_TOGGLE 0x1422 -#define STV_I2C_FLUSH 0x1423 -#define STV_I2C_SUCC_READ_REG_VALS 0x1424 - -#define STV_ISO_ENABLE 0x1440 -#define STV_SCAN_RATE 0x1443 -#define STV_LED_CTRL 0x1445 -#define STV_STV0600_EMULATION 0x1446 -#define STV_REG00 0x1500 -#define STV_REG01 0x1501 -#define STV_REG02 0x1502 -#define STV_REG03 0x1503 -#define STV_REG04 0x1504 - -#define STV_ISO_SIZE_L 0x15c1 -#define STV_ISO_SIZE_H 0x15c2 - -/* Refers to the CIF 352x288 and QCIF 176x144 */ -/* 1: 288 lines, 2: 144 lines */ -#define STV_Y_CTRL 0x15c3 - -#define STV_RESET 0x1620 - -/* 0xa: 352 columns, 0x6: 176 columns */ -#define STV_X_CTRL 0x1680 - -#define STV06XX_URB_MSG_TIMEOUT 5000 - -#define I2C_MAX_BYTES 16 -#define I2C_MAX_WORDS 8 - -#define I2C_BUFFER_LENGTH 0x23 -#define I2C_READ_CMD 3 -#define I2C_WRITE_CMD 1 - -#define LED_ON 1 -#define LED_OFF 0 - -/* STV06xx device descriptor */ -struct sd { - struct gspca_dev gspca_dev; - - /* A pointer to the currently connected sensor */ - const struct stv06xx_sensor *sensor; - - /* Sensor private data */ - void *sensor_priv; - - /* The first 4 lines produced by the stv6422 are no good, this keeps - track of how many bytes we still need to skip during a frame */ - int to_skip; - - /* Bridge / Camera type */ - u8 bridge; - #define BRIDGE_STV600 0 - #define BRIDGE_STV602 1 - #define BRIDGE_STV610 2 - #define BRIDGE_ST6422 3 /* With integrated sensor */ -}; - -int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data); -int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data); - -int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len); -int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len); - -int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value); -int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value); - -#endif diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c deleted file mode 100644 index 06fa54c5efb2..000000000000 --- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c +++ /dev/null @@ -1,540 +0,0 @@ -/* - * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher - * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland - * Copyright (c) 2002, 2003 Tuukka Toivonen - * Copyright (c) 2008 Erik Andrén - * Copyright (c) 2008 Chia-I Wu - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * P/N 861037: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express - * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam - * P/N 861075-0040: Sensor HDCS1000 ASIC - * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB - * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "stv06xx_hdcs.h" - -static struct v4l2_pix_format hdcs1x00_mode[] = { - { - HDCS_1X00_DEF_WIDTH, - HDCS_1X00_DEF_HEIGHT, - V4L2_PIX_FMT_SGRBG8, - V4L2_FIELD_NONE, - .sizeimage = - HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT, - .bytesperline = HDCS_1X00_DEF_WIDTH, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 - } -}; - -static struct v4l2_pix_format hdcs1020_mode[] = { - { - HDCS_1020_DEF_WIDTH, - HDCS_1020_DEF_HEIGHT, - V4L2_PIX_FMT_SGRBG8, - V4L2_FIELD_NONE, - .sizeimage = - HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT, - .bytesperline = HDCS_1020_DEF_WIDTH, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 - } -}; - -enum hdcs_power_state { - HDCS_STATE_SLEEP, - HDCS_STATE_IDLE, - HDCS_STATE_RUN -}; - -/* no lock? */ -struct hdcs { - enum hdcs_power_state state; - int w, h; - - /* visible area of the sensor array */ - struct { - int left, top; - int width, height; - int border; - } array; - - struct { - /* Column timing overhead */ - u8 cto; - /* Column processing overhead */ - u8 cpo; - /* Row sample period constant */ - u16 rs; - /* Exposure reset duration */ - u16 er; - } exp; - - int psmp; -}; - -static int hdcs_reg_write_seq(struct sd *sd, u8 reg, u8 *vals, u8 len) -{ - u8 regs[I2C_MAX_BYTES * 2]; - int i; - - if (unlikely((len <= 0) || (len >= I2C_MAX_BYTES) || - (reg + len > 0xff))) - return -EINVAL; - - for (i = 0; i < len; i++) { - regs[2 * i] = reg; - regs[2 * i + 1] = vals[i]; - /* All addresses are shifted left one bit - * as bit 0 toggles r/w */ - reg += 2; - } - - return stv06xx_write_sensor_bytes(sd, regs, len); -} - -static int hdcs_set_state(struct sd *sd, enum hdcs_power_state state) -{ - struct hdcs *hdcs = sd->sensor_priv; - u8 val; - int ret; - - if (hdcs->state == state) - return 0; - - /* we need to go idle before running or sleeping */ - if (hdcs->state != HDCS_STATE_IDLE) { - ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0); - if (ret) - return ret; - } - - hdcs->state = HDCS_STATE_IDLE; - - if (state == HDCS_STATE_IDLE) - return 0; - - switch (state) { - case HDCS_STATE_SLEEP: - val = HDCS_SLEEP_MODE; - break; - - case HDCS_STATE_RUN: - val = HDCS_RUN_ENABLE; - break; - - default: - return -EINVAL; - } - - ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val); - - /* Update the state if the write succeeded */ - if (!ret) - hdcs->state = state; - - return ret; -} - -static int hdcs_reset(struct sd *sd) -{ - struct hdcs *hdcs = sd->sensor_priv; - int err; - - err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 1); - if (err < 0) - return err; - - err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0); - if (err < 0) - hdcs->state = HDCS_STATE_IDLE; - - return err; -} - -static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct hdcs *hdcs = sd->sensor_priv; - int rowexp, srowexp; - int max_srowexp; - /* Column time period */ - int ct; - /* Column processing period */ - int cp; - /* Row processing period */ - int rp; - /* Minimum number of column timing periods - within the column processing period */ - int mnct; - int cycles, err; - u8 exp[14]; - - cycles = val * HDCS_CLK_FREQ_MHZ * 257; - - ct = hdcs->exp.cto + hdcs->psmp + (HDCS_ADC_START_SIG_DUR + 2); - cp = hdcs->exp.cto + (hdcs->w * ct / 2); - - /* the cycles one row takes */ - rp = hdcs->exp.rs + cp; - - rowexp = cycles / rp; - - /* the remaining cycles */ - cycles -= rowexp * rp; - - /* calculate sub-row exposure */ - if (IS_1020(sd)) { - /* see HDCS-1020 datasheet 3.5.6.4, p. 63 */ - srowexp = hdcs->w - (cycles + hdcs->exp.er + 13) / ct; - - mnct = (hdcs->exp.er + 12 + ct - 1) / ct; - max_srowexp = hdcs->w - mnct; - } else { - /* see HDCS-1000 datasheet 3.4.5.5, p. 61 */ - srowexp = cp - hdcs->exp.er - 6 - cycles; - - mnct = (hdcs->exp.er + 5 + ct - 1) / ct; - max_srowexp = cp - mnct * ct - 1; - } - - if (srowexp < 0) - srowexp = 0; - else if (srowexp > max_srowexp) - srowexp = max_srowexp; - - if (IS_1020(sd)) { - exp[0] = HDCS20_CONTROL; - exp[1] = 0x00; /* Stop streaming */ - exp[2] = HDCS_ROWEXPL; - exp[3] = rowexp & 0xff; - exp[4] = HDCS_ROWEXPH; - exp[5] = rowexp >> 8; - exp[6] = HDCS20_SROWEXP; - exp[7] = (srowexp >> 2) & 0xff; - exp[8] = HDCS20_ERROR; - exp[9] = 0x10; /* Clear exposure error flag*/ - exp[10] = HDCS20_CONTROL; - exp[11] = 0x04; /* Restart streaming */ - err = stv06xx_write_sensor_bytes(sd, exp, 6); - } else { - exp[0] = HDCS00_CONTROL; - exp[1] = 0x00; /* Stop streaming */ - exp[2] = HDCS_ROWEXPL; - exp[3] = rowexp & 0xff; - exp[4] = HDCS_ROWEXPH; - exp[5] = rowexp >> 8; - exp[6] = HDCS00_SROWEXPL; - exp[7] = srowexp & 0xff; - exp[8] = HDCS00_SROWEXPH; - exp[9] = srowexp >> 8; - exp[10] = HDCS_STATUS; - exp[11] = 0x10; /* Clear exposure error flag*/ - exp[12] = HDCS00_CONTROL; - exp[13] = 0x04; /* Restart streaming */ - err = stv06xx_write_sensor_bytes(sd, exp, 7); - if (err < 0) - return err; - } - PDEBUG(D_V4L2, "Writing exposure %d, rowexp %d, srowexp %d", - val, rowexp, srowexp); - return err; -} - -static int hdcs_set_gains(struct sd *sd, u8 g) -{ - int err; - u8 gains[4]; - - /* the voltage gain Av = (1 + 19 * val / 127) * (1 + bit7) */ - if (g > 127) - g = 0x80 | (g / 2); - - gains[0] = g; - gains[1] = g; - gains[2] = g; - gains[3] = g; - - err = hdcs_reg_write_seq(sd, HDCS_ERECPGA, gains, 4); - return err; -} - -static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val) -{ - PDEBUG(D_V4L2, "Writing gain %d", val); - return hdcs_set_gains((struct sd *) gspca_dev, - val & 0xff); -} - -static int hdcs_set_size(struct sd *sd, - unsigned int width, unsigned int height) -{ - struct hdcs *hdcs = sd->sensor_priv; - u8 win[4]; - unsigned int x, y; - int err; - - /* must be multiple of 4 */ - width = (width + 3) & ~0x3; - height = (height + 3) & ~0x3; - - if (width > hdcs->array.width) - width = hdcs->array.width; - - if (IS_1020(sd)) { - /* the borders are also invalid */ - if (height + 2 * hdcs->array.border + HDCS_1020_BOTTOM_Y_SKIP - > hdcs->array.height) - height = hdcs->array.height - 2 * hdcs->array.border - - HDCS_1020_BOTTOM_Y_SKIP; - - y = (hdcs->array.height - HDCS_1020_BOTTOM_Y_SKIP - height) / 2 - + hdcs->array.top; - } else { - if (height > hdcs->array.height) - height = hdcs->array.height; - - y = hdcs->array.top + (hdcs->array.height - height) / 2; - } - - x = hdcs->array.left + (hdcs->array.width - width) / 2; - - win[0] = y / 4; - win[1] = x / 4; - win[2] = (y + height) / 4 - 1; - win[3] = (x + width) / 4 - 1; - - err = hdcs_reg_write_seq(sd, HDCS_FWROW, win, 4); - if (err < 0) - return err; - - /* Update the current width and height */ - hdcs->w = width; - hdcs->h = height; - return err; -} - -static int hdcs_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - int err = -EINVAL; - - switch (ctrl->id) { - case V4L2_CID_GAIN: - err = hdcs_set_gain(gspca_dev, ctrl->val); - break; - case V4L2_CID_EXPOSURE: - err = hdcs_set_exposure(gspca_dev, ctrl->val); - break; - } - return err; -} - -static const struct v4l2_ctrl_ops hdcs_ctrl_ops = { - .s_ctrl = hdcs_s_ctrl, -}; - -static int hdcs_init_controls(struct sd *sd) -{ - struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler; - - v4l2_ctrl_handler_init(hdl, 2); - v4l2_ctrl_new_std(hdl, &hdcs_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 0xff, 1, HDCS_DEFAULT_EXPOSURE); - v4l2_ctrl_new_std(hdl, &hdcs_ctrl_ops, - V4L2_CID_GAIN, 0, 0xff, 1, HDCS_DEFAULT_GAIN); - return hdl->error; -} - -static int hdcs_probe_1x00(struct sd *sd) -{ - struct hdcs *hdcs; - u16 sensor; - int ret; - - ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor); - if (ret < 0 || sensor != 0x08) - return -ENODEV; - - pr_info("HDCS-1000/1100 sensor detected\n"); - - sd->gspca_dev.cam.cam_mode = hdcs1x00_mode; - sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1x00_mode); - - hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL); - if (!hdcs) - return -ENOMEM; - - hdcs->array.left = 8; - hdcs->array.top = 8; - hdcs->array.width = HDCS_1X00_DEF_WIDTH; - hdcs->array.height = HDCS_1X00_DEF_HEIGHT; - hdcs->array.border = 4; - - hdcs->exp.cto = 4; - hdcs->exp.cpo = 2; - hdcs->exp.rs = 186; - hdcs->exp.er = 100; - - /* - * Frame rate on HDCS-1000 with STV600 depends on PSMP: - * 4 = doesn't work at all - * 5 = 7.8 fps, - * 6 = 6.9 fps, - * 8 = 6.3 fps, - * 10 = 5.5 fps, - * 15 = 4.4 fps, - * 31 = 2.8 fps - * - * Frame rate on HDCS-1000 with STV602 depends on PSMP: - * 15 = doesn't work at all - * 18 = doesn't work at all - * 19 = 7.3 fps - * 20 = 7.4 fps - * 21 = 7.4 fps - * 22 = 7.4 fps - * 24 = 6.3 fps - * 30 = 5.4 fps - */ - hdcs->psmp = (sd->bridge == BRIDGE_STV602) ? 20 : 5; - - sd->sensor_priv = hdcs; - - return 0; -} - -static int hdcs_probe_1020(struct sd *sd) -{ - struct hdcs *hdcs; - u16 sensor; - int ret; - - ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor); - if (ret < 0 || sensor != 0x10) - return -ENODEV; - - pr_info("HDCS-1020 sensor detected\n"); - - sd->gspca_dev.cam.cam_mode = hdcs1020_mode; - sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1020_mode); - - hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL); - if (!hdcs) - return -ENOMEM; - - /* - * From Andrey's test image: looks like HDCS-1020 upper-left - * visible pixel is at 24,8 (y maybe even smaller?) and lower-right - * visible pixel at 375,299 (x maybe even larger?) - */ - hdcs->array.left = 24; - hdcs->array.top = 4; - hdcs->array.width = HDCS_1020_DEF_WIDTH; - hdcs->array.height = 304; - hdcs->array.border = 4; - - hdcs->psmp = 6; - - hdcs->exp.cto = 3; - hdcs->exp.cpo = 3; - hdcs->exp.rs = 155; - hdcs->exp.er = 96; - - sd->sensor_priv = hdcs; - - return 0; -} - -static int hdcs_start(struct sd *sd) -{ - PDEBUG(D_STREAM, "Starting stream"); - - return hdcs_set_state(sd, HDCS_STATE_RUN); -} - -static int hdcs_stop(struct sd *sd) -{ - PDEBUG(D_STREAM, "Halting stream"); - - return hdcs_set_state(sd, HDCS_STATE_SLEEP); -} - -static int hdcs_init(struct sd *sd) -{ - struct hdcs *hdcs = sd->sensor_priv; - int i, err = 0; - - /* Set the STV0602AA in STV0600 emulation mode */ - if (sd->bridge == BRIDGE_STV602) - stv06xx_write_bridge(sd, STV_STV0600_EMULATION, 1); - - /* Execute the bridge init */ - for (i = 0; i < ARRAY_SIZE(stv_bridge_init) && !err; i++) { - err = stv06xx_write_bridge(sd, stv_bridge_init[i][0], - stv_bridge_init[i][1]); - } - if (err < 0) - return err; - - /* sensor soft reset */ - hdcs_reset(sd); - - /* Execute the sensor init */ - for (i = 0; i < ARRAY_SIZE(stv_sensor_init) && !err; i++) { - err = stv06xx_write_sensor(sd, stv_sensor_init[i][0], - stv_sensor_init[i][1]); - } - if (err < 0) - return err; - - /* Enable continuous frame capture, bit 2: stop when frame complete */ - err = stv06xx_write_sensor(sd, HDCS_REG_CONFIG(sd), BIT(3)); - if (err < 0) - return err; - - /* Set PGA sample duration - (was 0x7E for the STV602, but caused slow framerate with HDCS-1020) */ - if (IS_1020(sd)) - err = stv06xx_write_sensor(sd, HDCS_TCTRL, - (HDCS_ADC_START_SIG_DUR << 6) | hdcs->psmp); - else - err = stv06xx_write_sensor(sd, HDCS_TCTRL, - (HDCS_ADC_START_SIG_DUR << 5) | hdcs->psmp); - if (err < 0) - return err; - - return hdcs_set_size(sd, hdcs->array.width, hdcs->array.height); -} - -static int hdcs_dump(struct sd *sd) -{ - u16 reg, val; - - pr_info("Dumping sensor registers:\n"); - - for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH; reg++) { - stv06xx_read_sensor(sd, reg, &val); - pr_info("reg 0x%02x = 0x%02x\n", reg, val); - } - return 0; -} diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h deleted file mode 100644 index 1ba9158d0102..000000000000 --- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher - * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland - * Copyright (c) 2002, 2003 Tuukka Toivonen - * Copyright (c) 2008 Erik Andrén - * Copyright (c) 2008 Chia-I Wu - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * P/N 861037: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express - * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam - * P/N 861075-0040: Sensor HDCS1000 ASIC - * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB - * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web - */ - -#ifndef STV06XX_HDCS_H_ -#define STV06XX_HDCS_H_ - -#include "stv06xx_sensor.h" - -#define HDCS_REG_CONFIG(sd) (IS_1020(sd) ? HDCS20_CONFIG : HDCS00_CONFIG) -#define HDCS_REG_CONTROL(sd) (IS_1020(sd) ? HDCS20_CONTROL : HDCS00_CONTROL) - -#define HDCS_1X00_DEF_WIDTH 360 -#define HDCS_1X00_DEF_HEIGHT 296 - -#define HDCS_1020_DEF_WIDTH 352 -#define HDCS_1020_DEF_HEIGHT 292 - -#define HDCS_1020_BOTTOM_Y_SKIP 4 - -#define HDCS_CLK_FREQ_MHZ 25 - -#define HDCS_ADC_START_SIG_DUR 3 - -/* LSB bit of I2C or register address signifies write (0) or read (1) */ -/* I2C Registers common for both HDCS-1000/1100 and HDCS-1020 */ -/* Identifications Register */ -#define HDCS_IDENT (0x00 << 1) -/* Status Register */ -#define HDCS_STATUS (0x01 << 1) -/* Interrupt Mask Register */ -#define HDCS_IMASK (0x02 << 1) -/* Pad Control Register */ -#define HDCS_PCTRL (0x03 << 1) -/* Pad Drive Control Register */ -#define HDCS_PDRV (0x04 << 1) -/* Interface Control Register */ -#define HDCS_ICTRL (0x05 << 1) -/* Interface Timing Register */ -#define HDCS_ITMG (0x06 << 1) -/* Baud Fraction Register */ -#define HDCS_BFRAC (0x07 << 1) -/* Baud Rate Register */ -#define HDCS_BRATE (0x08 << 1) -/* ADC Control Register */ -#define HDCS_ADCCTRL (0x09 << 1) -/* First Window Row Register */ -#define HDCS_FWROW (0x0a << 1) -/* First Window Column Register */ -#define HDCS_FWCOL (0x0b << 1) -/* Last Window Row Register */ -#define HDCS_LWROW (0x0c << 1) -/* Last Window Column Register */ -#define HDCS_LWCOL (0x0d << 1) -/* Timing Control Register */ -#define HDCS_TCTRL (0x0e << 1) -/* PGA Gain Register: Even Row, Even Column */ -#define HDCS_ERECPGA (0x0f << 1) -/* PGA Gain Register: Even Row, Odd Column */ -#define HDCS_EROCPGA (0x10 << 1) -/* PGA Gain Register: Odd Row, Even Column */ -#define HDCS_ORECPGA (0x11 << 1) -/* PGA Gain Register: Odd Row, Odd Column */ -#define HDCS_OROCPGA (0x12 << 1) -/* Row Exposure Low Register */ -#define HDCS_ROWEXPL (0x13 << 1) -/* Row Exposure High Register */ -#define HDCS_ROWEXPH (0x14 << 1) - -/* I2C Registers only for HDCS-1000/1100 */ -/* Sub-Row Exposure Low Register */ -#define HDCS00_SROWEXPL (0x15 << 1) -/* Sub-Row Exposure High Register */ -#define HDCS00_SROWEXPH (0x16 << 1) -/* Configuration Register */ -#define HDCS00_CONFIG (0x17 << 1) -/* Control Register */ -#define HDCS00_CONTROL (0x18 << 1) - -/* I2C Registers only for HDCS-1020 */ -/* Sub-Row Exposure Register */ -#define HDCS20_SROWEXP (0x15 << 1) -/* Error Control Register */ -#define HDCS20_ERROR (0x16 << 1) -/* Interface Timing 2 Register */ -#define HDCS20_ITMG2 (0x17 << 1) -/* Interface Control 2 Register */ -#define HDCS20_ICTRL2 (0x18 << 1) -/* Horizontal Blank Register */ -#define HDCS20_HBLANK (0x19 << 1) -/* Vertical Blank Register */ -#define HDCS20_VBLANK (0x1a << 1) -/* Configuration Register */ -#define HDCS20_CONFIG (0x1b << 1) -/* Control Register */ -#define HDCS20_CONTROL (0x1c << 1) - -#define HDCS_RUN_ENABLE (1 << 2) -#define HDCS_SLEEP_MODE (1 << 1) - -#define HDCS_DEFAULT_EXPOSURE 48 -#define HDCS_DEFAULT_GAIN 50 - -static int hdcs_probe_1x00(struct sd *sd); -static int hdcs_probe_1020(struct sd *sd); -static int hdcs_start(struct sd *sd); -static int hdcs_init(struct sd *sd); -static int hdcs_init_controls(struct sd *sd); -static int hdcs_stop(struct sd *sd); -static int hdcs_dump(struct sd *sd); - -static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val); -static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val); - -const struct stv06xx_sensor stv06xx_sensor_hdcs1x00 = { - .name = "HP HDCS-1000/1100", - .i2c_flush = 0, - .i2c_addr = (0x55 << 1), - .i2c_len = 1, - - /* FIXME (see if we can lower min_packet_size, needs testing, and also - adjusting framerate when the bandwidth gets lower) */ - .min_packet_size = { 847 }, - .max_packet_size = { 847 }, - - .init = hdcs_init, - .init_controls = hdcs_init_controls, - .probe = hdcs_probe_1x00, - .start = hdcs_start, - .stop = hdcs_stop, - .dump = hdcs_dump, -}; - -const struct stv06xx_sensor stv06xx_sensor_hdcs1020 = { - .name = "HDCS-1020", - .i2c_flush = 0, - .i2c_addr = (0x55 << 1), - .i2c_len = 1, - - /* FIXME (see if we can lower min_packet_size, needs testing, and also - adjusting framerate when the bandwidthm gets lower) */ - .min_packet_size = { 847 }, - .max_packet_size = { 847 }, - - .init = hdcs_init, - .init_controls = hdcs_init_controls, - .probe = hdcs_probe_1020, - .start = hdcs_start, - .stop = hdcs_stop, - .dump = hdcs_dump, -}; - -static const u16 stv_bridge_init[][2] = { - {STV_ISO_ENABLE, 0}, - {STV_REG23, 0}, - {STV_REG00, 0x1d}, - {STV_REG01, 0xb5}, - {STV_REG02, 0xa8}, - {STV_REG03, 0x95}, - {STV_REG04, 0x07}, - - {STV_SCAN_RATE, 0x20}, - {STV_Y_CTRL, 0x01}, - {STV_X_CTRL, 0x0a} -}; - -static const u8 stv_sensor_init[][2] = { - /* Clear status (writing 1 will clear the corresponding status bit) */ - {HDCS_STATUS, BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1)}, - /* Disable all interrupts */ - {HDCS_IMASK, 0x00}, - {HDCS_PCTRL, BIT(6) | BIT(5) | BIT(1) | BIT(0)}, - {HDCS_PDRV, 0x00}, - {HDCS_ICTRL, BIT(5)}, - {HDCS_ITMG, BIT(4) | BIT(1)}, - /* ADC output resolution to 10 bits */ - {HDCS_ADCCTRL, 10} -}; - -#endif diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c deleted file mode 100644 index cdfc3d05ab6b..000000000000 --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher - * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland - * Copyright (c) 2002, 2003 Tuukka Toivonen - * Copyright (c) 2008 Erik Andrén - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * P/N 861037: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express - * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam - * P/N 861075-0040: Sensor HDCS1000 ASIC - * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB - * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web - */ - -/* - * The spec file for the PB-0100 suggests the following for best quality - * images after the sensor has been reset : - * - * PB_ADCGAINL = R60 = 0x03 (3 dec) : sets low reference of ADC - to produce good black level - * PB_PREADCTRL = R32 = 0x1400 (5120 dec) : Enables global gain changes - through R53 - * PB_ADCMINGAIN = R52 = 0x10 (16 dec) : Sets the minimum gain for - auto-exposure - * PB_ADCGLOBALGAIN = R53 = 0x10 (16 dec) : Sets the global gain - * PB_EXPGAIN = R14 = 0x11 (17 dec) : Sets the auto-exposure value - * PB_UPDATEINT = R23 = 0x02 (2 dec) : Sets the speed on - auto-exposure routine - * PB_CFILLIN = R5 = 0x0E (14 dec) : Sets the frame rate - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "stv06xx_pb0100.h" - -struct pb0100_ctrls { - struct { /* one big happy control cluster... */ - struct v4l2_ctrl *autogain; - struct v4l2_ctrl *gain; - struct v4l2_ctrl *exposure; - struct v4l2_ctrl *red; - struct v4l2_ctrl *blue; - struct v4l2_ctrl *natural; - }; - struct v4l2_ctrl *target; -}; - -static struct v4l2_pix_format pb0100_mode[] = { -/* low res / subsample modes disabled as they are only half res horizontal, - halving the vertical resolution does not seem to work */ - { - 320, - 240, - V4L2_PIX_FMT_SGRBG8, - V4L2_FIELD_NONE, - .sizeimage = 320 * 240, - .bytesperline = 320, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = PB0100_CROP_TO_VGA - }, - { - 352, - 288, - V4L2_PIX_FMT_SGRBG8, - V4L2_FIELD_NONE, - .sizeimage = 352 * 288, - .bytesperline = 352, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - } -}; - -static int pb0100_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - struct pb0100_ctrls *ctrls = sd->sensor_priv; - int err = -EINVAL; - - switch (ctrl->id) { - case V4L2_CID_AUTOGAIN: - err = pb0100_set_autogain(gspca_dev, ctrl->val); - if (err) - break; - if (ctrl->val) - break; - err = pb0100_set_gain(gspca_dev, ctrls->gain->val); - if (err) - break; - err = pb0100_set_exposure(gspca_dev, ctrls->exposure->val); - break; - case V4L2_CTRL_CLASS_USER + 0x1001: - err = pb0100_set_autogain_target(gspca_dev, ctrl->val); - break; - } - return err; -} - -static const struct v4l2_ctrl_ops pb0100_ctrl_ops = { - .s_ctrl = pb0100_s_ctrl, -}; - -static int pb0100_init_controls(struct sd *sd) -{ - struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler; - struct pb0100_ctrls *ctrls; - static const struct v4l2_ctrl_config autogain_target = { - .ops = &pb0100_ctrl_ops, - .id = V4L2_CTRL_CLASS_USER + 0x1000, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Automatic Gain Target", - .max = 255, - .step = 1, - .def = 128, - }; - static const struct v4l2_ctrl_config natural_light = { - .ops = &pb0100_ctrl_ops, - .id = V4L2_CTRL_CLASS_USER + 0x1001, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Natural Light Source", - .max = 1, - .step = 1, - .def = 1, - }; - - ctrls = kzalloc(sizeof(*ctrls), GFP_KERNEL); - if (!ctrls) - return -ENOMEM; - - v4l2_ctrl_handler_init(hdl, 6); - ctrls->autogain = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - ctrls->exposure = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 511, 1, 12); - ctrls->gain = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops, - V4L2_CID_GAIN, 0, 255, 1, 128); - ctrls->red = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops, - V4L2_CID_RED_BALANCE, -255, 255, 1, 0); - ctrls->blue = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops, - V4L2_CID_BLUE_BALANCE, -255, 255, 1, 0); - ctrls->natural = v4l2_ctrl_new_custom(hdl, &natural_light, NULL); - ctrls->target = v4l2_ctrl_new_custom(hdl, &autogain_target, NULL); - if (hdl->error) { - kfree(ctrls); - return hdl->error; - } - sd->sensor_priv = ctrls; - v4l2_ctrl_auto_cluster(5, &ctrls->autogain, 0, false); - return 0; -} - -static int pb0100_probe(struct sd *sd) -{ - u16 sensor; - int err; - - err = stv06xx_read_sensor(sd, PB_IDENT, &sensor); - - if (err < 0) - return -ENODEV; - if ((sensor >> 8) != 0x64) - return -ENODEV; - - pr_info("Photobit pb0100 sensor detected\n"); - - sd->gspca_dev.cam.cam_mode = pb0100_mode; - sd->gspca_dev.cam.nmodes = ARRAY_SIZE(pb0100_mode); - - return 0; -} - -static int pb0100_start(struct sd *sd) -{ - int err, packet_size, max_packet_size; - struct usb_host_interface *alt; - struct usb_interface *intf; - struct cam *cam = &sd->gspca_dev.cam; - u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv; - - intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); - alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); - if (!alt) - return -ENODEV; - packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); - - /* If we don't have enough bandwidth use a lower framerate */ - max_packet_size = sd->sensor->max_packet_size[sd->gspca_dev.curr_mode]; - if (packet_size < max_packet_size) - stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1)); - else - stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(5)|BIT(3)|BIT(1)); - - /* Setup sensor window */ - if (mode & PB0100_CROP_TO_VGA) { - stv06xx_write_sensor(sd, PB_RSTART, 30); - stv06xx_write_sensor(sd, PB_CSTART, 20); - stv06xx_write_sensor(sd, PB_RWSIZE, 240 - 1); - stv06xx_write_sensor(sd, PB_CWSIZE, 320 - 1); - } else { - stv06xx_write_sensor(sd, PB_RSTART, 8); - stv06xx_write_sensor(sd, PB_CSTART, 4); - stv06xx_write_sensor(sd, PB_RWSIZE, 288 - 1); - stv06xx_write_sensor(sd, PB_CWSIZE, 352 - 1); - } - - if (mode & PB0100_SUBSAMPLE) { - stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02); /* Wrong, FIXME */ - stv06xx_write_bridge(sd, STV_X_CTRL, 0x06); - - stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10); - } else { - stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01); - stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a); - /* larger -> slower */ - stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20); - } - - err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3)|BIT(1)); - PDEBUG(D_STREAM, "Started stream, status: %d", err); - - return (err < 0) ? err : 0; -} - -static int pb0100_stop(struct sd *sd) -{ - int err; - - err = stv06xx_write_sensor(sd, PB_ABORTFRAME, 1); - - if (err < 0) - goto out; - - /* Set bit 1 to zero */ - err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3)); - - PDEBUG(D_STREAM, "Halting stream"); -out: - return (err < 0) ? err : 0; -} - -/* FIXME: Sort the init commands out and put them into tables, - this is only for getting the camera to work */ -/* FIXME: No error handling for now, - add this once the init has been converted to proper tables */ -static int pb0100_init(struct sd *sd) -{ - stv06xx_write_bridge(sd, STV_REG00, 1); - stv06xx_write_bridge(sd, STV_SCAN_RATE, 0); - - /* Reset sensor */ - stv06xx_write_sensor(sd, PB_RESET, 1); - stv06xx_write_sensor(sd, PB_RESET, 0); - - /* Disable chip */ - stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3)); - - /* Gain stuff...*/ - stv06xx_write_sensor(sd, PB_PREADCTRL, BIT(12)|BIT(10)|BIT(6)); - stv06xx_write_sensor(sd, PB_ADCGLOBALGAIN, 12); - - /* Set up auto-exposure */ - /* ADC VREF_HI new setting for a transition - from the Expose1 to the Expose2 setting */ - stv06xx_write_sensor(sd, PB_R28, 12); - /* gain max for autoexposure */ - stv06xx_write_sensor(sd, PB_ADCMAXGAIN, 180); - /* gain min for autoexposure */ - stv06xx_write_sensor(sd, PB_ADCMINGAIN, 12); - /* Maximum frame integration time (programmed into R8) - allowed for auto-exposure routine */ - stv06xx_write_sensor(sd, PB_R54, 3); - /* Minimum frame integration time (programmed into R8) - allowed for auto-exposure routine */ - stv06xx_write_sensor(sd, PB_R55, 0); - stv06xx_write_sensor(sd, PB_UPDATEINT, 1); - /* R15 Expose0 (maximum that auto-exposure may use) */ - stv06xx_write_sensor(sd, PB_R15, 800); - /* R17 Expose2 (minimum that auto-exposure may use) */ - stv06xx_write_sensor(sd, PB_R17, 10); - - stv06xx_write_sensor(sd, PB_EXPGAIN, 0); - - /* 0x14 */ - stv06xx_write_sensor(sd, PB_VOFFSET, 0); - /* 0x0D */ - stv06xx_write_sensor(sd, PB_ADCGAINH, 11); - /* Set black level (important!) */ - stv06xx_write_sensor(sd, PB_ADCGAINL, 0); - - /* ??? */ - stv06xx_write_bridge(sd, STV_REG00, 0x11); - stv06xx_write_bridge(sd, STV_REG03, 0x45); - stv06xx_write_bridge(sd, STV_REG04, 0x07); - - /* Scan/timing for the sensor */ - stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1)); - stv06xx_write_sensor(sd, PB_CFILLIN, 14); - stv06xx_write_sensor(sd, PB_VBL, 0); - stv06xx_write_sensor(sd, PB_FINTTIME, 0); - stv06xx_write_sensor(sd, PB_RINTTIME, 123); - - stv06xx_write_bridge(sd, STV_REG01, 0xc2); - stv06xx_write_bridge(sd, STV_REG02, 0xb0); - return 0; -} - -static int pb0100_dump(struct sd *sd) -{ - return 0; -} - -static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - struct sd *sd = (struct sd *) gspca_dev; - struct pb0100_ctrls *ctrls = sd->sensor_priv; - - err = stv06xx_write_sensor(sd, PB_G1GAIN, val); - if (!err) - err = stv06xx_write_sensor(sd, PB_G2GAIN, val); - PDEBUG(D_V4L2, "Set green gain to %d, status: %d", val, err); - - if (!err) - err = pb0100_set_red_balance(gspca_dev, ctrls->red->val); - if (!err) - err = pb0100_set_blue_balance(gspca_dev, ctrls->blue->val); - - return err; -} - -static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - struct sd *sd = (struct sd *) gspca_dev; - struct pb0100_ctrls *ctrls = sd->sensor_priv; - - val += ctrls->gain->val; - if (val < 0) - val = 0; - else if (val > 255) - val = 255; - - err = stv06xx_write_sensor(sd, PB_RGAIN, val); - PDEBUG(D_V4L2, "Set red gain to %d, status: %d", val, err); - - return err; -} - -static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - struct sd *sd = (struct sd *) gspca_dev; - struct pb0100_ctrls *ctrls = sd->sensor_priv; - - val += ctrls->gain->val; - if (val < 0) - val = 0; - else if (val > 255) - val = 255; - - err = stv06xx_write_sensor(sd, PB_BGAIN, val); - PDEBUG(D_V4L2, "Set blue gain to %d, status: %d", val, err); - - return err; -} - -static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - int err; - - err = stv06xx_write_sensor(sd, PB_RINTTIME, val); - PDEBUG(D_V4L2, "Set exposure to %d, status: %d", val, err); - - return err; -} - -static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - struct sd *sd = (struct sd *) gspca_dev; - struct pb0100_ctrls *ctrls = sd->sensor_priv; - - if (val) { - if (ctrls->natural->val) - val = BIT(6)|BIT(4)|BIT(0); - else - val = BIT(4)|BIT(0); - } else - val = 0; - - err = stv06xx_write_sensor(sd, PB_EXPGAIN, val); - PDEBUG(D_V4L2, "Set autogain to %d (natural: %d), status: %d", - val, ctrls->natural->val, err); - - return err; -} - -static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val) -{ - int err, totalpixels, brightpixels, darkpixels; - struct sd *sd = (struct sd *) gspca_dev; - - /* Number of pixels counted by the sensor when subsampling the pixels. - * Slightly larger than the real value to avoid oscillation */ - totalpixels = gspca_dev->width * gspca_dev->height; - totalpixels = totalpixels/(8*8) + totalpixels/(64*64); - - brightpixels = (totalpixels * val) >> 8; - darkpixels = totalpixels - brightpixels; - err = stv06xx_write_sensor(sd, PB_R21, brightpixels); - if (!err) - err = stv06xx_write_sensor(sd, PB_R22, darkpixels); - - PDEBUG(D_V4L2, "Set autogain target to %d, status: %d", val, err); - - return err; -} diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h deleted file mode 100644 index 5071e5353fd3..000000000000 --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher - * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland - * Copyright (c) 2002, 2003 Tuukka Toivonen - * Copyright (c) 2008 Erik Andrén - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * P/N 861037: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express - * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam - * P/N 861075-0040: Sensor HDCS1000 ASIC - * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB - * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web - */ - -#ifndef STV06XX_PB0100_H_ -#define STV06XX_PB0100_H_ - -#include "stv06xx_sensor.h" - -/* mode priv field flags */ -#define PB0100_CROP_TO_VGA 0x01 -#define PB0100_SUBSAMPLE 0x02 - -/* I2C Registers */ -#define PB_IDENT 0x00 /* Chip Version */ -#define PB_RSTART 0x01 /* Row Window Start */ -#define PB_CSTART 0x02 /* Column Window Start */ -#define PB_RWSIZE 0x03 /* Row Window Size */ -#define PB_CWSIZE 0x04 /* Column Window Size */ -#define PB_CFILLIN 0x05 /* Column Fill-In */ -#define PB_VBL 0x06 /* Vertical Blank Count */ -#define PB_CONTROL 0x07 /* Control Mode */ -#define PB_FINTTIME 0x08 /* Integration Time/Frame Unit Count */ -#define PB_RINTTIME 0x09 /* Integration Time/Row Unit Count */ -#define PB_ROWSPEED 0x0a /* Row Speed Control */ -#define PB_ABORTFRAME 0x0b /* Abort Frame */ -#define PB_R12 0x0c /* Reserved */ -#define PB_RESET 0x0d /* Reset */ -#define PB_EXPGAIN 0x0e /* Exposure Gain Command */ -#define PB_R15 0x0f /* Expose0 */ -#define PB_R16 0x10 /* Expose1 */ -#define PB_R17 0x11 /* Expose2 */ -#define PB_R18 0x12 /* Low0_DAC */ -#define PB_R19 0x13 /* Low1_DAC */ -#define PB_R20 0x14 /* Low2_DAC */ -#define PB_R21 0x15 /* Threshold11 */ -#define PB_R22 0x16 /* Threshold0x */ -#define PB_UPDATEINT 0x17 /* Update Interval */ -#define PB_R24 0x18 /* High_DAC */ -#define PB_R25 0x19 /* Trans0H */ -#define PB_R26 0x1a /* Trans1L */ -#define PB_R27 0x1b /* Trans1H */ -#define PB_R28 0x1c /* Trans2L */ -#define PB_R29 0x1d /* Reserved */ -#define PB_R30 0x1e /* Reserved */ -#define PB_R31 0x1f /* Wait to Read */ -#define PB_PREADCTRL 0x20 /* Pixel Read Control Mode */ -#define PB_R33 0x21 /* IREF_VLN */ -#define PB_R34 0x22 /* IREF_VLP */ -#define PB_R35 0x23 /* IREF_VLN_INTEG */ -#define PB_R36 0x24 /* IREF_MASTER */ -#define PB_R37 0x25 /* IDACP */ -#define PB_R38 0x26 /* IDACN */ -#define PB_R39 0x27 /* DAC_Control_Reg */ -#define PB_R40 0x28 /* VCL */ -#define PB_R41 0x29 /* IREF_VLN_ADCIN */ -#define PB_R42 0x2a /* Reserved */ -#define PB_G1GAIN 0x2b /* Green 1 Gain */ -#define PB_BGAIN 0x2c /* Blue Gain */ -#define PB_RGAIN 0x2d /* Red Gain */ -#define PB_G2GAIN 0x2e /* Green 2 Gain */ -#define PB_R47 0x2f /* Dark Row Address */ -#define PB_R48 0x30 /* Dark Row Options */ -#define PB_R49 0x31 /* Reserved */ -#define PB_R50 0x32 /* Image Test Data */ -#define PB_ADCMAXGAIN 0x33 /* Maximum Gain */ -#define PB_ADCMINGAIN 0x34 /* Minimum Gain */ -#define PB_ADCGLOBALGAIN 0x35 /* Global Gain */ -#define PB_R54 0x36 /* Maximum Frame */ -#define PB_R55 0x37 /* Minimum Frame */ -#define PB_R56 0x38 /* Reserved */ -#define PB_VOFFSET 0x39 /* VOFFSET */ -#define PB_R58 0x3a /* Snap-Shot Sequence Trigger */ -#define PB_ADCGAINH 0x3b /* VREF_HI */ -#define PB_ADCGAINL 0x3c /* VREF_LO */ -#define PB_R61 0x3d /* Reserved */ -#define PB_R62 0x3e /* Reserved */ -#define PB_R63 0x3f /* Reserved */ -#define PB_R64 0x40 /* Red/Blue Gain */ -#define PB_R65 0x41 /* Green 2/Green 1 Gain */ -#define PB_R66 0x42 /* VREF_HI/LO */ -#define PB_R67 0x43 /* Integration Time/Row Unit Count */ -#define PB_R240 0xf0 /* ADC Test */ -#define PB_R241 0xf1 /* Chip Enable */ -#define PB_R242 0xf2 /* Reserved */ - -static int pb0100_probe(struct sd *sd); -static int pb0100_start(struct sd *sd); -static int pb0100_init(struct sd *sd); -static int pb0100_init_controls(struct sd *sd); -static int pb0100_stop(struct sd *sd); -static int pb0100_dump(struct sd *sd); - -/* V4L2 controls supported by the driver */ -static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val); -static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); -static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); -static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val); -static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val); -static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val); - -const struct stv06xx_sensor stv06xx_sensor_pb0100 = { - .name = "PB-0100", - .i2c_flush = 1, - .i2c_addr = 0xba, - .i2c_len = 2, - - .min_packet_size = { 635, 847 }, - .max_packet_size = { 847, 923 }, - - .init = pb0100_init, - .init_controls = pb0100_init_controls, - .probe = pb0100_probe, - .start = pb0100_start, - .stop = pb0100_stop, - .dump = pb0100_dump, -}; - -#endif diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h deleted file mode 100644 index 3a498c2495c6..000000000000 --- a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher - * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland - * Copyright (c) 2002, 2003 Tuukka Toivonen - * Copyright (c) 2008 Erik Andrén - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * P/N 861037: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express - * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam - * P/N 861075-0040: Sensor HDCS1000 ASIC - * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB - * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web - */ - -#ifndef STV06XX_SENSOR_H_ -#define STV06XX_SENSOR_H_ - -#include "stv06xx.h" - -#define IS_1020(sd) ((sd)->sensor == &stv06xx_sensor_hdcs1020) - -extern const struct stv06xx_sensor stv06xx_sensor_vv6410; -extern const struct stv06xx_sensor stv06xx_sensor_hdcs1x00; -extern const struct stv06xx_sensor stv06xx_sensor_hdcs1020; -extern const struct stv06xx_sensor stv06xx_sensor_pb0100; -extern const struct stv06xx_sensor stv06xx_sensor_st6422; - -struct stv06xx_sensor { - /* Defines the name of a sensor */ - char name[32]; - - /* Sensor i2c address */ - u8 i2c_addr; - - /* Flush value*/ - u8 i2c_flush; - - /* length of an i2c word */ - u8 i2c_len; - - /* Isoc packet size (per mode) */ - int min_packet_size[4]; - int max_packet_size[4]; - - /* Probes if the sensor is connected */ - int (*probe)(struct sd *sd); - - /* Performs a initialization sequence */ - int (*init)(struct sd *sd); - - /* Initializes the controls */ - int (*init_controls)(struct sd *sd); - - /* Reads a sensor register */ - int (*read_sensor)(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); - - /* Writes to a sensor register */ - int (*write_sensor)(struct sd *sd, const u8 address, - u8 *i2c_data, const u8 len); - - /* Instructs the sensor to start streaming */ - int (*start)(struct sd *sd); - - /* Instructs the sensor to stop streaming */ - int (*stop)(struct sd *sd); - - /* Instructs the sensor to dump all its contents */ - int (*dump)(struct sd *sd); -}; - -#endif diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c deleted file mode 100644 index 8a57990dfe0f..000000000000 --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Support for the sensor part which is integrated (I think) into the - * st6422 stv06xx alike bridge, as its integrated there are no i2c writes - * but instead direct bridge writes. - * - * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com> - * - * Strongly based on qc-usb-messenger, which is: - * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher - * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland - * Copyright (c) 2002, 2003 Tuukka Toivonen - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "stv06xx_st6422.h" - -static struct v4l2_pix_format st6422_mode[] = { - /* Note we actually get 124 lines of data, of which we skip the 4st - 4 as they are garbage */ - { - 162, - 120, - V4L2_PIX_FMT_SGRBG8, - V4L2_FIELD_NONE, - .sizeimage = 162 * 120, - .bytesperline = 162, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1 - }, - /* Note we actually get 248 lines of data, of which we skip the 4st - 4 as they are garbage, and we tell the app it only gets the - first 240 of the 244 lines it actually gets, so that it ignores - the last 4. */ - { - 324, - 240, - V4L2_PIX_FMT_SGRBG8, - V4L2_FIELD_NONE, - .sizeimage = 324 * 244, - .bytesperline = 324, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - }, -}; - -/* V4L2 controls supported by the driver */ -static int setbrightness(struct sd *sd, s32 val); -static int setcontrast(struct sd *sd, s32 val); -static int setgain(struct sd *sd, u8 gain); -static int setexposure(struct sd *sd, s16 expo); - -static int st6422_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - int err = -EINVAL; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - err = setbrightness(sd, ctrl->val); - break; - case V4L2_CID_CONTRAST: - err = setcontrast(sd, ctrl->val); - break; - case V4L2_CID_GAIN: - err = setgain(sd, ctrl->val); - break; - case V4L2_CID_EXPOSURE: - err = setexposure(sd, ctrl->val); - break; - } - - /* commit settings */ - if (err >= 0) - err = stv06xx_write_bridge(sd, 0x143f, 0x01); - sd->gspca_dev.usb_err = err; - return err; -} - -static const struct v4l2_ctrl_ops st6422_ctrl_ops = { - .s_ctrl = st6422_s_ctrl, -}; - -static int st6422_init_controls(struct sd *sd) -{ - struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler; - - v4l2_ctrl_handler_init(hdl, 4); - v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 31, 1, 3); - v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops, - V4L2_CID_CONTRAST, 0, 15, 1, 11); - v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 1023, 1, 256); - v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops, - V4L2_CID_GAIN, 0, 255, 1, 64); - - return hdl->error; -} - -static int st6422_probe(struct sd *sd) -{ - if (sd->bridge != BRIDGE_ST6422) - return -ENODEV; - - pr_info("st6422 sensor detected\n"); - - sd->gspca_dev.cam.cam_mode = st6422_mode; - sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode); - return 0; -} - -static int st6422_init(struct sd *sd) -{ - int err = 0, i; - - const u16 st6422_bridge_init[][2] = { - { STV_ISO_ENABLE, 0x00 }, /* disable capture */ - { 0x1436, 0x00 }, - { 0x1432, 0x03 }, /* 0x00-0x1F brightness */ - { 0x143a, 0xf9 }, /* 0x00-0x0F contrast */ - { 0x0509, 0x38 }, /* R */ - { 0x050a, 0x38 }, /* G */ - { 0x050b, 0x38 }, /* B */ - { 0x050c, 0x2a }, - { 0x050d, 0x01 }, - - - { 0x1431, 0x00 }, /* 0x00-0x07 ??? */ - { 0x1433, 0x34 }, /* 160x120, 0x00-0x01 night filter */ - { 0x1438, 0x18 }, /* 640x480 */ -/* 18 bayes */ -/* 10 compressed? */ - - { 0x1439, 0x00 }, -/* anti-noise? 0xa2 gives a perfect image */ - - { 0x143b, 0x05 }, - { 0x143c, 0x00 }, /* 0x00-0x01 - ??? */ - - -/* shutter time 0x0000-0x03FF */ -/* low value give good picures on moving objects (but requires much light) */ -/* high value gives good picures in darkness (but tends to be overexposed) */ - { 0x143e, 0x01 }, - { 0x143d, 0x00 }, - - { 0x1442, 0xe2 }, -/* write: 1x1x xxxx */ -/* read: 1x1x xxxx */ -/* bit 5 == button pressed and hold if 0 */ -/* write 0xe2,0xea */ - -/* 0x144a */ -/* 0x00 init */ -/* bit 7 == button has been pressed, but not handled */ - -/* interrupt */ -/* if(urb->iso_frame_desc[i].status == 0x80) { */ -/* if(urb->iso_frame_desc[i].status == 0x88) { */ - - { 0x1500, 0xd0 }, - { 0x1500, 0xd0 }, - { 0x1500, 0x50 }, /* 0x00 - 0xFF 0x80 == compr ? */ - - { 0x1501, 0xaf }, -/* high val-> light area gets darker */ -/* low val -> light area gets lighter */ - { 0x1502, 0xc2 }, -/* high val-> light area gets darker */ -/* low val -> light area gets lighter */ - { 0x1503, 0x45 }, -/* high val-> light area gets darker */ -/* low val -> light area gets lighter */ - { 0x1505, 0x02 }, -/* 2 : 324x248 80352 bytes */ -/* 7 : 248x162 40176 bytes */ -/* c+f: 162*124 20088 bytes */ - - { 0x150e, 0x8e }, - { 0x150f, 0x37 }, - { 0x15c0, 0x00 }, - { 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? */ - - - { 0x143f, 0x01 }, /* commit settings */ - - }; - - for (i = 0; i < ARRAY_SIZE(st6422_bridge_init) && !err; i++) { - err = stv06xx_write_bridge(sd, st6422_bridge_init[i][0], - st6422_bridge_init[i][1]); - } - - return err; -} - -static int setbrightness(struct sd *sd, s32 val) -{ - /* val goes from 0 -> 31 */ - return stv06xx_write_bridge(sd, 0x1432, val); -} - -static int setcontrast(struct sd *sd, s32 val) -{ - /* Val goes from 0 -> 15 */ - return stv06xx_write_bridge(sd, 0x143a, val | 0xf0); -} - -static int setgain(struct sd *sd, u8 gain) -{ - int err; - - /* Set red, green, blue, gain */ - err = stv06xx_write_bridge(sd, 0x0509, gain); - if (err < 0) - return err; - - err = stv06xx_write_bridge(sd, 0x050a, gain); - if (err < 0) - return err; - - err = stv06xx_write_bridge(sd, 0x050b, gain); - if (err < 0) - return err; - - /* 2 mystery writes */ - err = stv06xx_write_bridge(sd, 0x050c, 0x2a); - if (err < 0) - return err; - - return stv06xx_write_bridge(sd, 0x050d, 0x01); -} - -static int setexposure(struct sd *sd, s16 expo) -{ - int err; - - err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff); - if (err < 0) - return err; - - return stv06xx_write_bridge(sd, 0x143e, expo >> 8); -} - -static int st6422_start(struct sd *sd) -{ - int err; - struct cam *cam = &sd->gspca_dev.cam; - - if (cam->cam_mode[sd->gspca_dev.curr_mode].priv) - err = stv06xx_write_bridge(sd, 0x1505, 0x0f); - else - err = stv06xx_write_bridge(sd, 0x1505, 0x02); - if (err < 0) - return err; - - /* commit settings */ - err = stv06xx_write_bridge(sd, 0x143f, 0x01); - return (err < 0) ? err : 0; -} - -static int st6422_stop(struct sd *sd) -{ - PDEBUG(D_STREAM, "Halting stream"); - - return 0; -} diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h deleted file mode 100644 index 8f20fbf30f33..000000000000 --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Support for the sensor part which is integrated (I think) into the - * st6422 stv06xx alike bridge, as its integrated there are no i2c writes - * but instead direct bridge writes. - * - * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com> - * - * Strongly based on qc-usb-messenger, which is: - * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher - * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland - * Copyright (c) 2002, 2003 Tuukka Toivonen - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef STV06XX_ST6422_H_ -#define STV06XX_ST6422_H_ - -#include "stv06xx_sensor.h" - -static int st6422_probe(struct sd *sd); -static int st6422_start(struct sd *sd); -static int st6422_init(struct sd *sd); -static int st6422_init_controls(struct sd *sd); -static int st6422_stop(struct sd *sd); - -const struct stv06xx_sensor stv06xx_sensor_st6422 = { - .name = "ST6422", - /* No known way to lower framerate in case of less bandwidth */ - .min_packet_size = { 300, 847 }, - .max_packet_size = { 300, 847 }, - .init = st6422_init, - .init_controls = st6422_init_controls, - .probe = st6422_probe, - .start = st6422_start, - .stop = st6422_stop, -}; - -#endif diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c deleted file mode 100644 index 748e1421d6d8..000000000000 --- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher - * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland - * Copyright (c) 2002, 2003 Tuukka Toivonen - * Copyright (c) 2008 Erik Andrén - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * P/N 861037: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express - * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam - * P/N 861075-0040: Sensor HDCS1000 ASIC - * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB - * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "stv06xx_vv6410.h" - -static struct v4l2_pix_format vv6410_mode[] = { - { - 356, - 292, - V4L2_PIX_FMT_SGRBG8, - V4L2_FIELD_NONE, - .sizeimage = 356 * 292, - .bytesperline = 356, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0 - } -}; - -static int vv6410_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - int err = -EINVAL; - - switch (ctrl->id) { - case V4L2_CID_HFLIP: - err = vv6410_set_hflip(gspca_dev, ctrl->val); - break; - case V4L2_CID_VFLIP: - err = vv6410_set_vflip(gspca_dev, ctrl->val); - break; - case V4L2_CID_GAIN: - err = vv6410_set_analog_gain(gspca_dev, ctrl->val); - break; - case V4L2_CID_EXPOSURE: - err = vv6410_set_exposure(gspca_dev, ctrl->val); - break; - } - return err; -} - -static const struct v4l2_ctrl_ops vv6410_ctrl_ops = { - .s_ctrl = vv6410_s_ctrl, -}; - -static int vv6410_probe(struct sd *sd) -{ - u16 data; - int err; - - err = stv06xx_read_sensor(sd, VV6410_DEVICEH, &data); - if (err < 0) - return -ENODEV; - - if (data != 0x19) - return -ENODEV; - - pr_info("vv6410 sensor detected\n"); - - sd->gspca_dev.cam.cam_mode = vv6410_mode; - sd->gspca_dev.cam.nmodes = ARRAY_SIZE(vv6410_mode); - return 0; -} - -static int vv6410_init_controls(struct sd *sd) -{ - struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler; - - v4l2_ctrl_handler_init(hdl, 4); - v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops, - V4L2_CID_HFLIP, 0, 1, 1, 0); - v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops, - V4L2_CID_VFLIP, 0, 1, 1, 0); - v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 32768, 1, 20000); - v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops, - V4L2_CID_GAIN, 0, 15, 1, 10); - return hdl->error; -} - -static int vv6410_init(struct sd *sd) -{ - int err = 0, i; - - for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++) - stv06xx_write_bridge(sd, stv_bridge_init[i].addr, stv_bridge_init[i].data); - - if (err < 0) - return err; - - err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init, - ARRAY_SIZE(vv6410_sensor_init)); - return (err < 0) ? err : 0; -} - -static int vv6410_start(struct sd *sd) -{ - int err; - struct cam *cam = &sd->gspca_dev.cam; - u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv; - - if (priv & VV6410_SUBSAMPLE) { - PDEBUG(D_CONF, "Enabling subsampling"); - stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02); - stv06xx_write_bridge(sd, STV_X_CTRL, 0x06); - - stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10); - } else { - stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01); - stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a); - stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x00); - - } - - /* Turn on LED */ - err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_ON); - if (err < 0) - return err; - - err = stv06xx_write_sensor(sd, VV6410_SETUP0, 0); - if (err < 0) - return err; - - PDEBUG(D_STREAM, "Starting stream"); - - return 0; -} - -static int vv6410_stop(struct sd *sd) -{ - int err; - - /* Turn off LED */ - err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_OFF); - if (err < 0) - return err; - - err = stv06xx_write_sensor(sd, VV6410_SETUP0, VV6410_LOW_POWER_MODE); - if (err < 0) - return err; - - PDEBUG(D_STREAM, "Halting stream"); - - return (err < 0) ? err : 0; -} - -static int vv6410_dump(struct sd *sd) -{ - u8 i; - int err = 0; - - pr_info("Dumping all vv6410 sensor registers\n"); - for (i = 0; i < 0xff && !err; i++) { - u16 data; - err = stv06xx_read_sensor(sd, i, &data); - pr_info("Register 0x%x contained 0x%x\n", i, data); - } - return (err < 0) ? err : 0; -} - -static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u16 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - - err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data); - if (err < 0) - return err; - - if (val) - i2c_data |= VV6410_HFLIP; - else - i2c_data &= ~VV6410_HFLIP; - - PDEBUG(D_V4L2, "Set horizontal flip to %d", val); - err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data); - - return (err < 0) ? err : 0; -} - -static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - u16 i2c_data; - struct sd *sd = (struct sd *) gspca_dev; - - err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data); - if (err < 0) - return err; - - if (val) - i2c_data |= VV6410_VFLIP; - else - i2c_data &= ~VV6410_VFLIP; - - PDEBUG(D_V4L2, "Set vertical flip to %d", val); - err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data); - - return (err < 0) ? err : 0; -} - -static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - struct sd *sd = (struct sd *) gspca_dev; - - PDEBUG(D_V4L2, "Set analog gain to %d", val); - err = stv06xx_write_sensor(sd, VV6410_ANALOGGAIN, 0xf0 | (val & 0xf)); - - return (err < 0) ? err : 0; -} - -static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val) -{ - int err; - struct sd *sd = (struct sd *) gspca_dev; - unsigned int fine, coarse; - - val = (val * val >> 14) + val / 4; - - fine = val % VV6410_CIF_LINELENGTH; - coarse = min(512, val / VV6410_CIF_LINELENGTH); - - PDEBUG(D_V4L2, "Set coarse exposure to %d, fine expsure to %d", - coarse, fine); - - err = stv06xx_write_sensor(sd, VV6410_FINEH, fine >> 8); - if (err < 0) - goto out; - - err = stv06xx_write_sensor(sd, VV6410_FINEL, fine & 0xff); - if (err < 0) - goto out; - - err = stv06xx_write_sensor(sd, VV6410_COARSEH, coarse >> 8); - if (err < 0) - goto out; - - err = stv06xx_write_sensor(sd, VV6410_COARSEL, coarse & 0xff); - -out: - return err; -} diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h deleted file mode 100644 index 53e67b40ca05..000000000000 --- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher - * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland - * Copyright (c) 2002, 2003 Tuukka Toivonen - * Copyright (c) 2008 Erik Andrén - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * P/N 861037: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0010: Sensor HDCS1000 ASIC STV0600 - * P/N 861050-0020: Sensor Photobit PB100 ASIC STV0600-1 - QuickCam Express - * P/N 861055: Sensor ST VV6410 ASIC STV0610 - LEGO cam - * P/N 861075-0040: Sensor HDCS1000 ASIC - * P/N 961179-0700: Sensor ST VV6410 ASIC STV0602 - Dexxa WebCam USB - * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web - */ - -#ifndef STV06XX_VV6410_H_ -#define STV06XX_VV6410_H_ - -#include "stv06xx_sensor.h" - -#define VV6410_COLS 416 -#define VV6410_ROWS 320 - -/* Status registers */ -/* Chip identification number including revision indicator */ -#define VV6410_DEVICEH 0x00 -#define VV6410_DEVICEL 0x01 - -/* User can determine whether timed I2C data - has been consumed by interrogating flag states */ -#define VV6410_STATUS0 0x02 - -/* Current line counter value */ -#define VV6410_LINECOUNTH 0x03 -#define VV6410_LINECOUNTL 0x04 - -/* End x coordinate of image size */ -#define VV6410_XENDH 0x05 -#define VV6410_XENDL 0x06 - -/* End y coordinate of image size */ -#define VV6410_YENDH 0x07 -#define VV6410_YENDL 0x08 - -/* This is the average pixel value returned from the - dark line offset cancellation algorithm */ -#define VV6410_DARKAVGH 0x09 -#define VV6410_DARKAVGL 0x0a - -/* This is the average pixel value returned from the - black line offset cancellation algorithm */ -#define VV6410_BLACKAVGH 0x0b -#define VV6410_BLACKAVGL 0x0c - -/* Flags to indicate whether the x or y image coordinates have been clipped */ -#define VV6410_STATUS1 0x0d - -/* Setup registers */ - -/* Low-power/sleep modes & video timing */ -#define VV6410_SETUP0 0x10 - -/* Various parameters */ -#define VV6410_SETUP1 0x11 - -/* Contains pixel counter reset value used by external sync */ -#define VV6410_SYNCVALUE 0x12 - -/* Frame grabbing modes (FST, LST and QCK) */ -#define VV6410_FGMODES 0x14 - -/* FST and QCK mapping modes. */ -#define VV6410_PINMAPPING 0x15 - -/* Data resolution */ -#define VV6410_DATAFORMAT 0x16 - -/* Output coding formats */ -#define VV6410_OPFORMAT 0x17 - -/* Various mode select bits */ -#define VV6410_MODESELECT 0x18 - -/* Exposure registers */ -/* Fine exposure. */ -#define VV6410_FINEH 0x20 -#define VV6410_FINEL 0x21 - -/* Coarse exposure */ -#define VV6410_COARSEH 0x22 -#define VV6410_COARSEL 0x23 - -/* Analog gain setting */ -#define VV6410_ANALOGGAIN 0x24 - -/* Clock division */ -#define VV6410_CLKDIV 0x25 - -/* Dark line offset cancellation value */ -#define VV6410_DARKOFFSETH 0x2c -#define VV6410_DARKOFFSETL 0x2d - -/* Dark line offset cancellation enable */ -#define VV6410_DARKOFFSETSETUP 0x2e - -/* Video timing registers */ -/* Line Length (Pixel Clocks) */ -#define VV6410_LINELENGTHH 0x52 -#define VV6410_LINELENGTHL 0x53 - -/* X-co-ordinate of top left corner of region of interest (x-offset) */ -#define VV6410_XOFFSETH 0x57 -#define VV6410_XOFFSETL 0x58 - -/* Y-coordinate of top left corner of region of interest (y-offset) */ -#define VV6410_YOFFSETH 0x59 -#define VV6410_YOFFSETL 0x5a - -/* Field length (Lines) */ -#define VV6410_FIELDLENGTHH 0x61 -#define VV6410_FIELDLENGTHL 0x62 - -/* System registers */ -/* Black offset cancellation default value */ -#define VV6410_BLACKOFFSETH 0x70 -#define VV6410_BLACKOFFSETL 0x71 - -/* Black offset cancellation setup */ -#define VV6410_BLACKOFFSETSETUP 0x72 - -/* Analog Control Register 0 */ -#define VV6410_CR0 0x75 - -/* Analog Control Register 1 */ -#define VV6410_CR1 0x76 - -/* ADC Setup Register */ -#define VV6410_AS0 0x77 - -/* Analog Test Register */ -#define VV6410_AT0 0x78 - -/* Audio Amplifier Setup Register */ -#define VV6410_AT1 0x79 - -#define VV6410_HFLIP (1 << 3) -#define VV6410_VFLIP (1 << 4) - -#define VV6410_LOW_POWER_MODE (1 << 0) -#define VV6410_SOFT_RESET (1 << 2) -#define VV6410_PAL_25_FPS (0 << 3) - -#define VV6410_CLK_DIV_2 (1 << 1) - -#define VV6410_FINE_EXPOSURE 320 -#define VV6410_COARSE_EXPOSURE 192 -#define VV6410_DEFAULT_GAIN 5 - -#define VV6410_SUBSAMPLE 0x01 -#define VV6410_CROP_TO_QVGA 0x02 - -#define VV6410_CIF_LINELENGTH 415 - -static int vv6410_probe(struct sd *sd); -static int vv6410_start(struct sd *sd); -static int vv6410_init(struct sd *sd); -static int vv6410_init_controls(struct sd *sd); -static int vv6410_stop(struct sd *sd); -static int vv6410_dump(struct sd *sd); - -/* V4L2 controls supported by the driver */ -static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val); -static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val); -static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val); -static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val); - -const struct stv06xx_sensor stv06xx_sensor_vv6410 = { - .name = "ST VV6410", - .i2c_flush = 5, - .i2c_addr = 0x20, - .i2c_len = 1, - /* FIXME (see if we can lower packet_size-s, needs testing, and also - adjusting framerate when the bandwidth gets lower) */ - .min_packet_size = { 1023 }, - .max_packet_size = { 1023 }, - .init = vv6410_init, - .init_controls = vv6410_init_controls, - .probe = vv6410_probe, - .start = vv6410_start, - .stop = vv6410_stop, - .dump = vv6410_dump, -}; - -/* If NULL, only single value to write, stored in len */ -struct stv_init { - u16 addr; - u8 data; -}; - -static const struct stv_init stv_bridge_init[] = { - /* This reg is written twice. Some kind of reset? */ - {STV_RESET, 0x80}, - {STV_RESET, 0x00}, - {STV_SCAN_RATE, 0x00}, - {STV_I2C_FLUSH, 0x04}, - {STV_REG00, 0x0b}, - {STV_REG01, 0xa7}, - {STV_REG02, 0xb7}, - {STV_REG03, 0x00}, - {STV_REG04, 0x00}, - {0x1536, 0x02}, - {0x1537, 0x00}, - {0x1538, 0x60}, - {0x1539, 0x01}, - {0x153a, 0x20}, - {0x153b, 0x01}, -}; - -static const u8 vv6410_sensor_init[][2] = { - /* Setup registers */ - {VV6410_SETUP0, VV6410_SOFT_RESET}, - {VV6410_SETUP0, VV6410_LOW_POWER_MODE}, - /* Use shuffled read-out mode */ - {VV6410_SETUP1, BIT(6)}, - /* All modes to 1, FST, Fast QCK, Free running QCK, Free running LST, FST will qualify visible pixels */ - {VV6410_FGMODES, BIT(6) | BIT(4) | BIT(2) | BIT(0)}, - {VV6410_PINMAPPING, 0x00}, - /* Pre-clock generator divide off */ - {VV6410_DATAFORMAT, BIT(7) | BIT(0)}, - - {VV6410_CLKDIV, VV6410_CLK_DIV_2}, - - /* System registers */ - /* Enable voltage doubler */ - {VV6410_AS0, BIT(6) | BIT(4) | BIT(3) | BIT(2) | BIT(1)}, - {VV6410_AT0, 0x00}, - /* Power up audio, differential */ - {VV6410_AT1, BIT(4) | BIT(0)}, -}; - -#endif diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c deleted file mode 100644 index 9ccfcb1c6479..000000000000 --- a/drivers/media/video/gspca/sunplus.c +++ /dev/null @@ -1,1085 +0,0 @@ -/* - * Sunplus spca504(abc) spca533 spca536 library - * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr - * - * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "sunplus" - -#include "gspca.h" -#include "jpeg.h" - -MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); -MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver"); -MODULE_LICENSE("GPL"); - -#define QUALITY 85 - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - bool autogain; - - u8 bridge; -#define BRIDGE_SPCA504 0 -#define BRIDGE_SPCA504B 1 -#define BRIDGE_SPCA504C 2 -#define BRIDGE_SPCA533 3 -#define BRIDGE_SPCA536 4 - u8 subtype; -#define AiptekMiniPenCam13 1 -#define LogitechClickSmart420 2 -#define LogitechClickSmart820 3 -#define MegapixV4 4 -#define MegaImageVI 5 - - u8 jpeg_hdr[JPEG_HDR_SZ]; -}; - -static const struct v4l2_pix_format vga_mode[] = { - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, -}; - -static const struct v4l2_pix_format custom_mode[] = { - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2}, - {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 464, - .sizeimage = 464 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, -}; - -static const struct v4l2_pix_format vga_mode2[] = { - {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 4}, - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 3}, - {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, -}; - -#define SPCA50X_OFFSET_DATA 10 -#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3 -#define SPCA504_PCCAM600_OFFSET_COMPRESS 4 -#define SPCA504_PCCAM600_OFFSET_MODE 5 -#define SPCA504_PCCAM600_OFFSET_DATA 14 - /* Frame packet header offsets for the spca533 */ -#define SPCA533_OFFSET_DATA 16 -#define SPCA533_OFFSET_FRAMSEQ 15 -/* Frame packet header offsets for the spca536 */ -#define SPCA536_OFFSET_DATA 4 -#define SPCA536_OFFSET_FRAMSEQ 1 - -struct cmd { - u8 req; - u16 val; - u16 idx; -}; - -/* Initialisation data for the Creative PC-CAM 600 */ -static const struct cmd spca504_pccam600_init_data[] = { -/* {0xa0, 0x0000, 0x0503}, * capture mode */ - {0x00, 0x0000, 0x2000}, - {0x00, 0x0013, 0x2301}, - {0x00, 0x0003, 0x2000}, - {0x00, 0x0001, 0x21ac}, - {0x00, 0x0001, 0x21a6}, - {0x00, 0x0000, 0x21a7}, /* brightness */ - {0x00, 0x0020, 0x21a8}, /* contrast */ - {0x00, 0x0001, 0x21ac}, /* sat/hue */ - {0x00, 0x0000, 0x21ad}, /* hue */ - {0x00, 0x001a, 0x21ae}, /* saturation */ - {0x00, 0x0002, 0x21a3}, /* gamma */ - {0x30, 0x0154, 0x0008}, - {0x30, 0x0004, 0x0006}, - {0x30, 0x0258, 0x0009}, - {0x30, 0x0004, 0x0000}, - {0x30, 0x0093, 0x0004}, - {0x30, 0x0066, 0x0005}, - {0x00, 0x0000, 0x2000}, - {0x00, 0x0013, 0x2301}, - {0x00, 0x0003, 0x2000}, - {0x00, 0x0013, 0x2301}, - {0x00, 0x0003, 0x2000}, -}; - -/* Creative PC-CAM 600 specific open data, sent before using the - * generic initialisation data from spca504_open_data. - */ -static const struct cmd spca504_pccam600_open_data[] = { - {0x00, 0x0001, 0x2501}, - {0x20, 0x0500, 0x0001}, /* snapshot mode */ - {0x00, 0x0003, 0x2880}, - {0x00, 0x0001, 0x2881}, -}; - -/* Initialisation data for the logitech clicksmart 420 */ -static const struct cmd spca504A_clicksmart420_init_data[] = { -/* {0xa0, 0x0000, 0x0503}, * capture mode */ - {0x00, 0x0000, 0x2000}, - {0x00, 0x0013, 0x2301}, - {0x00, 0x0003, 0x2000}, - {0x00, 0x0001, 0x21ac}, - {0x00, 0x0001, 0x21a6}, - {0x00, 0x0000, 0x21a7}, /* brightness */ - {0x00, 0x0020, 0x21a8}, /* contrast */ - {0x00, 0x0001, 0x21ac}, /* sat/hue */ - {0x00, 0x0000, 0x21ad}, /* hue */ - {0x00, 0x001a, 0x21ae}, /* saturation */ - {0x00, 0x0002, 0x21a3}, /* gamma */ - {0x30, 0x0004, 0x000a}, - {0xb0, 0x0001, 0x0000}, - - {0xa1, 0x0080, 0x0001}, - {0x30, 0x0049, 0x0000}, - {0x30, 0x0060, 0x0005}, - {0x0c, 0x0004, 0x0000}, - {0x00, 0x0000, 0x0000}, - {0x00, 0x0000, 0x2000}, - {0x00, 0x0013, 0x2301}, - {0x00, 0x0003, 0x2000}, -}; - -/* clicksmart 420 open data ? */ -static const struct cmd spca504A_clicksmart420_open_data[] = { - {0x00, 0x0001, 0x2501}, - {0x20, 0x0502, 0x0000}, - {0x06, 0x0000, 0x0000}, - {0x00, 0x0004, 0x2880}, - {0x00, 0x0001, 0x2881}, - - {0xa0, 0x0000, 0x0503}, -}; - -static const u8 qtable_creative_pccam[2][64] = { - { /* Q-table Y-components */ - 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12, - 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11, - 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11, - 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13, - 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17, - 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c, - 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e, - 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e}, - { /* Q-table C-components */ - 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, - 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e} -}; - -/* FIXME: This Q-table is identical to the Creative PC-CAM one, - * except for one byte. Possibly a typo? - * NWG: 18/05/2003. - */ -static const u8 qtable_spca504_default[2][64] = { - { /* Q-table Y-components */ - 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12, - 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11, - 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11, - 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13, - 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17, - 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c, - 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e, - 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e, - }, - { /* Q-table C-components */ - 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, - 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e} -}; - -/* read <len> bytes to gspca_dev->usb_buf */ -static void reg_r(struct gspca_dev *gspca_dev, - u8 req, - u16 index, - u16 len) -{ - int ret; - -#ifdef GSPCA_DEBUG - if (len > USB_BUF_SZ) { - pr_err("reg_r: buffer overflow\n"); - return; - } -#endif - if (gspca_dev->usb_err < 0) - return; - ret = usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, /* value */ - index, - len ? gspca_dev->usb_buf : NULL, len, - 500); - if (ret < 0) { - pr_err("reg_r err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -/* write one byte */ -static void reg_w_1(struct gspca_dev *gspca_dev, - u8 req, - u16 value, - u16 index, - u16 byte) -{ - int ret; - - if (gspca_dev->usb_err < 0) - return; - gspca_dev->usb_buf[0] = byte; - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, - gspca_dev->usb_buf, 1, - 500); - if (ret < 0) { - pr_err("reg_w_1 err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -/* write req / index / value */ -static void reg_w_riv(struct gspca_dev *gspca_dev, - u8 req, u16 index, u16 value) -{ - struct usb_device *dev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return; - ret = usb_control_msg(dev, - usb_sndctrlpipe(dev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, NULL, 0, 500); - if (ret < 0) { - pr_err("reg_w_riv err %d\n", ret); - gspca_dev->usb_err = ret; - return; - } - PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x", - req, index, value); -} - -static void write_vector(struct gspca_dev *gspca_dev, - const struct cmd *data, int ncmds) -{ - while (--ncmds >= 0) { - reg_w_riv(gspca_dev, data->req, data->idx, data->val); - data++; - } -} - -static void setup_qtable(struct gspca_dev *gspca_dev, - const u8 qtable[2][64]) -{ - int i; - - /* loop over y components */ - for (i = 0; i < 64; i++) - reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]); - - /* loop over c components */ - for (i = 0; i < 64; i++) - reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]); -} - -static void spca504_acknowledged_command(struct gspca_dev *gspca_dev, - u8 req, u16 idx, u16 val) -{ - reg_w_riv(gspca_dev, req, idx, val); - reg_r(gspca_dev, 0x01, 0x0001, 1); - PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]); - reg_w_riv(gspca_dev, req, idx, val); - - msleep(200); - reg_r(gspca_dev, 0x01, 0x0001, 1); - PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]); -} - -#ifdef GSPCA_DEBUG -static void spca504_read_info(struct gspca_dev *gspca_dev) -{ - int i; - u8 info[6]; - - for (i = 0; i < 6; i++) { - reg_r(gspca_dev, 0, i, 1); - info[i] = gspca_dev->usb_buf[0]; - } - PDEBUG(D_STREAM, - "Read info: %d %d %d %d %d %d." - " Should be 1,0,2,2,0,0", - info[0], info[1], info[2], - info[3], info[4], info[5]); -} -#endif - -static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, - u8 req, - u16 idx, u16 val, u8 endcode, u8 count) -{ - u16 status; - - reg_w_riv(gspca_dev, req, idx, val); - reg_r(gspca_dev, 0x01, 0x0001, 1); - if (gspca_dev->usb_err < 0) - return; - PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x", - gspca_dev->usb_buf[0], endcode); - if (!count) - return; - count = 200; - while (--count > 0) { - msleep(10); - /* gsmart mini2 write a each wait setting 1 ms is enough */ -/* reg_w_riv(gspca_dev, req, idx, val); */ - reg_r(gspca_dev, 0x01, 0x0001, 1); - status = gspca_dev->usb_buf[0]; - if (status == endcode) { - PDEBUG(D_FRAM, "status 0x%04x after wait %d", - status, 200 - count); - break; - } - } -} - -static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev) -{ - int count = 10; - - while (--count > 0) { - reg_r(gspca_dev, 0x21, 0, 1); - if ((gspca_dev->usb_buf[0] & 0x01) == 0) - break; - msleep(10); - } -} - -static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev) -{ - int count = 50; - - while (--count > 0) { - reg_r(gspca_dev, 0x21, 1, 1); - if (gspca_dev->usb_buf[0] != 0) { - reg_w_1(gspca_dev, 0x21, 0, 1, 0); - reg_r(gspca_dev, 0x21, 1, 1); - spca504B_PollingDataReady(gspca_dev); - break; - } - msleep(10); - } -} - -#ifdef GSPCA_DEBUG -static void spca50x_GetFirmware(struct gspca_dev *gspca_dev) -{ - u8 *data; - - data = gspca_dev->usb_buf; - reg_r(gspca_dev, 0x20, 0, 5); - PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d", - data[0], data[1], data[2], data[3], data[4]); - reg_r(gspca_dev, 0x23, 0, 64); - reg_r(gspca_dev, 0x23, 1, 64); -} -#endif - -static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 Size; - - Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - switch (sd->bridge) { - case BRIDGE_SPCA533: - reg_w_riv(gspca_dev, 0x31, 0, 0); - spca504B_WaitCmdStatus(gspca_dev); - spca504B_PollingDataReady(gspca_dev); -#ifdef GSPCA_DEBUG - spca50x_GetFirmware(gspca_dev); -#endif - reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */ - reg_r(gspca_dev, 0x24, 8, 1); - - reg_w_1(gspca_dev, 0x25, 0, 4, Size); - reg_r(gspca_dev, 0x25, 4, 1); /* size */ - spca504B_PollingDataReady(gspca_dev); - - /* Init the cam width height with some values get on init ? */ - reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00); - spca504B_WaitCmdStatus(gspca_dev); - spca504B_PollingDataReady(gspca_dev); - break; - default: -/* case BRIDGE_SPCA504B: */ -/* case BRIDGE_SPCA536: */ - reg_w_1(gspca_dev, 0x25, 0, 4, Size); - reg_r(gspca_dev, 0x25, 4, 1); /* size */ - reg_w_1(gspca_dev, 0x27, 0, 0, 6); - reg_r(gspca_dev, 0x27, 0, 1); /* type */ - spca504B_PollingDataReady(gspca_dev); - break; - case BRIDGE_SPCA504: - Size += 3; - if (sd->subtype == AiptekMiniPenCam13) { - /* spca504a aiptek */ - spca504A_acknowledged_command(gspca_dev, - 0x08, Size, 0, - 0x80 | (Size & 0x0f), 1); - spca504A_acknowledged_command(gspca_dev, - 1, 3, 0, 0x9f, 0); - } else { - spca504_acknowledged_command(gspca_dev, 0x08, Size, 0); - } - break; - case BRIDGE_SPCA504C: - /* capture mode */ - reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00); - reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f)); - break; - } -} - -static void spca504_wait_status(struct gspca_dev *gspca_dev) -{ - int cnt; - - cnt = 256; - while (--cnt > 0) { - /* With this we get the status, when return 0 it's all ok */ - reg_r(gspca_dev, 0x06, 0x00, 1); - if (gspca_dev->usb_buf[0] == 0) - return; - msleep(10); - } -} - -static void spca504B_setQtable(struct gspca_dev *gspca_dev) -{ - reg_w_1(gspca_dev, 0x26, 0, 0, 3); - reg_r(gspca_dev, 0x26, 0, 1); - spca504B_PollingDataReady(gspca_dev); -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - u16 reg; - - reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7; - reg_w_riv(gspca_dev, 0x00, reg, val); -} - -static void setcontrast(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - u16 reg; - - reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8; - reg_w_riv(gspca_dev, 0x00, reg, val); -} - -static void setcolors(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - u16 reg; - - reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae; - reg_w_riv(gspca_dev, 0x00, reg, val); -} - -static void init_ctl_reg(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int pollreg = 1; - - switch (sd->bridge) { - case BRIDGE_SPCA504: - case BRIDGE_SPCA504C: - pollreg = 0; - /* fall thru */ - default: -/* case BRIDGE_SPCA533: */ -/* case BRIDGE_SPCA504B: */ - reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */ - reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */ - reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */ - break; - case BRIDGE_SPCA536: - reg_w_riv(gspca_dev, 0, 0x20f5, 0x40); - reg_w_riv(gspca_dev, 0, 0x20f4, 0x01); - reg_w_riv(gspca_dev, 0, 0x2089, 0x00); - break; - } - if (pollreg) - spca504B_PollingDataReady(gspca_dev); -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - - cam = &gspca_dev->cam; - - sd->bridge = id->driver_info >> 8; - sd->subtype = id->driver_info; - - if (sd->subtype == AiptekMiniPenCam13) { - - /* try to get the firmware as some cam answer 2.0.1.2.2 - * and should be a spca504b then overwrite that setting */ - reg_r(gspca_dev, 0x20, 0, 1); - switch (gspca_dev->usb_buf[0]) { - case 1: - break; /* (right bridge/subtype) */ - case 2: - sd->bridge = BRIDGE_SPCA504B; - sd->subtype = 0; - break; - default: - return -ENODEV; - } - } - - switch (sd->bridge) { - default: -/* case BRIDGE_SPCA504B: */ -/* case BRIDGE_SPCA504: */ -/* case BRIDGE_SPCA536: */ - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - break; - case BRIDGE_SPCA533: - cam->cam_mode = custom_mode; - if (sd->subtype == MegaImageVI) /* 320x240 only */ - cam->nmodes = ARRAY_SIZE(custom_mode) - 1; - else - cam->nmodes = ARRAY_SIZE(custom_mode); - break; - case BRIDGE_SPCA504C: - cam->cam_mode = vga_mode2; - cam->nmodes = ARRAY_SIZE(vga_mode2); - break; - } - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->bridge) { - case BRIDGE_SPCA504B: - reg_w_riv(gspca_dev, 0x1d, 0x00, 0); - reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01); - reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00); - reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00); - reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13); - reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00); - /* fall thru */ - case BRIDGE_SPCA533: - spca504B_PollingDataReady(gspca_dev); -#ifdef GSPCA_DEBUG - spca50x_GetFirmware(gspca_dev); -#endif - break; - case BRIDGE_SPCA536: -#ifdef GSPCA_DEBUG - spca50x_GetFirmware(gspca_dev); -#endif - reg_r(gspca_dev, 0x00, 0x5002, 1); - reg_w_1(gspca_dev, 0x24, 0, 0, 0); - reg_r(gspca_dev, 0x24, 0, 1); - spca504B_PollingDataReady(gspca_dev); - reg_w_riv(gspca_dev, 0x34, 0, 0); - spca504B_WaitCmdStatus(gspca_dev); - break; - case BRIDGE_SPCA504C: /* pccam600 */ - PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)"); - reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000); - reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */ - spca504_wait_status(gspca_dev); - if (sd->subtype == LogitechClickSmart420) - write_vector(gspca_dev, - spca504A_clicksmart420_open_data, - ARRAY_SIZE(spca504A_clicksmart420_open_data)); - else - write_vector(gspca_dev, spca504_pccam600_open_data, - ARRAY_SIZE(spca504_pccam600_open_data)); - setup_qtable(gspca_dev, qtable_creative_pccam); - break; - default: -/* case BRIDGE_SPCA504: */ - PDEBUG(D_STREAM, "Opening SPCA504"); - if (sd->subtype == AiptekMiniPenCam13) { -#ifdef GSPCA_DEBUG - spca504_read_info(gspca_dev); -#endif - - /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ - spca504A_acknowledged_command(gspca_dev, 0x24, - 8, 3, 0x9e, 1); - /* Twice sequential need status 0xff->0x9e->0x9d */ - spca504A_acknowledged_command(gspca_dev, 0x24, - 8, 3, 0x9e, 0); - - spca504A_acknowledged_command(gspca_dev, 0x24, - 0, 0, 0x9d, 1); - /******************************/ - /* spca504a aiptek */ - spca504A_acknowledged_command(gspca_dev, 0x08, - 6, 0, 0x86, 1); -/* reg_write (dev, 0, 0x2000, 0); */ -/* reg_write (dev, 0, 0x2883, 1); */ -/* spca504A_acknowledged_command (gspca_dev, 0x08, - 6, 0, 0x86, 1); */ -/* spca504A_acknowledged_command (gspca_dev, 0x24, - 0, 0, 0x9D, 1); */ - reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05); - /* L92 sno1t.txt */ - reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05); - spca504A_acknowledged_command(gspca_dev, 0x01, - 0x0f, 0, 0xff, 0); - } - /* setup qtable */ - reg_w_riv(gspca_dev, 0, 0x2000, 0); - reg_w_riv(gspca_dev, 0, 0x2883, 1); - setup_qtable(gspca_dev, qtable_spca504_default); - break; - } - return gspca_dev->usb_err; -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int enable; - - /* create the JPEG header */ - jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, - 0x22); /* JPEG 411 */ - jpeg_set_qual(sd->jpeg_hdr, QUALITY); - - if (sd->bridge == BRIDGE_SPCA504B) - spca504B_setQtable(gspca_dev); - spca504B_SetSizeType(gspca_dev); - switch (sd->bridge) { - default: -/* case BRIDGE_SPCA504B: */ -/* case BRIDGE_SPCA533: */ -/* case BRIDGE_SPCA536: */ - switch (sd->subtype) { - case MegapixV4: - case LogitechClickSmart820: - case MegaImageVI: - reg_w_riv(gspca_dev, 0xf0, 0, 0); - spca504B_WaitCmdStatus(gspca_dev); - reg_r(gspca_dev, 0xf0, 4, 0); - spca504B_WaitCmdStatus(gspca_dev); - break; - default: - reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00); - spca504B_WaitCmdStatus(gspca_dev); - spca504B_PollingDataReady(gspca_dev); - break; - } - break; - case BRIDGE_SPCA504: - if (sd->subtype == AiptekMiniPenCam13) { -#ifdef GSPCA_DEBUG - spca504_read_info(gspca_dev); -#endif - - /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ - spca504A_acknowledged_command(gspca_dev, 0x24, - 8, 3, 0x9e, 1); - /* Twice sequential need status 0xff->0x9e->0x9d */ - spca504A_acknowledged_command(gspca_dev, 0x24, - 8, 3, 0x9e, 0); - spca504A_acknowledged_command(gspca_dev, 0x24, - 0, 0, 0x9d, 1); - } else { - spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); -#ifdef GSPCA_DEBUG - spca504_read_info(gspca_dev); -#endif - spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); - spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); - } - spca504B_SetSizeType(gspca_dev); - reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05); - /* L92 sno1t.txt */ - reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05); - break; - case BRIDGE_SPCA504C: - if (sd->subtype == LogitechClickSmart420) { - write_vector(gspca_dev, - spca504A_clicksmart420_init_data, - ARRAY_SIZE(spca504A_clicksmart420_init_data)); - } else { - write_vector(gspca_dev, spca504_pccam600_init_data, - ARRAY_SIZE(spca504_pccam600_init_data)); - } - enable = (sd->autogain ? 0x04 : 0x01); - reg_w_riv(gspca_dev, 0x0c, 0x0000, enable); - /* auto exposure */ - reg_w_riv(gspca_dev, 0xb0, 0x0000, enable); - /* auto whiteness */ - - /* set default exposure compensation and whiteness balance */ - reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */ - reg_w_riv(gspca_dev, 0x30, 0x0002, 1600); - spca504B_SetSizeType(gspca_dev); - break; - } - init_ctl_reg(gspca_dev); - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->bridge) { - default: -/* case BRIDGE_SPCA533: */ -/* case BRIDGE_SPCA536: */ -/* case BRIDGE_SPCA504B: */ - reg_w_riv(gspca_dev, 0x31, 0, 0); - spca504B_WaitCmdStatus(gspca_dev); - spca504B_PollingDataReady(gspca_dev); - break; - case BRIDGE_SPCA504: - case BRIDGE_SPCA504C: - reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000); - - if (sd->subtype == AiptekMiniPenCam13) { - /* spca504a aiptek */ -/* spca504A_acknowledged_command(gspca_dev, 0x08, - 6, 0, 0x86, 1); */ - spca504A_acknowledged_command(gspca_dev, 0x24, - 0x00, 0x00, 0x9d, 1); - spca504A_acknowledged_command(gspca_dev, 0x01, - 0x0f, 0x00, 0xff, 1); - } else { - spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); - reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000); - } - break; - } -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - int i, sof = 0; - static u8 ffd9[] = {0xff, 0xd9}; - -/* frames are jpeg 4.1.1 without 0xff escape */ - switch (sd->bridge) { - case BRIDGE_SPCA533: - if (data[0] == 0xff) { - if (data[1] != 0x01) { /* drop packet */ -/* gspca_dev->last_packet_type = DISCARD_PACKET; */ - return; - } - sof = 1; - data += SPCA533_OFFSET_DATA; - len -= SPCA533_OFFSET_DATA; - } else { - data += 1; - len -= 1; - } - break; - case BRIDGE_SPCA536: - if (data[0] == 0xff) { - sof = 1; - data += SPCA536_OFFSET_DATA; - len -= SPCA536_OFFSET_DATA; - } else { - data += 2; - len -= 2; - } - break; - default: -/* case BRIDGE_SPCA504: */ -/* case BRIDGE_SPCA504B: */ - switch (data[0]) { - case 0xfe: /* start of frame */ - sof = 1; - data += SPCA50X_OFFSET_DATA; - len -= SPCA50X_OFFSET_DATA; - break; - case 0xff: /* drop packet */ -/* gspca_dev->last_packet_type = DISCARD_PACKET; */ - return; - default: - data += 1; - len -= 1; - break; - } - break; - case BRIDGE_SPCA504C: - switch (data[0]) { - case 0xfe: /* start of frame */ - sof = 1; - data += SPCA504_PCCAM600_OFFSET_DATA; - len -= SPCA504_PCCAM600_OFFSET_DATA; - break; - case 0xff: /* drop packet */ -/* gspca_dev->last_packet_type = DISCARD_PACKET; */ - return; - default: - data += 1; - len -= 1; - break; - } - break; - } - if (sof) { /* start of frame */ - gspca_frame_add(gspca_dev, LAST_PACKET, - ffd9, 2); - - /* put the JPEG header in the new frame */ - gspca_frame_add(gspca_dev, FIRST_PACKET, - sd->jpeg_hdr, JPEG_HDR_SZ); - } - - /* add 0x00 after 0xff */ - i = 0; - do { - if (data[i] == 0xff) { - gspca_frame_add(gspca_dev, INTER_PACKET, - data, i + 1); - len -= i; - data += i; - *data = 0x00; - i = 0; - } - i++; - } while (i < len); - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_CONTRAST: - setcontrast(gspca_dev, ctrl->val); - break; - case V4L2_CID_SATURATION: - setcolors(gspca_dev, ctrl->val); - break; - case V4L2_CID_AUTOGAIN: - sd->autogain = ctrl->val; - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 4); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 255, 1, 0x20); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SATURATION, 0, 255, 1, 0x1a); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -#define BS(bridge, subtype) \ - .driver_info = (BRIDGE_ ## bridge << 8) \ - | (subtype) -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)}, - {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)}, - {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)}, - {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)}, - {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)}, - {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)}, - {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)}, - {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)}, - {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)}, - {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)}, - {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)}, - {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)}, - {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)}, - {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)}, - {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)}, - {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)}, - {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)}, - {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)}, - {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)}, - {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)}, - {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)}, - {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)}, - {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)}, - {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)}, - {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)}, - {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)}, - {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)}, - {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)}, - {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)}, - {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)}, - {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)}, - {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)}, - {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)}, - {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)}, - {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)}, - {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)}, - {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)}, - {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)}, - {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)}, - {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)}, - {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)}, - {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)}, - {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)}, - {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)}, - {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)}, - {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)}, - {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)}, - {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)}, - {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)}, - {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)}, - {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)}, - {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)}, - {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)}, - {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)}, - {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)}, - {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)}, - {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)}, - {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)}, - {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c deleted file mode 100644 index 8bc6c3ceec2c..000000000000 --- a/drivers/media/video/gspca/t613.c +++ /dev/null @@ -1,1054 +0,0 @@ -/* - * T613 subdriver - * - * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr) - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - *Notes: * t613 + tas5130A - * * Focus to light do not balance well as in win. - * Quality in win is not good, but its kinda better. - * * Fix some "extraneous bytes", most of apps will show the image anyway - * * Gamma table, is there, but its really doing something? - * * 7~8 Fps, its ok, max on win its 10. - * Costantino Leandro - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "t613" - -#include <linux/input.h> -#include <linux/slab.h> -#include "gspca.h" - -MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>"); -MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver"); -MODULE_LICENSE("GPL"); - -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - struct v4l2_ctrl *freq; - struct { /* awb / color gains control cluster */ - struct v4l2_ctrl *awb; - struct v4l2_ctrl *gain; - struct v4l2_ctrl *red_balance; - struct v4l2_ctrl *blue_balance; - }; - - u8 sensor; - u8 button_pressed; -}; -enum sensors { - SENSOR_OM6802, - SENSOR_OTHER, - SENSOR_TAS5130A, - SENSOR_LT168G, /* must verify if this is the actual model */ -}; - -static const struct v4l2_pix_format vga_mode_t16[] = { - {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120 * 4 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 4}, -#if 0 /* HDG: broken with my test cam, so lets disable it */ - {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 3}, -#endif - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2}, -#if 0 /* HDG: broken with my test cam, so lets disable it */ - {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, -#endif - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; - -/* sensor specific data */ -struct additional_sensor_data { - const u8 n3[6]; - const u8 *n4, n4sz; - const u8 reg80, reg8e; - const u8 nset8[6]; - const u8 data1[10]; - const u8 data2[9]; - const u8 data3[9]; - const u8 data5[6]; - const u8 stream[4]; -}; - -static const u8 n4_om6802[] = { - 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c, - 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68, - 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1, - 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8, - 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48, - 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0, - 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68, - 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40, - 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46 -}; -static const u8 n4_other[] = { - 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69, - 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68, - 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8, - 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8, - 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56, - 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5, - 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0, - 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00 -}; -static const u8 n4_tas5130a[] = { - 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20, - 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4, - 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10, - 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08, - 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a, - 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8, - 0xc6, 0xda -}; -static const u8 n4_lt168g[] = { - 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28, - 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70, - 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3, - 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20, - 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68, - 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40, - 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0, - 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c, - 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80 -}; - -static const struct additional_sensor_data sensor_data[] = { -[SENSOR_OM6802] = { - .n3 = - {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04}, - .n4 = n4_om6802, - .n4sz = sizeof n4_om6802, - .reg80 = 0x3c, - .reg8e = 0x33, - .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00}, - .data1 = - {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06, - 0xb3, 0xfc}, - .data2 = - {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, - 0xff}, - .data3 = - {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, - 0xff}, - .data5 = /* this could be removed later */ - {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23}, - .stream = - {0x0b, 0x04, 0x0a, 0x78}, - }, -[SENSOR_OTHER] = { - .n3 = - {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00}, - .n4 = n4_other, - .n4sz = sizeof n4_other, - .reg80 = 0xac, - .reg8e = 0xb8, - .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00}, - .data1 = - {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a, - 0xe8, 0xfc}, - .data2 = - {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96, - 0xd9}, - .data3 = - {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96, - 0xd9}, - .data5 = - {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69}, - .stream = - {0x0b, 0x04, 0x0a, 0x00}, - }, -[SENSOR_TAS5130A] = { - .n3 = - {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08}, - .n4 = n4_tas5130a, - .n4sz = sizeof n4_tas5130a, - .reg80 = 0x3c, - .reg8e = 0xb4, - .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00}, - .data1 = - {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27, - 0xc8, 0xfc}, - .data2 = - {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8, - 0xe0}, - .data3 = - {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8, - 0xe0}, - .data5 = - {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20}, - .stream = - {0x0b, 0x04, 0x0a, 0x40}, - }, -[SENSOR_LT168G] = { - .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00}, - .n4 = n4_lt168g, - .n4sz = sizeof n4_lt168g, - .reg80 = 0x7c, - .reg8e = 0xb3, - .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00}, - .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40, - 0xb0, 0xf4}, - .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6, - 0xff}, - .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6, - 0xff}, - .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b}, - .stream = {0x0b, 0x04, 0x0a, 0x28}, - }, -}; - -#define MAX_EFFECTS 7 -static const u8 effects_table[MAX_EFFECTS][6] = { - {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */ - {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */ - {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */ - {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */ - {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */ - {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */ - {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */ -}; - -#define GAMMA_MAX (15) -static const u8 gamma_table[GAMMA_MAX+1][17] = { -/* gamma table from cam1690.ini */ - {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21, /* 0 */ - 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb, - 0xff}, - {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d, /* 1 */ - 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1, - 0xff}, - {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35, /* 2 */ - 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3, - 0xff}, - {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */ - 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6, - 0xff}, - {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */ - 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9, - 0xff}, - {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */ - 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec, - 0xff}, - {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67, /* 6 */ - 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, - 0xff}, - {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, /* 7 */ - 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, - 0xff}, - {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79, /* 8 */ - 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0, - 0xff}, - {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84, /* 9 */ - 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2, - 0xff}, - {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e, /* 10 */ - 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3, - 0xff}, - {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b, /* 11 */ - 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5, - 0xff}, - {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */ - 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6, - 0xff}, - {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */ - 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9, - 0xff}, - {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */ - 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa, - 0xff}, - {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */ - 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc, - 0xff} -}; - -static const u8 tas5130a_sensor_init[][8] = { - {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09}, - {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09}, - {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09}, -}; - -static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07}; - -/* read 1 byte */ -static u8 reg_r(struct gspca_dev *gspca_dev, - u16 index) -{ - usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - 0, /* request */ - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, /* value */ - index, - gspca_dev->usb_buf, 1, 500); - return gspca_dev->usb_buf[0]; -} - -static void reg_w(struct gspca_dev *gspca_dev, - u16 index) -{ - usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, index, - NULL, 0, 500); -} - -static void reg_w_buf(struct gspca_dev *gspca_dev, - const u8 *buffer, u16 len) -{ - if (len <= USB_BUF_SZ) { - memcpy(gspca_dev->usb_buf, buffer, len); - usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x01, 0, - gspca_dev->usb_buf, len, 500); - } else { - u8 *tmpbuf; - - tmpbuf = kmemdup(buffer, len, GFP_KERNEL); - if (!tmpbuf) { - pr_err("Out of memory\n"); - return; - } - usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x01, 0, - tmpbuf, len, 500); - kfree(tmpbuf); - } -} - -/* write values to consecutive registers */ -static void reg_w_ixbuf(struct gspca_dev *gspca_dev, - u8 reg, - const u8 *buffer, u16 len) -{ - int i; - u8 *p, *tmpbuf; - - if (len * 2 <= USB_BUF_SZ) { - p = tmpbuf = gspca_dev->usb_buf; - } else { - p = tmpbuf = kmalloc(len * 2, GFP_KERNEL); - if (!tmpbuf) { - pr_err("Out of memory\n"); - return; - } - } - i = len; - while (--i >= 0) { - *p++ = reg++; - *p++ = *buffer++; - } - usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x01, 0, - tmpbuf, len * 2, 500); - if (len * 2 > USB_BUF_SZ) - kfree(tmpbuf); -} - -static void om6802_sensor_init(struct gspca_dev *gspca_dev) -{ - int i; - const u8 *p; - u8 byte; - u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05}; - static const u8 sensor_init[] = { - 0xdf, 0x6d, - 0xdd, 0x18, - 0x5a, 0xe0, - 0x5c, 0x07, - 0x5d, 0xb0, - 0x5e, 0x1e, - 0x60, 0x71, - 0xef, 0x00, - 0xe9, 0x00, - 0xea, 0x00, - 0x90, 0x24, - 0x91, 0xb2, - 0x82, 0x32, - 0xfd, 0x41, - 0x00 /* table end */ - }; - - reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset); - msleep(100); - i = 4; - while (--i > 0) { - byte = reg_r(gspca_dev, 0x0060); - if (!(byte & 0x01)) - break; - msleep(100); - } - byte = reg_r(gspca_dev, 0x0063); - if (byte != 0x17) { - pr_err("Bad sensor reset %02x\n", byte); - /* continue? */ - } - - p = sensor_init; - while (*p != 0) { - val[1] = *p++; - val[3] = *p++; - if (*p == 0) - reg_w(gspca_dev, 0x3c80); - reg_w_buf(gspca_dev, val, sizeof val); - i = 4; - while (--i >= 0) { - msleep(15); - byte = reg_r(gspca_dev, 0x60); - if (!(byte & 0x01)) - break; - } - } - msleep(15); - reg_w(gspca_dev, 0x3c80); -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct cam *cam = &gspca_dev->cam; - - cam->cam_mode = vga_mode_t16; - cam->nmodes = ARRAY_SIZE(vga_mode_t16); - - return 0; -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness) -{ - u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 }; - - if (brightness < 7) { - set6[1] = 0x26; - set6[3] = 0x70 - brightness * 0x10; - } else { - set6[3] = 0x00 + ((brightness - 7) * 0x10); - } - - reg_w_buf(gspca_dev, set6, sizeof set6); -} - -static void setcontrast(struct gspca_dev *gspca_dev, s32 contrast) -{ - u16 reg_to_write; - - if (contrast < 7) - reg_to_write = 0x8ea9 - contrast * 0x200; - else - reg_to_write = 0x00a9 + (contrast - 7) * 0x200; - - reg_w(gspca_dev, reg_to_write); -} - -static void setcolors(struct gspca_dev *gspca_dev, s32 val) -{ - u16 reg_to_write; - - reg_to_write = 0x80bb + val * 0x100; /* was 0xc0 */ - reg_w(gspca_dev, reg_to_write); -} - -static void setgamma(struct gspca_dev *gspca_dev, s32 val) -{ - PDEBUG(D_CONF, "Gamma: %d", sd->gamma); - reg_w_ixbuf(gspca_dev, 0x90, - gamma_table[val], sizeof gamma_table[0]); -} - -static void setawb_n_RGB(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 all_gain_reg[8] = { - 0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00 }; - s32 red_gain, blue_gain, green_gain; - - green_gain = sd->gain->val; - - red_gain = green_gain + sd->red_balance->val; - if (red_gain > 0x40) - red_gain = 0x40; - else if (red_gain < 0x10) - red_gain = 0x10; - - blue_gain = green_gain + sd->blue_balance->val; - if (blue_gain > 0x40) - blue_gain = 0x40; - else if (blue_gain < 0x10) - blue_gain = 0x10; - - all_gain_reg[1] = red_gain; - all_gain_reg[3] = blue_gain; - all_gain_reg[5] = green_gain; - all_gain_reg[7] = sensor_data[sd->sensor].reg80; - if (!sd->awb->val) - all_gain_reg[7] &= ~0x04; /* AWB off */ - - reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg); -} - -static void setsharpness(struct gspca_dev *gspca_dev, s32 val) -{ - u16 reg_to_write; - - reg_to_write = 0x0aa6 + 0x1000 * val; - - reg_w(gspca_dev, reg_to_write); -} - -static void setfreq(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 reg66; - u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 }; - - switch (sd->sensor) { - case SENSOR_LT168G: - if (val != 0) - freq[3] = 0xa8; - reg66 = 0x41; - break; - case SENSOR_OM6802: - reg66 = 0xca; - break; - default: - reg66 = 0x40; - break; - } - switch (val) { - case 0: /* no flicker */ - freq[3] = 0xf0; - break; - case 2: /* 60Hz */ - reg66 &= ~0x40; - break; - } - freq[1] = reg66; - - reg_w_buf(gspca_dev, freq, sizeof freq); -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - /* some of this registers are not really neded, because - * they are overriden by setbrigthness, setcontrast, etc, - * but wont hurt anyway, and can help someone with similar webcam - * to see the initial parameters.*/ - struct sd *sd = (struct sd *) gspca_dev; - const struct additional_sensor_data *sensor; - int i; - u16 sensor_id; - u8 test_byte = 0; - - static const u8 read_indexs[] = - { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5, - 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 }; - static const u8 n1[] = - {0x08, 0x03, 0x09, 0x03, 0x12, 0x04}; - static const u8 n2[] = - {0x08, 0x00}; - - sensor_id = (reg_r(gspca_dev, 0x06) << 8) - | reg_r(gspca_dev, 0x07); - switch (sensor_id & 0xff0f) { - case 0x0801: - PDEBUG(D_PROBE, "sensor tas5130a"); - sd->sensor = SENSOR_TAS5130A; - break; - case 0x0802: - PDEBUG(D_PROBE, "sensor lt168g"); - sd->sensor = SENSOR_LT168G; - break; - case 0x0803: - PDEBUG(D_PROBE, "sensor 'other'"); - sd->sensor = SENSOR_OTHER; - break; - case 0x0807: - PDEBUG(D_PROBE, "sensor om6802"); - sd->sensor = SENSOR_OM6802; - break; - default: - pr_err("unknown sensor %04x\n", sensor_id); - return -EINVAL; - } - - if (sd->sensor == SENSOR_OM6802) { - reg_w_buf(gspca_dev, n1, sizeof n1); - i = 5; - while (--i >= 0) { - reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset); - test_byte = reg_r(gspca_dev, 0x0063); - msleep(100); - if (test_byte == 0x17) - break; /* OK */ - } - if (i < 0) { - pr_err("Bad sensor reset %02x\n", test_byte); - return -EIO; - } - reg_w_buf(gspca_dev, n2, sizeof n2); - } - - i = 0; - while (read_indexs[i] != 0x00) { - test_byte = reg_r(gspca_dev, read_indexs[i]); - PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i], - test_byte); - i++; - } - - sensor = &sensor_data[sd->sensor]; - reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3); - reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz); - - if (sd->sensor == SENSOR_LT168G) { - test_byte = reg_r(gspca_dev, 0x80); - PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80, - test_byte); - reg_w(gspca_dev, 0x6c80); - } - - reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1); - reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2); - reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3); - - reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80); - reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80); - reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e); - reg_w(gspca_dev, (0x20 << 8) + 0x87); - reg_w(gspca_dev, (0x20 << 8) + 0x88); - reg_w(gspca_dev, (0x20 << 8) + 0x89); - - reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5); - reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8); - reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); - - if (sd->sensor == SENSOR_LT168G) { - test_byte = reg_r(gspca_dev, 0x80); - PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80, - test_byte); - reg_w(gspca_dev, 0x6c80); - } - - reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1); - reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2); - reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3); - - return 0; -} - -static void setmirror(struct gspca_dev *gspca_dev, s32 val) -{ - u8 hflipcmd[8] = - {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09}; - - if (val) - hflipcmd[3] = 0x01; - - reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd); -} - -static void seteffect(struct gspca_dev *gspca_dev, s32 val) -{ - int idx = 0; - - switch (val) { - case V4L2_COLORFX_NONE: - break; - case V4L2_COLORFX_BW: - idx = 2; - break; - case V4L2_COLORFX_SEPIA: - idx = 3; - break; - case V4L2_COLORFX_SKETCH: - idx = 4; - break; - case V4L2_COLORFX_NEGATIVE: - idx = 6; - break; - default: - break; - } - - reg_w_buf(gspca_dev, effects_table[idx], - sizeof effects_table[0]); - - if (val == V4L2_COLORFX_SKETCH) - reg_w(gspca_dev, 0x4aa6); - else - reg_w(gspca_dev, 0xfaa6); -} - -/* Is this really needed? - * i added some module parameters for test with some users */ -static void poll_sensor(struct gspca_dev *gspca_dev) -{ - static const u8 poll1[] = - {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82, - 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34, - 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01, - 0x60, 0x14}; - static const u8 poll2[] = - {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9, - 0x73, 0x02, 0x73, 0x02, 0x60, 0x14}; - static const u8 noise03[] = /* (some differences / ms-drv) */ - {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f, - 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c, - 0xc2, 0x80, 0xc3, 0x10}; - - PDEBUG(D_STREAM, "[Sensor requires polling]"); - reg_w_buf(gspca_dev, poll1, sizeof poll1); - reg_w_buf(gspca_dev, poll2, sizeof poll2); - reg_w_buf(gspca_dev, noise03, sizeof noise03); -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - const struct additional_sensor_data *sensor; - int i, mode; - u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 }; - static const u8 t3[] = - { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 }; - - mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - switch (mode) { - case 0: /* 640x480 (0x00) */ - break; - case 1: /* 352x288 */ - t2[1] = 0x40; - break; - case 2: /* 320x240 */ - t2[1] = 0x10; - break; - case 3: /* 176x144 */ - t2[1] = 0x50; - break; - default: -/* case 4: * 160x120 */ - t2[1] = 0x20; - break; - } - - switch (sd->sensor) { - case SENSOR_OM6802: - om6802_sensor_init(gspca_dev); - break; - case SENSOR_TAS5130A: - i = 0; - for (;;) { - reg_w_buf(gspca_dev, tas5130a_sensor_init[i], - sizeof tas5130a_sensor_init[0]); - if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1) - break; - i++; - } - reg_w(gspca_dev, 0x3c80); - /* just in case and to keep sync with logs (for mine) */ - reg_w_buf(gspca_dev, tas5130a_sensor_init[i], - sizeof tas5130a_sensor_init[0]); - reg_w(gspca_dev, 0x3c80); - break; - } - sensor = &sensor_data[sd->sensor]; - setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq)); - reg_r(gspca_dev, 0x0012); - reg_w_buf(gspca_dev, t2, sizeof t2); - reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3); - reg_w(gspca_dev, 0x0013); - msleep(15); - reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); - reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); - - if (sd->sensor == SENSOR_OM6802) - poll_sensor(gspca_dev); - - return 0; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream, - sizeof sensor_data[sd->sensor].stream); - reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream, - sizeof sensor_data[sd->sensor].stream); - if (sd->sensor == SENSOR_OM6802) { - msleep(20); - reg_w(gspca_dev, 0x0309); - } -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - /* If the last button state is pressed, release it now! */ - if (sd->button_pressed) { - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); - input_sync(gspca_dev->input_dev); - sd->button_pressed = 0; - } -#endif -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - int pkt_type; - - if (data[0] == 0x5a) { -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - if (len > 20) { - u8 state = (data[20] & 0x80) ? 1 : 0; - if (sd->button_pressed != state) { - input_report_key(gspca_dev->input_dev, - KEY_CAMERA, state); - input_sync(gspca_dev->input_dev); - sd->button_pressed = state; - } - } -#endif - /* Control Packet, after this came the header again, - * but extra bytes came in the packet before this, - * sometimes an EOF arrives, sometimes not... */ - return; - } - data += 2; - len -= 2; - if (data[0] == 0xff && data[1] == 0xd8) - pkt_type = FIRST_PACKET; - else if (data[len - 2] == 0xff && data[len - 1] == 0xd9) - pkt_type = LAST_PACKET; - else - pkt_type = INTER_PACKET; - gspca_frame_add(gspca_dev, pkt_type, data, len); -} - -static int sd_g_volatile_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - s32 red_gain, blue_gain, green_gain; - - gspca_dev->usb_err = 0; - - switch (ctrl->id) { - case V4L2_CID_AUTO_WHITE_BALANCE: - red_gain = reg_r(gspca_dev, 0x0087); - if (red_gain > 0x40) - red_gain = 0x40; - else if (red_gain < 0x10) - red_gain = 0x10; - - blue_gain = reg_r(gspca_dev, 0x0088); - if (blue_gain > 0x40) - blue_gain = 0x40; - else if (blue_gain < 0x10) - blue_gain = 0x10; - - green_gain = reg_r(gspca_dev, 0x0089); - if (green_gain > 0x40) - green_gain = 0x40; - else if (green_gain < 0x10) - green_gain = 0x10; - - sd->gain->val = green_gain; - sd->red_balance->val = red_gain - green_gain; - sd->blue_balance->val = blue_gain - green_gain; - break; - } - return 0; -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_CONTRAST: - setcontrast(gspca_dev, ctrl->val); - break; - case V4L2_CID_SATURATION: - setcolors(gspca_dev, ctrl->val); - break; - case V4L2_CID_GAMMA: - setgamma(gspca_dev, ctrl->val); - break; - case V4L2_CID_HFLIP: - setmirror(gspca_dev, ctrl->val); - break; - case V4L2_CID_SHARPNESS: - setsharpness(gspca_dev, ctrl->val); - break; - case V4L2_CID_POWER_LINE_FREQUENCY: - setfreq(gspca_dev, ctrl->val); - break; - case V4L2_CID_BACKLIGHT_COMPENSATION: - reg_w(gspca_dev, ctrl->val ? 0xf48e : 0xb48e); - break; - case V4L2_CID_AUTO_WHITE_BALANCE: - setawb_n_RGB(gspca_dev); - break; - case V4L2_CID_COLORFX: - seteffect(gspca_dev, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .g_volatile_ctrl = sd_g_volatile_ctrl, - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 12); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 14, 1, 8); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 0x0d, 1, 7); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SATURATION, 0, 0xf, 1, 5); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAMMA, 0, GAMMA_MAX, 1, 10); - /* Activate lowlight, some apps dont bring up the - backlight_compensation control) */ - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BACKLIGHT_COMPENSATION, 0, 1, 1, 1); - if (sd->sensor == SENSOR_TAS5130A) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_HFLIP, 0, 1, 1, 0); - sd->awb = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1); - sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0x10, 0x40, 1, 0x20); - sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BLUE_BALANCE, -0x30, 0x30, 1, 0); - sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_RED_BALANCE, -0x30, 0x30, 1, 0); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SHARPNESS, 0, 15, 1, 6); - v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, - V4L2_CID_COLORFX, V4L2_COLORFX_SKETCH, - ~((1 << V4L2_COLORFX_NONE) | - (1 << V4L2_COLORFX_BW) | - (1 << V4L2_COLORFX_SEPIA) | - (1 << V4L2_COLORFX_SKETCH) | - (1 << V4L2_COLORFX_NEGATIVE)), - V4L2_COLORFX_NONE); - sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, - V4L2_CID_POWER_LINE_FREQUENCY, - V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1, - V4L2_CID_POWER_LINE_FREQUENCY_50HZ); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - - v4l2_ctrl_auto_cluster(4, &sd->awb, 0, true); - - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .other_input = 1, -#endif -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x17a1, 0x0128)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/topro.c b/drivers/media/video/gspca/topro.c deleted file mode 100644 index a6055246cb9d..000000000000 --- a/drivers/media/video/gspca/topro.c +++ /dev/null @@ -1,4969 +0,0 @@ -/* - * Topro TP6800/6810 webcam driver. - * - * Copyright (C) 2011 Jean-François Moine (http://moinejf.free.fr) - * Copyright (C) 2009 Anders Blomdell (anders.blomdell@control.lth.se) - * Copyright (C) 2008 Thomas Champagne (lafeuil@gmail.com) - * - * 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, see <http://www.gnu.org/licenses/>. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "gspca.h" - -MODULE_DESCRIPTION("Topro TP6800/6810 gspca webcam driver"); -MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, " - "Anders Blomdell <anders.blomdell@control.lth.se>"); -MODULE_LICENSE("GPL"); - -static int force_sensor = -1; - -/* JPEG header */ -static const u8 jpeg_head[] = { - 0xff, 0xd8, /* jpeg */ - -/* quantization table quality 50% */ - 0xff, 0xdb, 0x00, 0x84, /* DQT */ -0, -#define JPEG_QT0_OFFSET 7 - 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, - 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, - 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, - 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, - 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44, - 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, - 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, - 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63, -1, -#define JPEG_QT1_OFFSET 72 - 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, - 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - - /* Define Huffman table (thanks to Thomas Kaiser) */ - 0xff, 0xc4, 0x01, 0x5e, - 0x00, 0x00, 0x02, 0x03, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, - 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, - 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, - 0x07, 0x05, 0x04, 0x06, 0x01, 0x00, 0x00, 0x57, - 0x01, 0x02, 0x03, 0x00, 0x11, 0x04, 0x12, 0x21, - 0x31, 0x13, 0x41, 0x51, 0x61, 0x05, 0x22, 0x32, - 0x14, 0x71, 0x81, 0x91, 0x15, 0x23, 0x42, 0x52, - 0x62, 0xa1, 0xb1, 0x06, 0x33, 0x72, 0xc1, 0xd1, - 0x24, 0x43, 0x53, 0x82, 0x16, 0x34, 0x92, 0xa2, - 0xe1, 0xf1, 0xf0, 0x07, 0x08, 0x17, 0x18, 0x25, - 0x26, 0x27, 0x28, 0x35, 0x36, 0x37, 0x38, 0x44, - 0x45, 0x46, 0x47, 0x48, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x73, - 0x74, 0x75, 0x76, 0x77, 0x78, 0x83, 0x84, 0x85, - 0x86, 0x87, 0x88, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xb2, - 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xc2, 0xc3, - 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xe2, 0xe3, 0xe4, 0xe5, - 0xe6, 0xe7, 0xe8, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, - 0xf7, 0xf8, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, - 0x05, 0x06, 0x07, 0x08, 0x09, 0x11, 0x00, 0x02, - 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, - 0x04, 0x06, 0x01, 0x00, 0x00, 0x57, 0x00, 0x01, - 0x11, 0x02, 0x21, 0x03, 0x12, 0x31, 0x41, 0x13, - 0x22, 0x51, 0x61, 0x04, 0x32, 0x71, 0x05, 0x14, - 0x23, 0x42, 0x33, 0x52, 0x81, 0x91, 0xa1, 0xb1, - 0xf0, 0x06, 0x15, 0xc1, 0xd1, 0xe1, 0x24, 0x43, - 0x62, 0xf1, 0x16, 0x25, 0x34, 0x53, 0x72, 0x82, - 0x92, 0x07, 0x08, 0x17, 0x18, 0x26, 0x27, 0x28, - 0x35, 0x36, 0x37, 0x38, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x54, 0x55, 0x56, 0x57, 0x58, 0x63, 0x64, - 0x65, 0x66, 0x67, 0x68, 0x73, 0x74, 0x75, 0x76, - 0x77, 0x78, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, - 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0xa2, 0xa3, - 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xb2, 0xb3, 0xb4, - 0xb5, 0xb6, 0xb7, 0xb8, 0xc2, 0xc3, 0xc4, 0xc5, - 0xc6, 0xc7, 0xc8, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, - 0xd7, 0xd8, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xff, 0xc0, 0x00, 0x11, /* SOF0 (start of frame 0 */ - 0x08, /* data precision */ -#define JPEG_HEIGHT_OFFSET 493 - 0x01, 0xe0, /* height */ - 0x02, 0x80, /* width */ - 0x03, /* component number */ - 0x01, - 0x21, /* samples Y = jpeg 422 */ - 0x00, /* quant Y */ - 0x02, 0x11, 0x01, /* samples CbCr - quant CbCr */ - 0x03, 0x11, 0x01, - - 0xff, 0xda, 0x00, 0x0c, /* SOS (start of scan) */ - 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 -#define JPEG_HDR_SZ 521 -}; - -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - struct v4l2_ctrl *jpegqual; - struct v4l2_ctrl *sharpness; - struct v4l2_ctrl *gamma; - struct v4l2_ctrl *blue; - struct v4l2_ctrl *red; - - u8 framerate; - u8 quality; /* webcam current JPEG quality (0..16) */ - s8 ag_cnt; /* autogain / start counter for tp6810 */ -#define AG_CNT_START 13 /* check gain every N frames */ - - u8 bridge; - u8 sensor; - - u8 jpeg_hdr[JPEG_HDR_SZ]; -}; - -enum bridges { - BRIDGE_TP6800, - BRIDGE_TP6810, -}; - -enum sensors { - SENSOR_CX0342, - SENSOR_SOI763A, /* ~= ov7630 / ov7648 */ - NSENSORS -}; - -static const struct v4l2_pix_format vga_mode[] = { - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 4 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG} -}; - -/* - * JPEG quality - * index: webcam compression - * value: JPEG quality in % - */ -static const u8 jpeg_q[17] = { - 88, 77, 67, 57, 55, 55, 45, 45, 36, 36, 30, 30, 26, 26, 22, 22, 94 -}; - -#define BULK_OUT_SIZE 0x20 -#if BULK_OUT_SIZE > USB_BUF_SZ -#error "USB buffer too small" -#endif - -static const u8 rates[] = {30, 20, 15, 10, 7, 5}; -static const struct framerates framerates[] = { - { - .rates = rates, - .nrates = ARRAY_SIZE(rates) - }, - { - .rates = rates, - .nrates = ARRAY_SIZE(rates) - } -}; -static const u8 rates_6810[] = {30, 15, 10, 7, 5}; -static const struct framerates framerates_6810[] = { - { - .rates = rates_6810, - .nrates = ARRAY_SIZE(rates_6810) - }, - { - .rates = rates_6810, - .nrates = ARRAY_SIZE(rates_6810) - } -}; - -/* - * webcam quality in % - * the last value is the ultra fine quality - */ - -/* TP6800 register offsets */ -#define TP6800_R10_SIF_TYPE 0x10 -#define TP6800_R11_SIF_CONTROL 0x11 -#define TP6800_R12_SIF_ADDR_S 0x12 -#define TP6800_R13_SIF_TX_DATA 0x13 -#define TP6800_R14_SIF_RX_DATA 0x14 -#define TP6800_R15_GPIO_PU 0x15 -#define TP6800_R16_GPIO_PD 0x16 -#define TP6800_R17_GPIO_IO 0x17 -#define TP6800_R18_GPIO_DATA 0x18 -#define TP6800_R19_SIF_ADDR_S2 0x19 -#define TP6800_R1A_SIF_TX_DATA2 0x1a -#define TP6800_R1B_SIF_RX_DATA2 0x1b -#define TP6800_R21_ENDP_1_CTL 0x21 -#define TP6800_R2F_TIMING_CFG 0x2f -#define TP6800_R30_SENSOR_CFG 0x30 -#define TP6800_R31_PIXEL_START 0x31 -#define TP6800_R32_PIXEL_END_L 0x32 -#define TP6800_R33_PIXEL_END_H 0x33 -#define TP6800_R34_LINE_START 0x34 -#define TP6800_R35_LINE_END_L 0x35 -#define TP6800_R36_LINE_END_H 0x36 -#define TP6800_R37_FRONT_DARK_ST 0x37 -#define TP6800_R38_FRONT_DARK_END 0x38 -#define TP6800_R39_REAR_DARK_ST_L 0x39 -#define TP6800_R3A_REAR_DARK_ST_H 0x3a -#define TP6800_R3B_REAR_DARK_END_L 0x3b -#define TP6800_R3C_REAR_DARK_END_H 0x3c -#define TP6800_R3D_HORIZ_DARK_LINE_L 0x3d -#define TP6800_R3E_HORIZ_DARK_LINE_H 0x3e -#define TP6800_R3F_FRAME_RATE 0x3f -#define TP6800_R50 0x50 -#define TP6800_R51 0x51 -#define TP6800_R52 0x52 -#define TP6800_R53 0x53 -#define TP6800_R54_DARK_CFG 0x54 -#define TP6800_R55_GAMMA_R 0x55 -#define TP6800_R56_GAMMA_G 0x56 -#define TP6800_R57_GAMMA_B 0x57 -#define TP6800_R5C_EDGE_THRLD 0x5c -#define TP6800_R5D_DEMOSAIC_CFG 0x5d -#define TP6800_R78_FORMAT 0x78 -#define TP6800_R79_QUALITY 0x79 -#define TP6800_R7A_BLK_THRLD 0x7a - -/* CX0342 register offsets */ - -#define CX0342_SENSOR_ID 0x00 -#define CX0342_VERSION_NO 0x01 -#define CX0342_ORG_X_L 0x02 -#define CX0342_ORG_X_H 0x03 -#define CX0342_ORG_Y_L 0x04 -#define CX0342_ORG_Y_H 0x05 -#define CX0342_STOP_X_L 0x06 -#define CX0342_STOP_X_H 0x07 -#define CX0342_STOP_Y_L 0x08 -#define CX0342_STOP_Y_H 0x09 -#define CX0342_FRAME_WIDTH_L 0x0a -#define CX0342_FRAME_WIDTH_H 0x0b -#define CX0342_FRAME_HEIGH_L 0x0c -#define CX0342_FRAME_HEIGH_H 0x0d -#define CX0342_EXPO_LINE_L 0x10 -#define CX0342_EXPO_LINE_H 0x11 -#define CX0342_EXPO_CLK_L 0x12 -#define CX0342_EXPO_CLK_H 0x13 -#define CX0342_RAW_GRGAIN_L 0x14 -#define CX0342_RAW_GRGAIN_H 0x15 -#define CX0342_RAW_GBGAIN_L 0x16 -#define CX0342_RAW_GBGAIN_H 0x17 -#define CX0342_RAW_RGAIN_L 0x18 -#define CX0342_RAW_RGAIN_H 0x19 -#define CX0342_RAW_BGAIN_L 0x1a -#define CX0342_RAW_BGAIN_H 0x1b -#define CX0342_GLOBAL_GAIN 0x1c -#define CX0342_SYS_CTRL_0 0x20 -#define CX0342_SYS_CTRL_1 0x21 -#define CX0342_SYS_CTRL_2 0x22 -#define CX0342_BYPASS_MODE 0x23 -#define CX0342_SYS_CTRL_3 0x24 -#define CX0342_TIMING_EN 0x25 -#define CX0342_OUTPUT_CTRL 0x26 -#define CX0342_AUTO_ADC_CALIB 0x27 -#define CX0342_SYS_CTRL_4 0x28 -#define CX0342_ADCGN 0x30 -#define CX0342_SLPCR 0x31 -#define CX0342_SLPFN_LO 0x32 -#define CX0342_ADC_CTL 0x33 -#define CX0342_LVRST_BLBIAS 0x34 -#define CX0342_VTHSEL 0x35 -#define CX0342_RAMP_RIV 0x36 -#define CX0342_LDOSEL 0x37 -#define CX0342_CLOCK_GEN 0x40 -#define CX0342_SOFT_RESET 0x41 -#define CX0342_PLL 0x42 -#define CX0342_DR_ENH_PULSE_OFFSET_L 0x43 -#define CX0342_DR_ENH_PULSE_OFFSET_H 0x44 -#define CX0342_DR_ENH_PULSE_POS_L 0x45 -#define CX0342_DR_ENH_PULSE_POS_H 0x46 -#define CX0342_DR_ENH_PULSE_WIDTH 0x47 -#define CX0342_AS_CURRENT_CNT_L 0x48 -#define CX0342_AS_CURRENT_CNT_H 0x49 -#define CX0342_AS_PREVIOUS_CNT_L 0x4a -#define CX0342_AS_PREVIOUS_CNT_H 0x4b -#define CX0342_SPV_VALUE_L 0x4c -#define CX0342_SPV_VALUE_H 0x4d -#define CX0342_GPXLTHD_L 0x50 -#define CX0342_GPXLTHD_H 0x51 -#define CX0342_RBPXLTHD_L 0x52 -#define CX0342_RBPXLTHD_H 0x53 -#define CX0342_PLANETHD_L 0x54 -#define CX0342_PLANETHD_H 0x55 -#define CX0342_ROWDARK_TH 0x56 -#define CX0342_ROWDARK_TOL 0x57 -#define CX0342_RB_GAP_L 0x58 -#define CX0342_RB_GAP_H 0x59 -#define CX0342_G_GAP_L 0x5a -#define CX0342_G_GAP_H 0x5b -#define CX0342_AUTO_ROW_DARK 0x60 -#define CX0342_MANUAL_DARK_VALUE 0x61 -#define CX0342_GB_DARK_OFFSET 0x62 -#define CX0342_GR_DARK_OFFSET 0x63 -#define CX0342_RED_DARK_OFFSET 0x64 -#define CX0342_BLUE_DARK_OFFSET 0x65 -#define CX0342_DATA_SCALING_MULTI 0x66 -#define CX0342_AUTOD_Q_FRAME 0x67 -#define CX0342_AUTOD_ALLOW_VARI 0x68 -#define CX0342_AUTO_DARK_VALUE_L 0x69 -#define CX0342_AUTO_DARK_VALUE_H 0x6a -#define CX0342_IO_CTRL_0 0x70 -#define CX0342_IO_CTRL_1 0x71 -#define CX0342_IO_CTRL_2 0x72 -#define CX0342_IDLE_CTRL 0x73 -#define CX0342_TEST_MODE 0x74 -#define CX0342_FRAME_FIX_DATA_TEST 0x75 -#define CX0342_FRAME_CNT_TEST 0x76 -#define CX0342_RST_OVERFLOW_L 0x80 -#define CX0342_RST_OVERFLOW_H 0x81 -#define CX0342_RST_UNDERFLOW_L 0x82 -#define CX0342_RST_UNDERFLOW_H 0x83 -#define CX0342_DATA_OVERFLOW_L 0x84 -#define CX0342_DATA_OVERFLOW_H 0x85 -#define CX0342_DATA_UNDERFLOW_L 0x86 -#define CX0342_DATA_UNDERFLOW_H 0x87 -#define CX0342_CHANNEL_0_0_L_irst 0x90 -#define CX0342_CHANNEL_0_0_H_irst 0x91 -#define CX0342_CHANNEL_0_1_L_irst 0x92 -#define CX0342_CHANNEL_0_1_H_irst 0x93 -#define CX0342_CHANNEL_0_2_L_irst 0x94 -#define CX0342_CHANNEL_0_2_H_irst 0x95 -#define CX0342_CHANNEL_0_3_L_irst 0x96 -#define CX0342_CHANNEL_0_3_H_irst 0x97 -#define CX0342_CHANNEL_0_4_L_irst 0x98 -#define CX0342_CHANNEL_0_4_H_irst 0x99 -#define CX0342_CHANNEL_0_5_L_irst 0x9a -#define CX0342_CHANNEL_0_5_H_irst 0x9b -#define CX0342_CHANNEL_0_6_L_irst 0x9c -#define CX0342_CHANNEL_0_6_H_irst 0x9d -#define CX0342_CHANNEL_0_7_L_irst 0x9e -#define CX0342_CHANNEL_0_7_H_irst 0x9f -#define CX0342_CHANNEL_1_0_L_itx 0xa0 -#define CX0342_CHANNEL_1_0_H_itx 0xa1 -#define CX0342_CHANNEL_1_1_L_itx 0xa2 -#define CX0342_CHANNEL_1_1_H_itx 0xa3 -#define CX0342_CHANNEL_1_2_L_itx 0xa4 -#define CX0342_CHANNEL_1_2_H_itx 0xa5 -#define CX0342_CHANNEL_1_3_L_itx 0xa6 -#define CX0342_CHANNEL_1_3_H_itx 0xa7 -#define CX0342_CHANNEL_1_4_L_itx 0xa8 -#define CX0342_CHANNEL_1_4_H_itx 0xa9 -#define CX0342_CHANNEL_1_5_L_itx 0xaa -#define CX0342_CHANNEL_1_5_H_itx 0xab -#define CX0342_CHANNEL_1_6_L_itx 0xac -#define CX0342_CHANNEL_1_6_H_itx 0xad -#define CX0342_CHANNEL_1_7_L_itx 0xae -#define CX0342_CHANNEL_1_7_H_itx 0xaf -#define CX0342_CHANNEL_2_0_L_iwl 0xb0 -#define CX0342_CHANNEL_2_0_H_iwl 0xb1 -#define CX0342_CHANNEL_2_1_L_iwl 0xb2 -#define CX0342_CHANNEL_2_1_H_iwl 0xb3 -#define CX0342_CHANNEL_2_2_L_iwl 0xb4 -#define CX0342_CHANNEL_2_2_H_iwl 0xb5 -#define CX0342_CHANNEL_2_3_L_iwl 0xb6 -#define CX0342_CHANNEL_2_3_H_iwl 0xb7 -#define CX0342_CHANNEL_2_4_L_iwl 0xb8 -#define CX0342_CHANNEL_2_4_H_iwl 0xb9 -#define CX0342_CHANNEL_2_5_L_iwl 0xba -#define CX0342_CHANNEL_2_5_H_iwl 0xbb -#define CX0342_CHANNEL_2_6_L_iwl 0xbc -#define CX0342_CHANNEL_2_6_H_iwl 0xbd -#define CX0342_CHANNEL_2_7_L_iwl 0xbe -#define CX0342_CHANNEL_2_7_H_iwl 0xbf -#define CX0342_CHANNEL_3_0_L_ensp 0xc0 -#define CX0342_CHANNEL_3_0_H_ensp 0xc1 -#define CX0342_CHANNEL_3_1_L_ensp 0xc2 -#define CX0342_CHANNEL_3_1_H_ensp 0xc3 -#define CX0342_CHANNEL_3_2_L_ensp 0xc4 -#define CX0342_CHANNEL_3_2_H_ensp 0xc5 -#define CX0342_CHANNEL_3_3_L_ensp 0xc6 -#define CX0342_CHANNEL_3_3_H_ensp 0xc7 -#define CX0342_CHANNEL_3_4_L_ensp 0xc8 -#define CX0342_CHANNEL_3_4_H_ensp 0xc9 -#define CX0342_CHANNEL_3_5_L_ensp 0xca -#define CX0342_CHANNEL_3_5_H_ensp 0xcb -#define CX0342_CHANNEL_3_6_L_ensp 0xcc -#define CX0342_CHANNEL_3_6_H_ensp 0xcd -#define CX0342_CHANNEL_3_7_L_ensp 0xce -#define CX0342_CHANNEL_3_7_H_ensp 0xcf -#define CX0342_CHANNEL_4_0_L_sela 0xd0 -#define CX0342_CHANNEL_4_0_H_sela 0xd1 -#define CX0342_CHANNEL_4_1_L_sela 0xd2 -#define CX0342_CHANNEL_4_1_H_sela 0xd3 -#define CX0342_CHANNEL_5_0_L_intla 0xe0 -#define CX0342_CHANNEL_5_0_H_intla 0xe1 -#define CX0342_CHANNEL_5_1_L_intla 0xe2 -#define CX0342_CHANNEL_5_1_H_intla 0xe3 -#define CX0342_CHANNEL_5_2_L_intla 0xe4 -#define CX0342_CHANNEL_5_2_H_intla 0xe5 -#define CX0342_CHANNEL_5_3_L_intla 0xe6 -#define CX0342_CHANNEL_5_3_H_intla 0xe7 -#define CX0342_CHANNEL_6_0_L_xa_sel_pos 0xf0 -#define CX0342_CHANNEL_6_0_H_xa_sel_pos 0xf1 -#define CX0342_CHANNEL_7_1_L_cds_pos 0xf2 -#define CX0342_CHANNEL_7_1_H_cds_pos 0xf3 -#define CX0342_SENSOR_HEIGHT_L 0xfb -#define CX0342_SENSOR_HEIGHT_H 0xfc -#define CX0342_SENSOR_WIDTH_L 0xfd -#define CX0342_SENSOR_WIDTH_H 0xfe -#define CX0342_VSYNC_HSYNC_READ 0xff - -struct cmd { - u8 reg; - u8 val; -}; - -static const u8 DQT[17][130] = { - /* Define quantization table (thanks to Thomas Kaiser) */ - { /* Quality 0 */ - 0x00, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x01, - 0x04, 0x04, 0x04, 0x06, 0x05, 0x06, 0x0b, 0x06, - 0x06, 0x0b, 0x18, 0x10, 0x0e, 0x10, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - }, - { /* Quality 1 */ - 0x00, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - 0x01, - 0x08, 0x09, 0x09, 0x0c, 0x0a, 0x0c, 0x17, 0x0d, - 0x0d, 0x17, 0x31, 0x21, 0x1c, 0x21, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, - }, - { /* Quality 2 */ - 0x00, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x06, 0x06, 0x06, 0x04, 0x04, 0x04, - 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x01, - 0x0c, 0x0d, 0x0d, 0x12, 0x0f, 0x12, 0x23, 0x13, - 0x13, 0x23, 0x4a, 0x31, 0x2a, 0x31, 0x4a, 0x4a, - 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, - 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, - 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, - 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, - 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, - 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, - }, - { /* Quality 3 */ - 0x00, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, - 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x01, - 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, - 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - }, - { /* Quality 4 */ - 0x00, - 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x0a, 0x0a, 0x0a, 0x05, 0x05, 0x05, - 0x05, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x01, - 0x11, 0x16, 0x16, 0x1e, 0x1a, 0x1e, 0x3a, 0x20, - 0x20, 0x3a, 0x7b, 0x52, 0x46, 0x52, 0x7b, 0x7b, - 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, - 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, - 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, - 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, - 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, - 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, - }, - { /* Quality 5 */ - 0x00, - 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x06, 0x06, 0x06, - 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x01, - 0x11, 0x1b, 0x1b, 0x24, 0x1f, 0x24, 0x46, 0x27, - 0x27, 0x46, 0x94, 0x63, 0x54, 0x63, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - }, - { /* Quality 6 */ - 0x00, - 0x05, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x0e, 0x0e, 0x0e, 0x07, 0x07, 0x07, - 0x07, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, - 0x01, - 0x15, 0x1f, 0x1f, 0x2a, 0x24, 0x2a, 0x52, 0x2d, - 0x2d, 0x52, 0xad, 0x73, 0x62, 0x73, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - }, - { /* Quality 7 */ - 0x00, - 0x05, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, - 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, - 0x01, - 0x15, 0x24, 0x24, 0x30, 0x2a, 0x30, 0x5e, 0x34, - 0x34, 0x5e, 0xc6, 0x84, 0x70, 0x84, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - }, - { /* Quality 8 */ - 0x00, - 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x14, 0x14, 0x14, 0x0a, 0x0a, 0x0a, - 0x0a, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x14, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, - 0x01, - 0x19, 0x2d, 0x2d, 0x3c, 0x34, 0x3c, 0x75, 0x41, - 0x41, 0x75, 0xf7, 0xa5, 0x8c, 0xa5, 0xf7, 0xf7, - 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, - 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, - 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, - 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, - 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, - 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, - }, - { /* Quality 9 */ - 0x00, - 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x0c, - 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x01, - 0x19, 0x36, 0x36, 0x48, 0x3f, 0x48, 0x8d, 0x4e, - 0x4e, 0x8d, 0xff, 0xc6, 0xa8, 0xc6, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - { /* Quality 10 */ - 0x00, - 0x07, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x0e, 0x1c, 0x1c, 0x1c, 0x0e, 0x0e, 0x0e, - 0x0e, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x1c, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, - 0x01, - 0x1d, 0x3f, 0x3f, 0x54, 0x49, 0x54, 0xa4, 0x5b, - 0x5b, 0xa4, 0xff, 0xe7, 0xc4, 0xe7, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - { /* Quality 11 */ - 0x00, - 0x07, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, - 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, - 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, - 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, - 0x01, - 0x1d, 0x48, 0x48, 0x60, 0x54, 0x60, 0xbc, 0x68, - 0x68, 0xbc, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - { /* Quality 12 */ - 0x00, - 0x08, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0x28, 0x28, 0x28, 0x14, 0x14, 0x14, - 0x14, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, - 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, - 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, - 0x01, - 0x22, 0x5a, 0x5a, 0x78, 0x69, 0x78, 0xeb, 0x82, - 0x82, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - { /* Quality 13 */ - 0x00, - 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, - 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x72, 0x72, 0x72, 0x72, 0x72, - 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, - 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, - 0x01, - 0x22, 0x6c, 0x6c, 0x90, 0x7e, 0x90, 0xff, 0x9c, - 0x9c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - { /* Quality 14 */ - 0x00, - 0x0a, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x1c, 0x38, 0x38, 0x38, 0x1c, 0x1c, 0x1c, - 0x1c, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x38, 0x38, 0x38, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x01, - 0x2a, 0x7e, 0x7e, 0xa8, 0x93, 0xa8, 0xff, 0xb6, - 0xb6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - { /* Quality 15 */ - 0x00, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, - 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x40, 0x40, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x01, - 0x2a, 0x90, 0x90, 0xc0, 0xa8, 0xc0, 0xff, 0xd0, - 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - { /* Quality 16-31 */ - 0x00, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x01, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - } -}; - -static const struct cmd tp6810_cx_init_common[] = { - {0x1c, 0x00}, - {TP6800_R10_SIF_TYPE, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {TP6800_R50, 0xff}, - {TP6800_R51, 0x03}, - {0x00, 0x07}, - {TP6800_R79_QUALITY, 0x03}, - {TP6800_R2F_TIMING_CFG, 0x37}, - {TP6800_R30_SENSOR_CFG, 0x10}, - {TP6800_R21_ENDP_1_CTL, 0x00}, - {TP6800_R52, 0x40}, - {TP6800_R53, 0x40}, - {TP6800_R54_DARK_CFG, 0x40}, - {TP6800_R30_SENSOR_CFG, 0x18}, - {0x4b, 0x00}, - {TP6800_R3F_FRAME_RATE, 0x83}, - {TP6800_R79_QUALITY, 0x05}, - {TP6800_R21_ENDP_1_CTL, 0x00}, - {0x7c, 0x04}, - {0x25, 0x14}, - {0x26, 0x0f}, - {0x7b, 0x10}, -}; - -static const struct cmd tp6810_ov_init_common[] = { - {0x1c, 0x00}, - {TP6800_R10_SIF_TYPE, 0x00}, - {0x4e, 0x00}, - {0x4f, 0x00}, - {TP6800_R50, 0xff}, - {TP6800_R51, 0x03}, - {0x00, 0x07}, - {TP6800_R52, 0x40}, - {TP6800_R53, 0x40}, - {TP6800_R54_DARK_CFG, 0x40}, - {TP6800_R79_QUALITY, 0x03}, - {TP6800_R2F_TIMING_CFG, 0x17}, - {TP6800_R30_SENSOR_CFG, 0x18}, - {TP6800_R21_ENDP_1_CTL, 0x00}, - {TP6800_R3F_FRAME_RATE, 0x86}, - {0x25, 0x18}, - {0x26, 0x0f}, - {0x7b, 0x90}, -}; - -static const struct cmd tp6810_bridge_start[] = { - {0x59, 0x88}, - {0x5a, 0x0f}, - {0x5b, 0x4e}, - {TP6800_R5C_EDGE_THRLD, 0x63}, - {TP6800_R5D_DEMOSAIC_CFG, 0x00}, - {0x03, 0x7f}, - {0x04, 0x80}, - {0x06, 0x00}, - {0x00, 0x00}, -}; - -static const struct cmd tp6810_late_start[] = { - {0x7d, 0x01}, - {0xb0, 0x04}, - {0xb1, 0x04}, - {0xb2, 0x04}, - {0xb3, 0x04}, - {0xb4, 0x04}, - {0xb5, 0x04}, - {0xb6, 0x08}, - {0xb7, 0x08}, - {0xb8, 0x04}, - {0xb9, 0x04}, - {0xba, 0x04}, - {0xbb, 0x04}, - {0xbc, 0x04}, - {0xbd, 0x08}, - {0xbe, 0x08}, - {0xbf, 0x08}, - {0xc0, 0x04}, - {0xc1, 0x04}, - {0xc2, 0x08}, - {0xc3, 0x08}, - {0xc4, 0x08}, - {0xc5, 0x08}, - {0xc6, 0x08}, - {0xc7, 0x13}, - {0xc8, 0x04}, - {0xc9, 0x08}, - {0xca, 0x08}, - {0xcb, 0x08}, - {0xcc, 0x08}, - {0xcd, 0x08}, - {0xce, 0x13}, - {0xcf, 0x13}, - {0xd0, 0x08}, - {0xd1, 0x08}, - {0xd2, 0x08}, - {0xd3, 0x08}, - {0xd4, 0x08}, - {0xd5, 0x13}, - {0xd6, 0x13}, - {0xd7, 0x13}, - {0xd8, 0x08}, - {0xd9, 0x08}, - {0xda, 0x08}, - {0xdb, 0x08}, - {0xdc, 0x13}, - {0xdd, 0x13}, - {0xde, 0x13}, - {0xdf, 0x13}, - {0xe0, 0x08}, - {0xe1, 0x08}, - {0xe2, 0x08}, - {0xe3, 0x13}, - {0xe4, 0x13}, - {0xe5, 0x13}, - {0xe6, 0x13}, - {0xe7, 0x13}, - {0xe8, 0x08}, - {0xe9, 0x08}, - {0xea, 0x13}, - {0xeb, 0x13}, - {0xec, 0x13}, - {0xed, 0x13}, - {0xee, 0x13}, - {0xef, 0x13}, - {0x7d, 0x02}, - - /* later after isoc start */ - {0x7d, 0x08}, - {0x7d, 0x00}, -}; - -static const struct cmd cx0342_timing_seq[] = { - {CX0342_CHANNEL_0_1_L_irst, 0x20}, - {CX0342_CHANNEL_0_2_L_irst, 0x24}, - {CX0342_CHANNEL_0_2_H_irst, 0x00}, - {CX0342_CHANNEL_0_3_L_irst, 0x2f}, - {CX0342_CHANNEL_0_3_H_irst, 0x00}, - {CX0342_CHANNEL_1_0_L_itx, 0x02}, - {CX0342_CHANNEL_1_0_H_itx, 0x00}, - {CX0342_CHANNEL_1_1_L_itx, 0x20}, - {CX0342_CHANNEL_1_1_H_itx, 0x00}, - {CX0342_CHANNEL_1_2_L_itx, 0xe4}, - {CX0342_CHANNEL_1_2_H_itx, 0x00}, - {CX0342_CHANNEL_1_3_L_itx, 0xee}, - {CX0342_CHANNEL_1_3_H_itx, 0x00}, - {CX0342_CHANNEL_2_0_L_iwl, 0x30}, - {CX0342_CHANNEL_2_0_H_iwl, 0x00}, - {CX0342_CHANNEL_3_0_L_ensp, 0x34}, - {CX0342_CHANNEL_3_1_L_ensp, 0xe2}, - {CX0342_CHANNEL_3_1_H_ensp, 0x00}, - {CX0342_CHANNEL_3_2_L_ensp, 0xf6}, - {CX0342_CHANNEL_3_2_H_ensp, 0x00}, - {CX0342_CHANNEL_3_3_L_ensp, 0xf4}, - {CX0342_CHANNEL_3_3_H_ensp, 0x02}, - {CX0342_CHANNEL_4_0_L_sela, 0x26}, - {CX0342_CHANNEL_4_0_H_sela, 0x00}, - {CX0342_CHANNEL_4_1_L_sela, 0xe2}, - {CX0342_CHANNEL_4_1_H_sela, 0x00}, - {CX0342_CHANNEL_5_0_L_intla, 0x26}, - {CX0342_CHANNEL_5_1_L_intla, 0x29}, - {CX0342_CHANNEL_5_2_L_intla, 0xf0}, - {CX0342_CHANNEL_5_2_H_intla, 0x00}, - {CX0342_CHANNEL_5_3_L_intla, 0xf3}, - {CX0342_CHANNEL_5_3_H_intla, 0x00}, - {CX0342_CHANNEL_6_0_L_xa_sel_pos, 0x24}, - {CX0342_CHANNEL_7_1_L_cds_pos, 0x02}, - {CX0342_TIMING_EN, 0x01}, -}; - -/* define the JPEG header */ -static void jpeg_define(u8 *jpeg_hdr, - int height, - int width) -{ - memcpy(jpeg_hdr, jpeg_head, sizeof jpeg_head); - jpeg_hdr[JPEG_HEIGHT_OFFSET + 0] = height >> 8; - jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height; - jpeg_hdr[JPEG_HEIGHT_OFFSET + 2] = width >> 8; - jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width; -} - -/* set the JPEG quality for sensor soi763a */ -static void jpeg_set_qual(u8 *jpeg_hdr, - int quality) -{ - int i, sc; - - if (quality < 50) - sc = 5000 / quality; - else - sc = 200 - quality * 2; - for (i = 0; i < 64; i++) { - jpeg_hdr[JPEG_QT0_OFFSET + i] = - (jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100; - jpeg_hdr[JPEG_QT1_OFFSET + i] = - (jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100; - } -} - -static void reg_w(struct gspca_dev *gspca_dev, u8 index, u8 value) -{ - struct usb_device *dev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return; - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x0e, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, NULL, 0, 500); - if (ret < 0) { - pr_err("reg_w err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -/* the returned value is in gspca_dev->usb_buf */ -static void reg_r(struct gspca_dev *gspca_dev, u8 index) -{ - struct usb_device *dev = gspca_dev->dev; - int ret; - - if (gspca_dev->usb_err < 0) - return; - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - 0x0d, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, index, gspca_dev->usb_buf, 1, 500); - if (ret < 0) { - pr_err("reg_r err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -static void reg_w_buf(struct gspca_dev *gspca_dev, - const struct cmd *p, int l) -{ - do { - reg_w(gspca_dev, p->reg, p->val); - p++; - } while (--l > 0); -} - -static int i2c_w(struct gspca_dev *gspca_dev, u8 index, u8 value) -{ - struct sd *sd = (struct sd *) gspca_dev; - - reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00); - reg_w(gspca_dev, TP6800_R19_SIF_ADDR_S2, index); - reg_w(gspca_dev, TP6800_R13_SIF_TX_DATA, value); - reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x01); - if (sd->bridge == BRIDGE_TP6800) - return 0; - msleep(5); - reg_r(gspca_dev, TP6800_R11_SIF_CONTROL); - if (gspca_dev->usb_buf[0] == 0) - return 0; - reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00); - return -1; /* error */ -} - -static void i2c_w_buf(struct gspca_dev *gspca_dev, - const struct cmd *p, int l) -{ - do { - i2c_w(gspca_dev, p->reg, p->val); - p++; - } while (--l > 0); -} - -static int i2c_r(struct gspca_dev *gspca_dev, u8 index, int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - int v; - - reg_w(gspca_dev, TP6800_R19_SIF_ADDR_S2, index); - reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x02); - msleep(5); - reg_r(gspca_dev, TP6800_R14_SIF_RX_DATA); - v = gspca_dev->usb_buf[0]; - if (sd->bridge == BRIDGE_TP6800) - return v; - if (len > 1) { - reg_r(gspca_dev, TP6800_R1B_SIF_RX_DATA2); - v |= (gspca_dev->usb_buf[0] << 8); - } - reg_r(gspca_dev, TP6800_R11_SIF_CONTROL); - if (gspca_dev->usb_buf[0] == 0) - return v; - reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00); - return -1; -} - -static void bulk_w(struct gspca_dev *gspca_dev, - u8 tag, - const u8 *data, - int length) -{ - struct usb_device *dev = gspca_dev->dev; - int count, actual_count, ret; - - if (gspca_dev->usb_err < 0) - return; - for (;;) { - count = length > BULK_OUT_SIZE - 1 - ? BULK_OUT_SIZE - 1 : length; - gspca_dev->usb_buf[0] = tag; - memcpy(&gspca_dev->usb_buf[1], data, count); - ret = usb_bulk_msg(dev, - usb_sndbulkpipe(dev, 3), - gspca_dev->usb_buf, count + 1, - &actual_count, 500); - if (ret < 0) { - pr_err("bulk write error %d tag=%02x\n", - ret, tag); - gspca_dev->usb_err = ret; - return; - } - length -= count; - if (length <= 0) - break; - data += count; - } -} - -static int probe_6810(struct gspca_dev *gspca_dev) -{ - u8 gpio; - int ret; - - reg_r(gspca_dev, TP6800_R18_GPIO_DATA); - gpio = gspca_dev->usb_buf[0]; - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio); - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20); - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio); - reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x04); /* i2c 16 bits */ - reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x21); /* ov??? */ - reg_w(gspca_dev, TP6800_R1A_SIF_TX_DATA2, 0x00); - if (i2c_w(gspca_dev, 0x00, 0x00) >= 0) - return SENSOR_SOI763A; - - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20); - reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00); /* i2c 8 bits */ - reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x7f); /* (unknown i2c) */ - if (i2c_w(gspca_dev, 0x00, 0x00) >= 0) - return -2; - - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20); - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio); - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20); - reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00); /* i2c 8 bits */ - reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x11); /* tas??? / hv??? */ - ret = i2c_r(gspca_dev, 0x00, 1); - if (ret > 0) - return -3; - - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20); - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio); - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20); - reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x6e); /* po??? */ - ret = i2c_r(gspca_dev, 0x00, 1); - if (ret > 0) - return -4; - - ret = i2c_r(gspca_dev, 0x01, 1); - if (ret > 0) - return -5; - - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20); - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio); - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20); - reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x04); /* i2c 16 bits */ - reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x5d); /* mi/mt??? */ - ret = i2c_r(gspca_dev, 0x00, 2); - if (ret > 0) - return -6; - - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20); - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio); - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20); - reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x5c); /* mi/mt??? */ - ret = i2c_r(gspca_dev, 0x36, 2); - if (ret > 0) - return -7; - - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio); - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20); - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio); - reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x61); /* (unknown i2c) */ - reg_w(gspca_dev, TP6800_R1A_SIF_TX_DATA2, 0x10); - if (i2c_w(gspca_dev, 0xff, 0x00) >= 0) - return -8; - - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20); - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio); - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20); - reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00); /* i2c 8 bits */ - reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20); /* cx0342 */ - ret = i2c_r(gspca_dev, 0x00, 1); - if (ret > 0) - return SENSOR_CX0342; - return -9; -} - -static void cx0342_6810_init(struct gspca_dev *gspca_dev) -{ - static const struct cmd reg_init_1[] = { - {TP6800_R2F_TIMING_CFG, 0x2f}, - {0x25, 0x02}, - {TP6800_R21_ENDP_1_CTL, 0x00}, - {TP6800_R3F_FRAME_RATE, 0x80}, - {TP6800_R2F_TIMING_CFG, 0x2f}, - {TP6800_R18_GPIO_DATA, 0xe1}, - {TP6800_R18_GPIO_DATA, 0xc1}, - {TP6800_R18_GPIO_DATA, 0xe1}, - {TP6800_R11_SIF_CONTROL, 0x00}, - }; - static const struct cmd reg_init_2[] = { - {TP6800_R78_FORMAT, 0x48}, - {TP6800_R11_SIF_CONTROL, 0x00}, - }; - static const struct cmd sensor_init[] = { - {CX0342_OUTPUT_CTRL, 0x07}, - {CX0342_BYPASS_MODE, 0x58}, - {CX0342_GPXLTHD_L, 0x28}, - {CX0342_RBPXLTHD_L, 0x28}, - {CX0342_PLANETHD_L, 0x50}, - {CX0342_PLANETHD_H, 0x03}, - {CX0342_RB_GAP_L, 0xff}, - {CX0342_RB_GAP_H, 0x07}, - {CX0342_G_GAP_L, 0xff}, - {CX0342_G_GAP_H, 0x07}, - {CX0342_RST_OVERFLOW_L, 0x5c}, - {CX0342_RST_OVERFLOW_H, 0x01}, - {CX0342_DATA_OVERFLOW_L, 0xfc}, - {CX0342_DATA_OVERFLOW_H, 0x03}, - {CX0342_DATA_UNDERFLOW_L, 0x00}, - {CX0342_DATA_UNDERFLOW_H, 0x00}, - {CX0342_SYS_CTRL_0, 0x40}, - {CX0342_GLOBAL_GAIN, 0x01}, - {CX0342_CLOCK_GEN, 0x00}, - {CX0342_SYS_CTRL_0, 0x02}, - {CX0342_IDLE_CTRL, 0x05}, - {CX0342_ADCGN, 0x00}, - {CX0342_ADC_CTL, 0x00}, - {CX0342_LVRST_BLBIAS, 0x01}, - {CX0342_VTHSEL, 0x0b}, - {CX0342_RAMP_RIV, 0x0b}, - {CX0342_LDOSEL, 0x07}, - {CX0342_SPV_VALUE_L, 0x40}, - {CX0342_SPV_VALUE_H, 0x02}, - - {CX0342_AUTO_ADC_CALIB, 0x81}, - {CX0342_TIMING_EN, 0x01}, - }; - - reg_w_buf(gspca_dev, reg_init_1, ARRAY_SIZE(reg_init_1)); - reg_w_buf(gspca_dev, tp6810_cx_init_common, - ARRAY_SIZE(tp6810_cx_init_common)); - reg_w_buf(gspca_dev, reg_init_2, ARRAY_SIZE(reg_init_2)); - - reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20); /* cx0342 I2C addr */ - i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init)); - i2c_w_buf(gspca_dev, cx0342_timing_seq, ARRAY_SIZE(cx0342_timing_seq)); -} - -static void soi763a_6810_init(struct gspca_dev *gspca_dev) -{ - static const struct cmd reg_init_1[] = { - {TP6800_R2F_TIMING_CFG, 0x2f}, - {TP6800_R18_GPIO_DATA, 0xe1}, - {0x25, 0x02}, - {TP6800_R21_ENDP_1_CTL, 0x00}, - {TP6800_R3F_FRAME_RATE, 0x80}, - {TP6800_R2F_TIMING_CFG, 0x2f}, - {TP6800_R18_GPIO_DATA, 0xc1}, - }; - static const struct cmd reg_init_2[] = { - {TP6800_R78_FORMAT, 0x54}, - }; - static const struct cmd sensor_init[] = { - {0x00, 0x00}, - {0x01, 0x80}, - {0x02, 0x80}, - {0x03, 0x90}, - {0x04, 0x20}, - {0x05, 0x20}, - {0x06, 0x80}, - {0x07, 0x00}, - {0x08, 0xff}, - {0x09, 0xff}, - {0x0a, 0x76}, /* 7630 = soi673a */ - {0x0b, 0x30}, - {0x0c, 0x20}, - {0x0d, 0x20}, - {0x0e, 0xff}, - {0x0f, 0xff}, - {0x10, 0x41}, - {0x15, 0x14}, - {0x11, 0x40}, - {0x12, 0x48}, - {0x13, 0x80}, - {0x14, 0x80}, - {0x16, 0x03}, - {0x28, 0xb0}, - {0x71, 0x20}, - {0x75, 0x8e}, - {0x17, 0x1b}, - {0x18, 0xbd}, - {0x19, 0x05}, - {0x1a, 0xf6}, - {0x1b, 0x04}, - {0x1c, 0x7f}, /* omnivision */ - {0x1d, 0xa2}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x45}, - {0x21, 0x80}, - {0x22, 0x80}, - {0x23, 0xee}, - {0x24, 0x50}, - {0x25, 0x7a}, - {0x26, 0xa0}, - {0x27, 0x9a}, - {0x29, 0x30}, - {0x2a, 0x80}, - {0x2b, 0x00}, - {0x2c, 0xac}, - {0x2d, 0x05}, - {0x2e, 0x80}, - {0x2f, 0x3c}, - {0x30, 0x22}, - {0x31, 0x00}, - {0x32, 0x86}, - {0x33, 0x08}, - {0x34, 0xff}, - {0x35, 0xff}, - {0x36, 0xff}, - {0x37, 0xff}, - {0x38, 0xff}, - {0x39, 0xff}, - {0x3a, 0xfe}, - {0x3b, 0xfe}, - {0x3c, 0xfe}, - {0x3d, 0xfe}, - {0x3e, 0xfe}, - {0x3f, 0x71}, - {0x40, 0xff}, - {0x41, 0xff}, - {0x42, 0xff}, - {0x43, 0xff}, - {0x44, 0xff}, - {0x45, 0xff}, - {0x46, 0xff}, - {0x47, 0xff}, - {0x48, 0xff}, - {0x49, 0xff}, - {0x4a, 0xfe}, - {0x4b, 0xff}, - {0x4c, 0x00}, - {0x4d, 0x00}, - {0x4e, 0xff}, - {0x4f, 0xff}, - {0x50, 0xff}, - {0x51, 0xff}, - {0x52, 0xff}, - {0x53, 0xff}, - {0x54, 0xff}, - {0x55, 0xff}, - {0x56, 0xff}, - {0x57, 0xff}, - {0x58, 0xff}, - {0x59, 0xff}, - {0x5a, 0xff}, - {0x5b, 0xfe}, - {0x5c, 0xff}, - {0x5d, 0x8f}, - {0x5e, 0xff}, - {0x5f, 0x8f}, - {0x60, 0xa2}, - {0x61, 0x4a}, - {0x62, 0xf3}, - {0x63, 0x75}, - {0x64, 0xf0}, - {0x65, 0x00}, - {0x66, 0x55}, - {0x67, 0x92}, - {0x68, 0xa0}, - {0x69, 0x4a}, - {0x6a, 0x22}, - {0x6b, 0x00}, - {0x6c, 0x33}, - {0x6d, 0x44}, - {0x6e, 0x22}, - {0x6f, 0x84}, - {0x70, 0x0b}, - {0x72, 0x10}, - {0x73, 0x50}, - {0x74, 0x21}, - {0x76, 0x00}, - {0x77, 0xa5}, - {0x78, 0x80}, - {0x79, 0x80}, - {0x7a, 0x80}, - {0x7b, 0xe2}, - {0x7c, 0x00}, - {0x7d, 0xf7}, - {0x7e, 0x00}, - {0x7f, 0x00}, - }; - - reg_w_buf(gspca_dev, reg_init_1, ARRAY_SIZE(reg_init_1)); - reg_w_buf(gspca_dev, tp6810_ov_init_common, - ARRAY_SIZE(tp6810_ov_init_common)); - reg_w_buf(gspca_dev, reg_init_2, ARRAY_SIZE(reg_init_2)); - - i2c_w(gspca_dev, 0x12, 0x80); /* sensor reset */ - msleep(10); - i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init)); -} - -/* set the gain and exposure */ -static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 gain, - s32 blue, s32 red) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor == SENSOR_CX0342) { - expo = (expo << 2) - 1; - i2c_w(gspca_dev, CX0342_EXPO_LINE_L, expo); - i2c_w(gspca_dev, CX0342_EXPO_LINE_H, expo >> 8); - if (sd->bridge == BRIDGE_TP6800) - i2c_w(gspca_dev, CX0342_RAW_GBGAIN_H, - gain >> 8); - i2c_w(gspca_dev, CX0342_RAW_GBGAIN_L, gain); - if (sd->bridge == BRIDGE_TP6800) - i2c_w(gspca_dev, CX0342_RAW_GRGAIN_H, - gain >> 8); - i2c_w(gspca_dev, CX0342_RAW_GRGAIN_L, gain); - if (sd->sensor == SENSOR_CX0342) { - if (sd->bridge == BRIDGE_TP6800) - i2c_w(gspca_dev, CX0342_RAW_BGAIN_H, - blue >> 8); - i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, blue); - if (sd->bridge == BRIDGE_TP6800) - i2c_w(gspca_dev, CX0342_RAW_RGAIN_H, - red >> 8); - i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, red); - } - i2c_w(gspca_dev, CX0342_SYS_CTRL_0, - sd->bridge == BRIDGE_TP6800 ? 0x80 : 0x81); - return; - } - - /* soi763a */ - i2c_w(gspca_dev, 0x10, /* AEC_H (exposure time) */ - expo); -/* i2c_w(gspca_dev, 0x76, 0x02); * AEC_L ([1:0] */ - i2c_w(gspca_dev, 0x00, /* gain */ - gain); -} - -/* set the JPEG quantization tables */ -static void set_dqt(struct gspca_dev *gspca_dev, u8 q) -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* update the jpeg quantization tables */ - PDEBUG(D_STREAM, "q %d -> %d", sd->quality, q); - sd->quality = q; - if (q > 16) - q = 16; - if (sd->sensor == SENSOR_SOI763A) - jpeg_set_qual(sd->jpeg_hdr, jpeg_q[q]); - else - memcpy(&sd->jpeg_hdr[JPEG_QT0_OFFSET - 1], - DQT[q], sizeof DQT[0]); -} - -/* set the JPEG compression quality factor */ -static void setquality(struct gspca_dev *gspca_dev, s32 q) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (q != 16) - q = 15 - q; - - reg_w(gspca_dev, TP6800_R7A_BLK_THRLD, 0x00); - reg_w(gspca_dev, TP6800_R79_QUALITY, 0x04); - reg_w(gspca_dev, TP6800_R79_QUALITY, q); - - /* auto quality */ - if (q == 15 && sd->bridge == BRIDGE_TP6810) { - msleep(4); - reg_w(gspca_dev, TP6800_R7A_BLK_THRLD, 0x19); - } -} - -static const u8 color_null[18] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -static const u8 color_gain[NSENSORS][18] = { -[SENSOR_CX0342] = - {0x4c, 0x00, 0xa9, 0x00, 0x31, 0x00, /* Y R/G/B (LE values) */ - 0xb6, 0x03, 0x6c, 0x03, 0xe0, 0x00, /* U R/G/B */ - 0xdf, 0x00, 0x46, 0x03, 0xdc, 0x03}, /* V R/G/B */ -[SENSOR_SOI763A] = - {0x4c, 0x00, 0x95, 0x00, 0x1d, 0x00, /* Y R/G/B (LE values) */ - 0xb6, 0x03, 0x6c, 0x03, 0xd7, 0x00, /* U R/G/B */ - 0xd5, 0x00, 0x46, 0x03, 0xdc, 0x03}, /* V R/G/B */ -}; - -static void setgamma(struct gspca_dev *gspca_dev, s32 gamma) -{ - struct sd *sd = (struct sd *) gspca_dev; -#define NGAMMA 6 - static const u8 gamma_tb[NGAMMA][3][1024] = { - { /* gamma 0 - from tp6800 + soi763a */ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09, - 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11, - 0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17, - 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e, - 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23, - 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, - 0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f, - 0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34, - 0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38, - 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c, - 0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40, - 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45, - 0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49, - 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c, - 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50, - 0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54, - 0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58, - 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, - 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f, - 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, - 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65, - 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, - 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a, - 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, - 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, - 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, - 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77, - 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79, - 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, - 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, - 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, - 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, - 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86, - 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89, - 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91, - 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, - 0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, - 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad, - 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, - 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, - 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, - 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc, - 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, - 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, - 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, - 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5, - 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9, - 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca, - 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, - 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, - 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, - 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, - 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, - 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, - 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, - 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, - 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, - 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, - 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, - 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, - 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, - 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, - 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, - 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, - 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, - 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, - 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, - 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, - 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09, - 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11, - 0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17, - 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e, - 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23, - 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, - 0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f, - 0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34, - 0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38, - 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c, - 0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40, - 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45, - 0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49, - 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c, - 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50, - 0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54, - 0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58, - 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, - 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f, - 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, - 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65, - 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, - 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a, - 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, - 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, - 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, - 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77, - 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79, - 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, - 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, - 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, - 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, - 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86, - 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89, - 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91, - 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, - 0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, - 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad, - 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, - 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, - 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, - 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc, - 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, - 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, - 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, - 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5, - 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9, - 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca, - 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, - 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, - 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, - 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, - 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, - 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, - 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, - 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, - 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, - 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, - 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, - 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, - 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, - 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, - 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, - 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, - 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, - 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, - 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, - 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, - 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09, - 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11, - 0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17, - 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e, - 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23, - 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, - 0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f, - 0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34, - 0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38, - 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c, - 0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40, - 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45, - 0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49, - 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c, - 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50, - 0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54, - 0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58, - 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, - 0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f, - 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, - 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65, - 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, - 0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a, - 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, - 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, - 0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, - 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x76, - 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79, - 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, - 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, - 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, - 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, - 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86, - 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89, - 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91, - 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, - 0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, - 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad, - 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, - 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, - 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, - 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc, - 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, - 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, - 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, - 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5, - 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9, - 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca, - 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, - 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, - 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, - 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, - 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, - 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, - 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, - 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, - 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, - 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, - 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, - 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, - 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, - 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, - 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, - 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, - 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, - 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, - 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, - 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, - 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb} - }, - { /* gamma 1 - from tp6810 + soi763a */ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x02, 0x03, 0x05, 0x07, 0x08, 0x09, 0x0a, - 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x15, - 0x16, 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1c, 0x1e, - 0x1f, 0x20, 0x22, 0x22, 0x23, 0x25, 0x26, 0x27, - 0x27, 0x28, 0x29, 0x2b, 0x2b, 0x2c, 0x2d, 0x2f, - 0x2f, 0x30, 0x31, 0x33, 0x33, 0x34, 0x35, 0x35, - 0x37, 0x38, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, - 0x3c, 0x3d, 0x3f, 0x3f, 0x40, 0x42, 0x42, 0x43, - 0x43, 0x44, 0x45, 0x45, 0x47, 0x47, 0x48, 0x49, - 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d, - 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53, - 0x54, 0x54, 0x55, 0x56, 0x56, 0x58, 0x58, 0x59, - 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5e, - 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61, 0x61, - 0x62, 0x62, 0x63, 0x63, 0x65, 0x65, 0x65, 0x66, - 0x66, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69, 0x69, - 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, - 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71, - 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, - 0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79, - 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, - 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x80, - 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x84, 0x84, - 0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x88, - 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, - 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, - 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x91, - 0x91, 0x91, 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, - 0x93, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x97, - 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99, - 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, - 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, - 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xab, - 0xac, 0xac, 0xac, 0xad, 0xad, 0xad, 0xad, 0xae, - 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, - 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, - 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, - 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, - 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, - 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, - 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, - 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, - 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, - 0xc4, 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, - 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, - 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, - 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, - 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, - 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, - 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, - 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, - 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, - 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, - 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, - 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, - 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, - 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, - 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, - 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, - 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, - 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, - 0xec, 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef, - 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, - 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, - 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, - 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, - 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, - 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, - 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, - 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, - 0x05, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0c, 0x0d, - 0x0e, 0x10, 0x10, 0x11, 0x12, 0x14, 0x15, 0x15, - 0x16, 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1c, 0x1e, - 0x1e, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x25, 0x25, - 0x26, 0x27, 0x27, 0x28, 0x29, 0x29, 0x2b, 0x2c, - 0x2c, 0x2d, 0x2d, 0x2f, 0x30, 0x30, 0x31, 0x31, - 0x33, 0x34, 0x34, 0x35, 0x35, 0x37, 0x38, 0x38, - 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, - 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x42, 0x43, - 0x43, 0x44, 0x44, 0x45, 0x45, 0x47, 0x47, 0x48, - 0x48, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4c, - 0x4c, 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, - 0x52, 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x55, - 0x55, 0x56, 0x56, 0x56, 0x58, 0x58, 0x59, 0x59, - 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c, - 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x60, - 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, 0x65, - 0x65, 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, - 0x68, 0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, - 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, - 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71, - 0x71, 0x71, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, - 0x75, 0x75, 0x75, 0x77, 0x77, 0x77, 0x78, 0x78, - 0x78, 0x79, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a, - 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, - 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, - 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, - 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86, - 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89, 0x89, - 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90, - 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92, - 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94, - 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, - 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, - 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, - 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, - 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, - 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc, - 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, - 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, - 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, - 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, - 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, - 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, - 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce, 0xcf, - 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, - 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, - 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, - 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, - 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, - 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, - 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, - 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, - 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, - 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, - 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, - 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, - 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, - 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, - 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, - 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, - 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, - 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, - 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, - 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, - 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, - 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, - 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, - 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, - 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, - 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x02, 0x03, 0x05, 0x05, 0x07, - 0x08, 0x09, 0x0a, 0x0a, 0x0c, 0x0d, 0x0e, 0x0e, - 0x10, 0x11, 0x12, 0x12, 0x14, 0x15, 0x16, 0x16, - 0x17, 0x18, 0x18, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e, - 0x1e, 0x1f, 0x1f, 0x20, 0x22, 0x22, 0x23, 0x23, - 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x29, 0x29, - 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f, 0x30, - 0x30, 0x31, 0x31, 0x33, 0x33, 0x34, 0x34, 0x35, - 0x35, 0x37, 0x37, 0x38, 0x38, 0x39, 0x39, 0x3a, - 0x3a, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, - 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x42, 0x42, 0x43, - 0x43, 0x44, 0x44, 0x45, 0x45, 0x47, 0x47, 0x47, - 0x48, 0x48, 0x49, 0x49, 0x49, 0x4a, 0x4a, 0x4b, - 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4f, - 0x4f, 0x50, 0x50, 0x50, 0x52, 0x52, 0x52, 0x53, - 0x53, 0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x56, - 0x56, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x5a, - 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c, - 0x5e, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60, - 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, - 0x63, 0x63, 0x65, 0x65, 0x65, 0x66, 0x66, 0x66, - 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x69, - 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c, - 0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, - 0x6f, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71, - 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x74, 0x74, - 0x74, 0x74, 0x75, 0x75, 0x75, 0x75, 0x77, 0x77, - 0x77, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, - 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, - 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, - 0x7d, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, - 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, - 0x82, 0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, - 0x85, 0x86, 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, - 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, - 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, - 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, - 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, - 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, - 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, - 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, - 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, - 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, - 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, - 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, - 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, - 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, - 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, - 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, - 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, - 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, - 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, - 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, - 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, - 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, - 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, - 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, - 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, - 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, - 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, - 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, - 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, - 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, - 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, - 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, - 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef, 0xef, - 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, - 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, - 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, - 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, - 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, - 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, - 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, - 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, - 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} - }, - { /* gamma 2 */ - {0x00, 0x01, 0x02, 0x05, 0x07, 0x08, 0x0a, 0x0c, - 0x0d, 0x0e, 0x10, 0x12, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x1a, 0x1b, 0x1c, 0x1e, 0x1f, 0x20, 0x22, - 0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2c, - 0x2d, 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34, 0x34, - 0x35, 0x37, 0x38, 0x38, 0x39, 0x3a, 0x3b, 0x3b, - 0x3c, 0x3d, 0x3f, 0x3f, 0x40, 0x42, 0x42, 0x43, - 0x44, 0x44, 0x45, 0x47, 0x47, 0x48, 0x49, 0x49, - 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4f, 0x4f, - 0x50, 0x50, 0x52, 0x53, 0x53, 0x54, 0x54, 0x55, - 0x55, 0x56, 0x56, 0x58, 0x58, 0x59, 0x5a, 0x5a, - 0x5b, 0x5b, 0x5c, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, - 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x63, 0x63, - 0x65, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68, - 0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c, - 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, - 0x70, 0x70, 0x71, 0x71, 0x73, 0x73, 0x73, 0x74, - 0x74, 0x75, 0x75, 0x75, 0x77, 0x77, 0x78, 0x78, - 0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, - 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f, - 0x7f, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, - 0x82, 0x82, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, - 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x89, 0x89, - 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, - 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91, - 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94, - 0x94, 0x94, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, - 0x97, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, - 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, - 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, - 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, - 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, - 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, 0xb4, - 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, - 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, - 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, - 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, - 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, - 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, - 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, - 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, - 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, - 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, - 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce, - 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, - 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, - 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, - 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, - 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, - 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, - 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, - 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, - 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, - 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, - 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, - 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, - 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, - 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, - 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, - 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, - 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed, - 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, - 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, - 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, - 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, - 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, - 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, - 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, - 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}, - {0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x05, - 0x07, 0x08, 0x09, 0x0a, 0x0d, 0x0e, 0x10, 0x11, - 0x12, 0x14, 0x15, 0x16, 0x16, 0x17, 0x18, 0x1a, - 0x1b, 0x1c, 0x1e, 0x1f, 0x20, 0x20, 0x22, 0x23, - 0x25, 0x26, 0x26, 0x27, 0x28, 0x29, 0x29, 0x2b, - 0x2c, 0x2d, 0x2d, 0x2f, 0x30, 0x30, 0x31, 0x33, - 0x33, 0x34, 0x35, 0x35, 0x37, 0x38, 0x38, 0x39, - 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3d, 0x3f, - 0x3f, 0x40, 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, - 0x45, 0x45, 0x47, 0x47, 0x48, 0x48, 0x49, 0x4a, - 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, - 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53, - 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x58, - 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, - 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, - 0x60, 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x63, - 0x63, 0x63, 0x65, 0x65, 0x65, 0x66, 0x66, 0x67, - 0x67, 0x67, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69, - 0x6a, 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, - 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, - 0x70, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x73, - 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77, 0x77, - 0x77, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x79, - 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7b, 0x7c, - 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, - 0x7f, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, - 0x82, 0x82, 0x82, 0x82, 0x84, 0x84, 0x84, 0x84, - 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x88, - 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, - 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92, - 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, - 0x97, 0x98, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xad, 0xad, 0xad, 0xad, 0xad, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, - 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, - 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, - 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, - 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, - 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, - 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, - 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, - 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, - 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, - 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, - 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9, - 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca, - 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, - 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, - 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, - 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, - 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, - 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, - 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, - 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, - 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, - 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, - 0xdb, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, - 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, - 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, - 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, - 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, - 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, - 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, - 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, - 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, - 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, - 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, - 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, - 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, - 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, - 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, - 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, - 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, - 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}, - {0x00, 0x00, 0x00, 0x01, 0x02, 0x05, 0x07, 0x08, - 0x09, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x12, 0x14, - 0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1e, - 0x1f, 0x20, 0x20, 0x22, 0x23, 0x25, 0x26, 0x27, - 0x28, 0x28, 0x29, 0x2b, 0x2c, 0x2d, 0x2d, 0x2f, - 0x30, 0x31, 0x31, 0x33, 0x34, 0x35, 0x35, 0x37, - 0x38, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, 0x3c, - 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x43, 0x43, - 0x44, 0x44, 0x45, 0x47, 0x47, 0x48, 0x48, 0x49, - 0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, - 0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53, - 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, - 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, - 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61, - 0x61, 0x61, 0x62, 0x62, 0x63, 0x63, 0x65, 0x65, - 0x65, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, - 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c, - 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, - 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x73, 0x73, - 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77, - 0x77, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x7a, - 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, - 0x7c, 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80, - 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, - 0x82, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, - 0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89, - 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, - 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92, - 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94, - 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, - 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, - 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, - 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, - 0xb3, 0xb3, 0xb3, 0xb4, 0xb3, 0xb4, 0xb4, 0xb4, - 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, - 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, - 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, - 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, - 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, - 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, - 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, - 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, - 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, - 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, - 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, - 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, - 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, - 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, - 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, - 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, - 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, - 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, - 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, - 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, - 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, - 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, - 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, - 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, - 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, - 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, - 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, - 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, - 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, - 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, - 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, - 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed, - 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, - 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, - 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, - 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, - 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, - 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, - 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb} - }, - { /* gamma 3 - from tp6810 + cx0342 */ - {0x08, 0x09, 0x0c, 0x0d, 0x10, 0x11, 0x14, 0x15, - 0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x1f, 0x20, 0x23, - 0x25, 0x26, 0x27, 0x28, 0x2b, 0x2c, 0x2d, 0x2f, - 0x30, 0x31, 0x33, 0x34, 0x35, 0x37, 0x38, 0x39, - 0x3a, 0x3b, 0x3c, 0x3d, 0x3f, 0x40, 0x42, 0x43, - 0x44, 0x45, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b, - 0x4c, 0x4d, 0x4d, 0x4f, 0x50, 0x52, 0x53, 0x53, - 0x54, 0x55, 0x56, 0x56, 0x58, 0x59, 0x5a, 0x5a, - 0x5b, 0x5c, 0x5c, 0x5e, 0x5f, 0x5f, 0x60, 0x61, - 0x61, 0x62, 0x63, 0x63, 0x65, 0x66, 0x66, 0x67, - 0x68, 0x68, 0x69, 0x69, 0x6a, 0x6c, 0x6c, 0x6d, - 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x73, - 0x73, 0x74, 0x74, 0x75, 0x75, 0x77, 0x77, 0x78, - 0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, - 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, - 0x82, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86, - 0x86, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b, - 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f, - 0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92, 0x93, - 0x93, 0x93, 0x94, 0x94, 0x96, 0x96, 0x97, 0x97, - 0x97, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a, - 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, - 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, - 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, - 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa8, 0xa8, - 0xa8, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac, - 0xac, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, - 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, - 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, - 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, - 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, - 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, - 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, - 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, - 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5, - 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, - 0xc7, 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, - 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, - 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, - 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, - 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, - 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, - 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, - 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, - 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, - 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, - 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, - 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, - 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, - 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, - 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, - 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, - 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, - 0xed, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, - 0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, - 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, - 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, - 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, - 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, - 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, - 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, - 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0x03, 0x05, 0x07, 0x09, 0x0a, 0x0c, 0x0d, 0x10, - 0x11, 0x12, 0x14, 0x15, 0x17, 0x18, 0x1a, 0x1b, - 0x1c, 0x1e, 0x1f, 0x20, 0x22, 0x23, 0x25, 0x26, - 0x27, 0x28, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2f, - 0x30, 0x31, 0x33, 0x33, 0x34, 0x35, 0x37, 0x38, - 0x38, 0x39, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3f, - 0x3f, 0x40, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45, - 0x47, 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b, 0x4b, - 0x4c, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x52, 0x52, - 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, 0x58, - 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, - 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61, - 0x61, 0x62, 0x62, 0x63, 0x63, 0x65, 0x65, 0x66, - 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69, - 0x6a, 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e, - 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71, - 0x71, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, - 0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79, - 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, - 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, - 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x84, - 0x84, 0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, - 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, - 0x8a, 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90, - 0x90, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, - 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x96, - 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x98, 0x98, - 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, - 0xab, 0xac, 0xac, 0xac, 0xac, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, - 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, - 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, - 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4, - 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, - 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, - 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, - 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, - 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, - 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, - 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, - 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, - 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, - 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, - 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, - 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, - 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, - 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, - 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, - 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, - 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, - 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, - 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, - 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, - 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, - 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, - 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, - 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, - 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, - 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, - 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, - 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, - 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xee, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef, - 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, - 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, - 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, - 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, - 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, - 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, - 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, - 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, - 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, - 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0x07, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, - 0x16, 0x17, 0x18, 0x1b, 0x1c, 0x1e, 0x1f, 0x20, - 0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2d, - 0x2f, 0x30, 0x31, 0x33, 0x34, 0x35, 0x37, 0x38, - 0x39, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3f, 0x40, - 0x42, 0x43, 0x44, 0x44, 0x45, 0x47, 0x48, 0x49, - 0x4a, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4f, 0x50, - 0x52, 0x52, 0x53, 0x54, 0x55, 0x55, 0x56, 0x58, - 0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5e, - 0x5f, 0x5f, 0x60, 0x61, 0x61, 0x62, 0x63, 0x63, - 0x65, 0x65, 0x66, 0x67, 0x67, 0x68, 0x68, 0x69, - 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, - 0x6f, 0x70, 0x70, 0x71, 0x71, 0x73, 0x73, 0x74, - 0x74, 0x75, 0x75, 0x77, 0x77, 0x78, 0x78, 0x79, - 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7d, - 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81, - 0x82, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86, - 0x88, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b, - 0x8b, 0x8b, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, - 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92, - 0x92, 0x93, 0x93, 0x94, 0x94, 0x94, 0x96, 0x96, - 0x96, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99, - 0x99, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, - 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0xa0, - 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3, - 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, - 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, 0xa9, - 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, - 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xaf, 0xaf, - 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, - 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb4, - 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, - 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, - 0xb9, 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, - 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf, - 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, - 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, - 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, - 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, - 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xcf, - 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, - 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, - 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, - 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, - 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, - 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, - 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, - 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, - 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, - 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, - 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, - 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, - 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, - 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, - 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, - 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, - 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, - 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, - 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, - 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, - 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, - 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} - }, - { /* gamma 4 - from tp6800 + soi763a */ - {0x11, 0x14, 0x15, 0x17, 0x1a, 0x1b, 0x1e, 0x1f, - 0x22, 0x23, 0x25, 0x27, 0x28, 0x2b, 0x2c, 0x2d, - 0x2f, 0x31, 0x33, 0x34, 0x35, 0x38, 0x39, 0x3a, - 0x3b, 0x3c, 0x3d, 0x40, 0x42, 0x43, 0x44, 0x45, - 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4f, - 0x50, 0x52, 0x53, 0x53, 0x54, 0x55, 0x56, 0x58, - 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5f, 0x60, - 0x61, 0x61, 0x62, 0x63, 0x65, 0x65, 0x66, 0x67, - 0x68, 0x68, 0x69, 0x6a, 0x6c, 0x6c, 0x6d, 0x6e, - 0x6f, 0x6f, 0x70, 0x71, 0x71, 0x73, 0x74, 0x74, - 0x75, 0x77, 0x77, 0x78, 0x79, 0x79, 0x7a, 0x7a, - 0x7b, 0x7c, 0x7c, 0x7d, 0x7f, 0x7f, 0x80, 0x80, - 0x81, 0x81, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86, - 0x86, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b, 0x8b, - 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x90, 0x90, 0x91, - 0x91, 0x92, 0x92, 0x93, 0x93, 0x94, 0x94, 0x96, - 0x96, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99, - 0x9a, 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d, - 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, - 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, - 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9, 0xab, - 0xab, 0xab, 0xac, 0xac, 0xad, 0xad, 0xad, 0xae, - 0xae, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, - 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, - 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, - 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xbc, - 0xbc, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf, - 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, - 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5, - 0xc5, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc9, - 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, - 0xcb, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xce, - 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, - 0xd0, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, - 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, - 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, - 0xd9, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, - 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf, - 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, - 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, - 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, - 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, - 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, - 0xec, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, - 0xee, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, - 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, - 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, - 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, - 0xf9, 0xf9, 0xfa, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}, - {0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x14, 0x15, - 0x16, 0x17, 0x1a, 0x1b, 0x1c, 0x1e, 0x1f, 0x20, - 0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2c, - 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34, 0x34, 0x35, - 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, - 0x3f, 0x40, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45, - 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b, 0x4b, 0x4c, - 0x4d, 0x4f, 0x4f, 0x50, 0x52, 0x52, 0x53, 0x54, - 0x54, 0x55, 0x55, 0x56, 0x58, 0x58, 0x59, 0x5a, - 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, - 0x60, 0x60, 0x61, 0x61, 0x62, 0x63, 0x63, 0x65, - 0x65, 0x66, 0x66, 0x67, 0x67, 0x68, 0x68, 0x69, - 0x69, 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e, - 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71, 0x73, - 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x77, 0x77, - 0x78, 0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b, - 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f, - 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, - 0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86, 0x86, - 0x88, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8a, - 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, - 0x8e, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, - 0x91, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x94, - 0x94, 0x94, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, - 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, - 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, - 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, - 0xaa, 0xab, 0xab, 0xac, 0xac, 0xac, 0xad, 0xad, - 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, - 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, - 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, - 0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, - 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, - 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, - 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, - 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, - 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5, - 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, - 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, - 0xca, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, - 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, - 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, - 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, - 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, - 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, - 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, - 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, - 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, - 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, - 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, - 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, - 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, - 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, - 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, - 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, - 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, - 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef, - 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, - 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, - 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, - 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, - 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, - 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}, - {0x0d, 0x10, 0x11, 0x14, 0x15, 0x17, 0x18, 0x1b, - 0x1c, 0x1e, 0x20, 0x22, 0x23, 0x26, 0x27, 0x28, - 0x29, 0x2b, 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34, - 0x35, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, - 0x3f, 0x40, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48, - 0x49, 0x4a, 0x4b, 0x4b, 0x4c, 0x4d, 0x4f, 0x50, - 0x52, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58, - 0x59, 0x5a, 0x5a, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f, - 0x60, 0x60, 0x61, 0x62, 0x62, 0x63, 0x65, 0x65, - 0x66, 0x67, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6c, - 0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70, - 0x71, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x77, - 0x78, 0x78, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, - 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, - 0x81, 0x81, 0x82, 0x82, 0x84, 0x84, 0x85, 0x85, - 0x86, 0x86, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, - 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, - 0x8f, 0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92, - 0x93, 0x93, 0x94, 0x94, 0x94, 0x96, 0x96, 0x97, - 0x97, 0x98, 0x98, 0x98, 0x99, 0x99, 0x9a, 0x9a, - 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, - 0x9d, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, - 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, - 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa8, 0xa8, - 0xa8, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac, - 0xac, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, - 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, - 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb4, - 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, - 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, - 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, - 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, - 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc3, - 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5, - 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, - 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, - 0xca, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, - 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, - 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, - 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, - 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, - 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, - 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, - 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, - 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, - 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, - 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, - 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, - 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, - 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, - 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, - 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, - 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, - 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, - 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, - 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, - 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb} - }, - { /* gamma 5 */ - {0x16, 0x18, 0x19, 0x1b, 0x1d, 0x1e, 0x20, 0x21, - 0x23, 0x24, 0x25, 0x27, 0x28, 0x2a, 0x2b, 0x2c, - 0x2d, 0x2f, 0x30, 0x31, 0x32, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, - 0x4f, 0x50, 0x51, 0x51, 0x52, 0x53, 0x54, 0x55, - 0x56, 0x56, 0x57, 0x58, 0x59, 0x59, 0x5a, 0x5b, - 0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 0x5f, 0x60, 0x61, - 0x62, 0x62, 0x63, 0x64, 0x64, 0x65, 0x66, 0x66, - 0x67, 0x68, 0x68, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, - 0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70, - 0x71, 0x71, 0x72, 0x73, 0x73, 0x74, 0x74, 0x75, - 0x75, 0x76, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, - 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7d, 0x7d, 0x7e, - 0x7e, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x82, - 0x82, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85, 0x85, - 0x86, 0x86, 0x87, 0x87, 0x88, 0x88, 0x89, 0x89, - 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8d, - 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x90, 0x90, - 0x91, 0x91, 0x91, 0x92, 0x92, 0x93, 0x93, 0x94, - 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x96, 0x97, - 0x97, 0x98, 0x98, 0x98, 0x99, 0x99, 0x9a, 0x9a, - 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d, - 0x9d, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f, 0xa0, 0xa0, - 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3, - 0xa3, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, - 0xa6, 0xa6, 0xa7, 0xa7, 0xa7, 0xa8, 0xa8, 0xa8, - 0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xab, 0xab, - 0xab, 0xac, 0xac, 0xac, 0xad, 0xad, 0xad, 0xae, - 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, - 0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5, - 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, - 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, - 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, - 0xbc, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, - 0xc1, 0xc1, 0xc1, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, - 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5, - 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, - 0xc7, 0xc8, 0xc8, 0xc8, 0xc8, 0xc9, 0xc9, 0xc9, - 0xc9, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, - 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, - 0xcd, 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, - 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, - 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, - 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd5, 0xd5, 0xd5, - 0xd5, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, - 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, - 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, - 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, - 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, - 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, - 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, - 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, - 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, - 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea, 0xea, 0xeb, - 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, - 0xed, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, - 0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3, - 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, - 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, - 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, - 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, - 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0x0f, 0x11, 0x12, 0x14, 0x15, 0x16, 0x18, 0x19, - 0x1a, 0x1b, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, - 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, - 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x31, 0x32, - 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x38, 0x39, - 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3e, 0x3f, 0x3f, - 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x44, 0x45, - 0x46, 0x47, 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b, - 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0x4e, 0x4f, 0x50, - 0x50, 0x51, 0x51, 0x52, 0x53, 0x53, 0x54, 0x54, - 0x55, 0x55, 0x56, 0x56, 0x57, 0x58, 0x58, 0x59, - 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5d, - 0x5d, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61, - 0x61, 0x62, 0x62, 0x63, 0x63, 0x64, 0x64, 0x65, - 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x68, 0x68, - 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, - 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, - 0x6f, 0x70, 0x70, 0x71, 0x71, 0x71, 0x72, 0x72, - 0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x75, - 0x76, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78, 0x78, - 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, - 0x7b, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, - 0x7e, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x81, - 0x81, 0x81, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, - 0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x86, - 0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88, - 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d, - 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, - 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91, - 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94, - 0x94, 0x94, 0x94, 0x95, 0x95, 0x95, 0x96, 0x96, - 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, - 0x98, 0x98, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9f, 0x9f, 0x9f, 0x9f, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, - 0xa9, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xab, 0xab, - 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, - 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, - 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, - 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, - 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, - 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, - 0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, - 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, - 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, - 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, - 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, - 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, - 0xc7, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc9, 0xc9, - 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, - 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, - 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, - 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, - 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3, - 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, - 0xd4, 0xd4, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, - 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7, - 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, - 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, - 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, - 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, - 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, - 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, - 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, - 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, - 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, - 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, - 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, - 0xe9, 0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea, - 0xea, 0xea, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, - 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, - 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee, - 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, - 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, - 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, - 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, - 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, - 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, - 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, - 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, - 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, - 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0x13, 0x15, 0x16, 0x18, 0x19, 0x1b, 0x1c, 0x1e, - 0x1f, 0x20, 0x22, 0x23, 0x24, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, - 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, - 0x42, 0x43, 0x44, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, - 0x4f, 0x50, 0x50, 0x51, 0x52, 0x53, 0x53, 0x54, - 0x55, 0x55, 0x56, 0x57, 0x57, 0x58, 0x59, 0x59, - 0x5a, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5f, - 0x5f, 0x60, 0x60, 0x61, 0x62, 0x62, 0x63, 0x63, - 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68, - 0x69, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, - 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70, - 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x74, 0x74, - 0x75, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78, - 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, - 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, - 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x83, - 0x83, 0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86, - 0x86, 0x87, 0x87, 0x88, 0x88, 0x88, 0x89, 0x89, - 0x89, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, - 0x8c, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, - 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92, - 0x92, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x95, - 0x95, 0x95, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, - 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a, - 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, - 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f, - 0x9f, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, - 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa8, 0xa8, 0xa8, 0xa9, - 0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xab, 0xab, - 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xad, 0xad, - 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, - 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, - 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5, - 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, - 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, - 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, - 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, - 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1, - 0xc1, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, - 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5, - 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, - 0xc7, 0xc7, 0xc7, 0xc7, 0xc8, 0xc8, 0xc8, 0xc8, - 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, - 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, - 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, - 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, - 0xd1, 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3, - 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, - 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd6, 0xd6, 0xd6, - 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, - 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, - 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, - 0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, - 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, - 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, - 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, - 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, - 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, - 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, - 0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea, 0xea, - 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, - 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, - 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef, - 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, - 0xf2, 0xf2, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, - 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, - 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, - 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, - 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, - 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, - 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, - 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - }, - }; - - reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00); - if (sd->bridge == BRIDGE_TP6810) - reg_w(gspca_dev, 0x02, 0x28); -/* msleep(50); */ - bulk_w(gspca_dev, 0x00, gamma_tb[gamma][0], 1024); - bulk_w(gspca_dev, 0x01, gamma_tb[gamma][1], 1024); - bulk_w(gspca_dev, 0x02, gamma_tb[gamma][2], 1024); - if (sd->bridge == BRIDGE_TP6810) { - int i; - - reg_w(gspca_dev, 0x02, 0x2b); - reg_w(gspca_dev, 0x02, 0x28); - for (i = 0; i < 6; i++) - reg_w(gspca_dev, TP6800_R55_GAMMA_R, - gamma_tb[gamma][0][i]); - reg_w(gspca_dev, 0x02, 0x2b); - reg_w(gspca_dev, 0x02, 0x28); - for (i = 0; i < 6; i++) - reg_w(gspca_dev, TP6800_R56_GAMMA_G, - gamma_tb[gamma][1][i]); - reg_w(gspca_dev, 0x02, 0x2b); - reg_w(gspca_dev, 0x02, 0x28); - for (i = 0; i < 6; i++) - reg_w(gspca_dev, TP6800_R57_GAMMA_B, - gamma_tb[gamma][2][i]); - reg_w(gspca_dev, 0x02, 0x28); - } - reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03); -/* msleep(50); */ -} - -static void setsharpness(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->bridge == BRIDGE_TP6800) { - val |= 0x08; /* grid compensation enable */ - if (gspca_dev->width == 640) - reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */ - else - val |= 0x04; /* scaling down enable */ - reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, val); - } else { - val = (val << 5) | 0x08; - reg_w(gspca_dev, 0x59, val); - } -} - -static void setautogain(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->ag_cnt = val ? AG_CNT_START : -1; -} - -/* set the resolution for sensor cx0342 */ -static void set_resolution(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00); - if (gspca_dev->width == 320) { - reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x06); - msleep(100); - i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01); - msleep(100); - reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03); - reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01); /* qvga */ - reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, 0x0d); - i2c_w(gspca_dev, CX0342_EXPO_LINE_L, 0x37); - i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x01); - } else { - reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x05); - msleep(100); - i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01); - msleep(100); - reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03); - reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */ - reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, 0x09); - i2c_w(gspca_dev, CX0342_EXPO_LINE_L, 0xcf); - i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00); - } - i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01); - bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342], - ARRAY_SIZE(color_gain[0])); - setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma)); - if (sd->sensor == SENSOR_SOI763A) - setquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual)); -} - -/* convert the frame rate to a tp68x0 value */ -static int get_fr_idx(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i; - - if (sd->bridge == BRIDGE_TP6800) { - for (i = 0; i < ARRAY_SIZE(rates) - 1; i++) { - if (sd->framerate >= rates[i]) - break; - } - i = 6 - i; /* 1 = 5fps .. 6 = 30fps */ - - /* 640x480 * 30 fps does not work */ - if (i == 6 /* if 30 fps */ - && gspca_dev->width == 640) - i = 0x05; /* 15 fps */ - } else { - for (i = 0; i < ARRAY_SIZE(rates_6810) - 1; i++) { - if (sd->framerate >= rates_6810[i]) - break; - } - i = 7 - i; /* 3 = 5fps .. 7 = 30fps */ - - /* 640x480 * 30 fps does not work */ - if (i == 7 /* if 30 fps */ - && gspca_dev->width == 640) - i = 6; /* 15 fps */ - i |= 0x80; /* clock * 1 */ - } - return i; -} - -static void setframerate(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 fr_idx; - - fr_idx = get_fr_idx(gspca_dev); - - if (sd->bridge == BRIDGE_TP6810) { - reg_r(gspca_dev, 0x7b); - reg_w(gspca_dev, 0x7b, - sd->sensor == SENSOR_CX0342 ? 0x10 : 0x90); - if (val >= 128) - fr_idx = 0xf0; /* lower frame rate */ - } - - reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, fr_idx); - - if (sd->sensor == SENSOR_CX0342) - i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01); -} - -static void setrgain(struct gspca_dev *gspca_dev, s32 rgain) -{ - i2c_w(gspca_dev, CX0342_RAW_RGAIN_H, rgain >> 8); - i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, rgain); - i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80); -} - -static int sd_setgain(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - s32 val = gspca_dev->gain->val; - - if (sd->sensor == SENSOR_CX0342) { - s32 old = gspca_dev->gain->cur.val ? - gspca_dev->gain->cur.val : 1; - - sd->blue->val = sd->blue->val * val / old; - if (sd->blue->val > 4095) - sd->blue->val = 4095; - sd->red->val = sd->red->val * val / old; - if (sd->red->val > 4095) - sd->red->val = 4095; - } - if (gspca_dev->streaming) { - if (sd->sensor == SENSOR_CX0342) - setexposure(gspca_dev, gspca_dev->exposure->val, - gspca_dev->gain->val, - sd->blue->val, sd->red->val); - else - setexposure(gspca_dev, gspca_dev->exposure->val, - gspca_dev->gain->val, 0, 0); - } - return gspca_dev->usb_err; -} - -static void setbgain(struct gspca_dev *gspca_dev, s32 bgain) -{ - i2c_w(gspca_dev, CX0342_RAW_BGAIN_H, bgain >> 8); - i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, bgain); - i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80); -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->bridge = id->driver_info; - - gspca_dev->cam.cam_mode = vga_mode; - gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); - gspca_dev->cam.mode_framerates = sd->bridge == BRIDGE_TP6800 ? - framerates : framerates_6810; - - sd->framerate = 30; /* default: 30 fps */ - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - static const struct cmd tp6800_preinit[] = { - {TP6800_R10_SIF_TYPE, 0x01}, /* sif */ - {TP6800_R11_SIF_CONTROL, 0x01}, - {TP6800_R15_GPIO_PU, 0x9f}, - {TP6800_R16_GPIO_PD, 0x9f}, - {TP6800_R17_GPIO_IO, 0x80}, - {TP6800_R18_GPIO_DATA, 0x40}, /* LED off */ - }; - static const struct cmd tp6810_preinit[] = { - {TP6800_R2F_TIMING_CFG, 0x2f}, - {TP6800_R15_GPIO_PU, 0x6f}, - {TP6800_R16_GPIO_PD, 0x40}, - {TP6800_R17_GPIO_IO, 0x9f}, - {TP6800_R18_GPIO_DATA, 0xc1}, /* LED off */ - }; - - if (sd->bridge == BRIDGE_TP6800) - reg_w_buf(gspca_dev, tp6800_preinit, - ARRAY_SIZE(tp6800_preinit)); - else - reg_w_buf(gspca_dev, tp6810_preinit, - ARRAY_SIZE(tp6810_preinit)); - msleep(15); - reg_r(gspca_dev, TP6800_R18_GPIO_DATA); - PDEBUG(D_PROBE, "gpio: %02x", gspca_dev->usb_buf[0]); -/* values: - * 0x80: snapshot button - * 0x40: LED - * 0x20: (bridge / sensor) reset for tp6810 ? - * 0x07: sensor type ? - */ - - /* guess the sensor type */ - if (force_sensor >= 0) { - sd->sensor = force_sensor; - } else { - if (sd->bridge == BRIDGE_TP6800) { -/*fixme: not sure this is working*/ - switch (gspca_dev->usb_buf[0] & 0x07) { - case 0: - sd->sensor = SENSOR_SOI763A; - break; - case 1: - sd->sensor = SENSOR_CX0342; - break; - } - } else { - int sensor; - - sensor = probe_6810(gspca_dev); - if (sensor < 0) { - pr_warn("Unknown sensor %d - forced to soi763a\n", - -sensor); - sensor = SENSOR_SOI763A; - } - sd->sensor = sensor; - } - } - if (sd->sensor == SENSOR_SOI763A) { - pr_info("Sensor soi763a\n"); - if (sd->bridge == BRIDGE_TP6810) { - soi763a_6810_init(gspca_dev); - } - } else { - pr_info("Sensor cx0342\n"); - if (sd->bridge == BRIDGE_TP6810) { - cx0342_6810_init(gspca_dev); - } - } - - set_dqt(gspca_dev, 0); - return 0; -} - -/* This function is called before choosing the alt setting */ -static int sd_isoc_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - static const struct cmd cx_sensor_init[] = { - {CX0342_AUTO_ADC_CALIB, 0x81}, - {CX0342_EXPO_LINE_L, 0x37}, - {CX0342_EXPO_LINE_H, 0x01}, - {CX0342_RAW_GRGAIN_L, 0x00}, - {CX0342_RAW_GBGAIN_L, 0x00}, - {CX0342_RAW_RGAIN_L, 0x00}, - {CX0342_RAW_BGAIN_L, 0x00}, - {CX0342_SYS_CTRL_0, 0x81}, - }; - static const struct cmd cx_bridge_init[] = { - {0x4d, 0x00}, - {0x4c, 0xff}, - {0x4e, 0xff}, - {0x4f, 0x00}, - }; - static const struct cmd ov_sensor_init[] = { - {0x10, 0x75}, /* exposure */ - {0x76, 0x03}, - {0x00, 0x00}, /* gain */ - }; - static const struct cmd ov_bridge_init[] = { - {0x7b, 0x90}, - {TP6800_R3F_FRAME_RATE, 0x87}, - }; - - if (sd->bridge == BRIDGE_TP6800) - return 0; - if (sd->sensor == SENSOR_CX0342) { - reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20); - reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87); - i2c_w_buf(gspca_dev, cx_sensor_init, - ARRAY_SIZE(cx_sensor_init)); - reg_w_buf(gspca_dev, cx_bridge_init, - ARRAY_SIZE(cx_bridge_init)); - bulk_w(gspca_dev, 0x03, color_null, sizeof color_null); - reg_w(gspca_dev, 0x59, 0x40); - } else { - reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x21); - i2c_w_buf(gspca_dev, ov_sensor_init, - ARRAY_SIZE(ov_sensor_init)); - reg_r(gspca_dev, 0x7b); - reg_w_buf(gspca_dev, ov_bridge_init, - ARRAY_SIZE(ov_bridge_init)); - } - reg_w(gspca_dev, TP6800_R78_FORMAT, - gspca_dev->curr_mode ? 0x00 : 0x01); - return gspca_dev->usb_err; -} - -static void set_led(struct gspca_dev *gspca_dev, int on) -{ - u8 data; - - reg_r(gspca_dev, TP6800_R18_GPIO_DATA); - data = gspca_dev->usb_buf[0]; - if (on) - data &= ~0x40; - else - data |= 0x40; - reg_w(gspca_dev, TP6800_R18_GPIO_DATA, data); -} - -static void cx0342_6800_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - static const struct cmd reg_init[] = { - /* fixme: is this useful? */ - {TP6800_R17_GPIO_IO, 0x9f}, - {TP6800_R16_GPIO_PD, 0x40}, - {TP6800_R10_SIF_TYPE, 0x00}, /* i2c 8 bits */ - {TP6800_R50, 0x00}, - {TP6800_R51, 0x00}, - {TP6800_R52, 0xff}, - {TP6800_R53, 0x03}, - {TP6800_R54_DARK_CFG, 0x07}, - {TP6800_R5C_EDGE_THRLD, 0x40}, - {TP6800_R7A_BLK_THRLD, 0x40}, - {TP6800_R2F_TIMING_CFG, 0x17}, - {TP6800_R30_SENSOR_CFG, 0x18}, /* G1B..RG0 */ - {TP6800_R37_FRONT_DARK_ST, 0x00}, - {TP6800_R38_FRONT_DARK_END, 0x00}, - {TP6800_R39_REAR_DARK_ST_L, 0x00}, - {TP6800_R3A_REAR_DARK_ST_H, 0x00}, - {TP6800_R3B_REAR_DARK_END_L, 0x00}, - {TP6800_R3C_REAR_DARK_END_H, 0x00}, - {TP6800_R3D_HORIZ_DARK_LINE_L, 0x00}, - {TP6800_R3E_HORIZ_DARK_LINE_H, 0x00}, - {TP6800_R21_ENDP_1_CTL, 0x03}, - - {TP6800_R31_PIXEL_START, 0x0b}, - {TP6800_R32_PIXEL_END_L, 0x8a}, - {TP6800_R33_PIXEL_END_H, 0x02}, - {TP6800_R34_LINE_START, 0x0e}, - {TP6800_R35_LINE_END_L, 0xf4}, - {TP6800_R36_LINE_END_H, 0x01}, - {TP6800_R78_FORMAT, 0x00}, - {TP6800_R12_SIF_ADDR_S, 0x20}, /* cx0342 i2c addr */ - }; - static const struct cmd sensor_init[] = { - {CX0342_OUTPUT_CTRL, 0x07}, - {CX0342_BYPASS_MODE, 0x58}, - {CX0342_GPXLTHD_L, 0x16}, - {CX0342_RBPXLTHD_L, 0x16}, - {CX0342_PLANETHD_L, 0xc0}, - {CX0342_PLANETHD_H, 0x03}, - {CX0342_RB_GAP_L, 0xff}, - {CX0342_RB_GAP_H, 0x07}, - {CX0342_G_GAP_L, 0xff}, - {CX0342_G_GAP_H, 0x07}, - {CX0342_RST_OVERFLOW_L, 0x5c}, - {CX0342_RST_OVERFLOW_H, 0x01}, - {CX0342_DATA_OVERFLOW_L, 0xfc}, - {CX0342_DATA_OVERFLOW_H, 0x03}, - {CX0342_DATA_UNDERFLOW_L, 0x00}, - {CX0342_DATA_UNDERFLOW_H, 0x00}, - {CX0342_SYS_CTRL_0, 0x40}, - {CX0342_GLOBAL_GAIN, 0x01}, - {CX0342_CLOCK_GEN, 0x00}, - {CX0342_SYS_CTRL_0, 0x02}, - {CX0342_IDLE_CTRL, 0x05}, - {CX0342_ADCGN, 0x00}, - {CX0342_ADC_CTL, 0x00}, - {CX0342_LVRST_BLBIAS, 0x01}, - {CX0342_VTHSEL, 0x0b}, - {CX0342_RAMP_RIV, 0x0b}, - {CX0342_LDOSEL, 0x07}, - {CX0342_SPV_VALUE_L, 0x40}, - {CX0342_SPV_VALUE_H, 0x02}, - }; - - reg_w_buf(gspca_dev, reg_init, ARRAY_SIZE(reg_init)); - i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init)); - i2c_w_buf(gspca_dev, cx0342_timing_seq, ARRAY_SIZE(cx0342_timing_seq)); - reg_w(gspca_dev, TP6800_R5C_EDGE_THRLD, 0x10); - reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00); - i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00); - i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01); - if (sd->sensor == SENSOR_CX0342) - setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure), - v4l2_ctrl_g_ctrl(gspca_dev->gain), - v4l2_ctrl_g_ctrl(sd->blue), - v4l2_ctrl_g_ctrl(sd->red)); - else - setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure), - v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0); - set_led(gspca_dev, 1); - set_resolution(gspca_dev); -} - -static void cx0342_6810_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - static const struct cmd sensor_init_2[] = { - {CX0342_EXPO_LINE_L, 0x6f}, - {CX0342_EXPO_LINE_H, 0x02}, - {CX0342_RAW_GRGAIN_L, 0x00}, - {CX0342_RAW_GBGAIN_L, 0x00}, - {CX0342_RAW_RGAIN_L, 0x00}, - {CX0342_RAW_BGAIN_L, 0x00}, - {CX0342_SYS_CTRL_0, 0x81}, - }; - static const struct cmd bridge_init_2[] = { - {0x4d, 0x00}, - {0x4c, 0xff}, - {0x4e, 0xff}, - {0x4f, 0x00}, - {TP6800_R7A_BLK_THRLD, 0x00}, - {TP6800_R79_QUALITY, 0x04}, - {TP6800_R79_QUALITY, 0x01}, - }; - static const struct cmd bridge_init_3[] = { - {TP6800_R31_PIXEL_START, 0x08}, - {TP6800_R32_PIXEL_END_L, 0x87}, - {TP6800_R33_PIXEL_END_H, 0x02}, - {TP6800_R34_LINE_START, 0x0e}, - {TP6800_R35_LINE_END_L, 0xf4}, - {TP6800_R36_LINE_END_H, 0x01}, - }; - static const struct cmd sensor_init_3[] = { - {CX0342_AUTO_ADC_CALIB, 0x81}, - {CX0342_EXPO_LINE_L, 0x6f}, - {CX0342_EXPO_LINE_H, 0x02}, - {CX0342_RAW_GRGAIN_L, 0x00}, - {CX0342_RAW_GBGAIN_L, 0x00}, - {CX0342_RAW_RGAIN_L, 0x00}, - {CX0342_RAW_BGAIN_L, 0x00}, - {CX0342_SYS_CTRL_0, 0x81}, - }; - static const struct cmd bridge_init_5[] = { - {0x4d, 0x00}, - {0x4c, 0xff}, - {0x4e, 0xff}, - {0x4f, 0x00}, - }; - static const struct cmd sensor_init_4[] = { - {CX0342_EXPO_LINE_L, 0xd3}, - {CX0342_EXPO_LINE_H, 0x01}, -/*fixme: gains, but 00..80 only*/ - {CX0342_RAW_GRGAIN_L, 0x40}, - {CX0342_RAW_GBGAIN_L, 0x40}, - {CX0342_RAW_RGAIN_L, 0x40}, - {CX0342_RAW_BGAIN_L, 0x40}, - {CX0342_SYS_CTRL_0, 0x81}, - }; - static const struct cmd sensor_init_5[] = { - {CX0342_IDLE_CTRL, 0x05}, - {CX0342_ADCGN, 0x00}, - {CX0342_ADC_CTL, 0x00}, - {CX0342_LVRST_BLBIAS, 0x01}, - {CX0342_VTHSEL, 0x0b}, - {CX0342_RAMP_RIV, 0x0b}, - {CX0342_LDOSEL, 0x07}, - {CX0342_SPV_VALUE_L, 0x40}, - {CX0342_SPV_VALUE_H, 0x02}, - {CX0342_AUTO_ADC_CALIB, 0x81}, - }; - - reg_w(gspca_dev, 0x22, gspca_dev->alt); - i2c_w_buf(gspca_dev, sensor_init_2, ARRAY_SIZE(sensor_init_2)); - reg_w_buf(gspca_dev, bridge_init_2, ARRAY_SIZE(bridge_init_2)); - reg_w_buf(gspca_dev, tp6810_cx_init_common, - ARRAY_SIZE(tp6810_cx_init_common)); - reg_w_buf(gspca_dev, bridge_init_3, ARRAY_SIZE(bridge_init_3)); - if (gspca_dev->curr_mode) { - reg_w(gspca_dev, 0x4a, 0x7f); - reg_w(gspca_dev, 0x07, 0x05); - reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */ - } else { - reg_w(gspca_dev, 0x4a, 0xff); - reg_w(gspca_dev, 0x07, 0x85); - reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01); /* qvga */ - } - setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma)); - reg_w_buf(gspca_dev, tp6810_bridge_start, - ARRAY_SIZE(tp6810_bridge_start)); - setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness)); - bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342], - ARRAY_SIZE(color_gain[0])); - reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87); - i2c_w_buf(gspca_dev, sensor_init_3, ARRAY_SIZE(sensor_init_3)); - reg_w_buf(gspca_dev, bridge_init_5, ARRAY_SIZE(bridge_init_5)); - i2c_w_buf(gspca_dev, sensor_init_4, ARRAY_SIZE(sensor_init_4)); - reg_w_buf(gspca_dev, bridge_init_5, ARRAY_SIZE(bridge_init_5)); - i2c_w_buf(gspca_dev, sensor_init_5, ARRAY_SIZE(sensor_init_5)); - - set_led(gspca_dev, 1); -/* setquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual)); */ -} - -static void soi763a_6800_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - static const struct cmd reg_init[] = { - {TP6800_R79_QUALITY, 0x04}, - {TP6800_R79_QUALITY, 0x01}, - {TP6800_R10_SIF_TYPE, 0x00}, /* i2c 8 bits */ - - {TP6800_R50, 0x00}, - {TP6800_R51, 0x00}, - {TP6800_R52, 0xff}, - {TP6800_R53, 0x03}, - {TP6800_R54_DARK_CFG, 0x07}, - {TP6800_R5C_EDGE_THRLD, 0x40}, - - {TP6800_R79_QUALITY, 0x03}, - {TP6800_R7A_BLK_THRLD, 0x40}, - - {TP6800_R2F_TIMING_CFG, 0x46}, - {TP6800_R30_SENSOR_CFG, 0x10}, /* BG1..G0R */ - {TP6800_R37_FRONT_DARK_ST, 0x00}, - {TP6800_R38_FRONT_DARK_END, 0x00}, - {TP6800_R39_REAR_DARK_ST_L, 0x00}, - {TP6800_R3A_REAR_DARK_ST_H, 0x00}, - {TP6800_R3B_REAR_DARK_END_L, 0x00}, - {TP6800_R3C_REAR_DARK_END_H, 0x00}, - {TP6800_R3D_HORIZ_DARK_LINE_L, 0x00}, - {TP6800_R3E_HORIZ_DARK_LINE_H, 0x00}, - {TP6800_R21_ENDP_1_CTL, 0x03}, - - {TP6800_R3F_FRAME_RATE, 0x04}, /* 15 fps */ - {TP6800_R5D_DEMOSAIC_CFG, 0x0e}, /* scale down - medium edge */ - - {TP6800_R31_PIXEL_START, 0x1b}, - {TP6800_R32_PIXEL_END_L, 0x9a}, - {TP6800_R33_PIXEL_END_H, 0x02}, - {TP6800_R34_LINE_START, 0x0f}, - {TP6800_R35_LINE_END_L, 0xf4}, - {TP6800_R36_LINE_END_H, 0x01}, - {TP6800_R78_FORMAT, 0x01}, /* qvga */ - {TP6800_R12_SIF_ADDR_S, 0x21}, /* soi763a i2c addr */ - {TP6800_R1A_SIF_TX_DATA2, 0x00}, - }; - static const struct cmd sensor_init[] = { - {0x12, 0x48}, /* mirror - RGB */ - {0x13, 0xa0}, /* clock - no AGC nor AEC */ - {0x03, 0xa4}, /* saturation */ - {0x04, 0x30}, /* hue */ - {0x05, 0x88}, /* contrast */ - {0x06, 0x60}, /* brightness */ - {0x10, 0x41}, /* AEC */ - {0x11, 0x40}, /* clock rate */ - {0x13, 0xa0}, - {0x14, 0x00}, /* 640x480 */ - {0x15, 0x14}, - {0x1f, 0x41}, - {0x20, 0x80}, - {0x23, 0xee}, - {0x24, 0x50}, - {0x25, 0x7a}, - {0x26, 0x00}, - {0x27, 0xe2}, - {0x28, 0xb0}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x2d, 0x81}, - {0x2f, 0x9d}, - {0x60, 0x80}, - {0x61, 0x00}, - {0x62, 0x88}, - {0x63, 0x11}, - {0x64, 0x89}, - {0x65, 0x00}, - {0x67, 0x94}, - {0x68, 0x7a}, - {0x69, 0x0f}, - {0x6c, 0x80}, - {0x6d, 0x80}, - {0x6e, 0x80}, - {0x6f, 0xff}, - {0x71, 0x20}, - {0x74, 0x20}, - {0x75, 0x86}, - {0x77, 0xb5}, - {0x17, 0x18}, /* H href start */ - {0x18, 0xbf}, /* H href end */ - {0x19, 0x03}, /* V start */ - {0x1a, 0xf8}, /* V end */ - {0x01, 0x80}, /* blue gain */ - {0x02, 0x80}, /* red gain */ - }; - - reg_w_buf(gspca_dev, reg_init, ARRAY_SIZE(reg_init)); - - i2c_w(gspca_dev, 0x12, 0x80); /* sensor reset */ - msleep(10); - - i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init)); - - reg_w(gspca_dev, TP6800_R5C_EDGE_THRLD, 0x10); - reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00); - - setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness)); - - bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A], - ARRAY_SIZE(color_gain[0])); - - set_led(gspca_dev, 1); - if (sd->sensor == SENSOR_CX0342) - setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure), - v4l2_ctrl_g_ctrl(gspca_dev->gain), - v4l2_ctrl_g_ctrl(sd->blue), - v4l2_ctrl_g_ctrl(sd->red)); - else - setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure), - v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0); - if (sd->sensor == SENSOR_SOI763A) - setquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual)); - setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma)); -} - -static void soi763a_6810_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - static const struct cmd bridge_init_2[] = { - {TP6800_R7A_BLK_THRLD, 0x00}, - {TP6800_R79_QUALITY, 0x04}, - {TP6800_R79_QUALITY, 0x01}, - }; - static const struct cmd bridge_init_3[] = { - {TP6800_R31_PIXEL_START, 0x20}, - {TP6800_R32_PIXEL_END_L, 0x9f}, - {TP6800_R33_PIXEL_END_H, 0x02}, - {TP6800_R34_LINE_START, 0x13}, - {TP6800_R35_LINE_END_L, 0xf8}, - {TP6800_R36_LINE_END_H, 0x01}, - }; - static const struct cmd bridge_init_6[] = { - {0x08, 0xff}, - {0x09, 0xff}, - {0x0a, 0x5f}, - {0x0b, 0x80}, - }; - - reg_w(gspca_dev, 0x22, gspca_dev->alt); - bulk_w(gspca_dev, 0x03, color_null, sizeof color_null); - reg_w(gspca_dev, 0x59, 0x40); - if (sd->sensor == SENSOR_CX0342) - setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure), - v4l2_ctrl_g_ctrl(gspca_dev->gain), - v4l2_ctrl_g_ctrl(sd->blue), - v4l2_ctrl_g_ctrl(sd->red)); - else - setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure), - v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0); - reg_w_buf(gspca_dev, bridge_init_2, ARRAY_SIZE(bridge_init_2)); - reg_w_buf(gspca_dev, tp6810_ov_init_common, - ARRAY_SIZE(tp6810_ov_init_common)); - reg_w_buf(gspca_dev, bridge_init_3, ARRAY_SIZE(bridge_init_3)); - if (gspca_dev->curr_mode) { - reg_w(gspca_dev, 0x4a, 0x7f); - reg_w(gspca_dev, 0x07, 0x05); - reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */ - } else { - reg_w(gspca_dev, 0x4a, 0xff); - reg_w(gspca_dev, 0x07, 0x85); - reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01); /* qvga */ - } - setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma)); - reg_w_buf(gspca_dev, tp6810_bridge_start, - ARRAY_SIZE(tp6810_bridge_start)); - - if (gspca_dev->curr_mode) { - reg_w(gspca_dev, 0x4f, 0x00); - reg_w(gspca_dev, 0x4e, 0x7c); - } - - reg_w(gspca_dev, 0x00, 0x00); - - setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness)); - bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A], - ARRAY_SIZE(color_gain[0])); - set_led(gspca_dev, 1); - reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0xf0); - if (sd->sensor == SENSOR_CX0342) - setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure), - v4l2_ctrl_g_ctrl(gspca_dev->gain), - v4l2_ctrl_g_ctrl(sd->blue), - v4l2_ctrl_g_ctrl(sd->red)); - else - setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure), - v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0); - reg_w_buf(gspca_dev, bridge_init_6, ARRAY_SIZE(bridge_init_6)); -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width); - set_dqt(gspca_dev, sd->quality); - if (sd->bridge == BRIDGE_TP6800) { - if (sd->sensor == SENSOR_CX0342) - cx0342_6800_start(gspca_dev); - else - soi763a_6800_start(gspca_dev); - } else { - if (sd->sensor == SENSOR_CX0342) - cx0342_6810_start(gspca_dev); - else - soi763a_6810_start(gspca_dev); - reg_w_buf(gspca_dev, tp6810_late_start, - ARRAY_SIZE(tp6810_late_start)); - reg_w(gspca_dev, 0x80, 0x03); - reg_w(gspca_dev, 0x82, gspca_dev->curr_mode ? 0x0a : 0x0e); - - if (sd->sensor == SENSOR_CX0342) - setexposure(gspca_dev, - v4l2_ctrl_g_ctrl(gspca_dev->exposure), - v4l2_ctrl_g_ctrl(gspca_dev->gain), - v4l2_ctrl_g_ctrl(sd->blue), - v4l2_ctrl_g_ctrl(sd->red)); - else - setexposure(gspca_dev, - v4l2_ctrl_g_ctrl(gspca_dev->exposure), - v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0); - if (sd->sensor == SENSOR_SOI763A) - setquality(gspca_dev, - v4l2_ctrl_g_ctrl(sd->jpegqual)); - if (sd->bridge == BRIDGE_TP6810) - setautogain(gspca_dev, - v4l2_ctrl_g_ctrl(gspca_dev->autogain)); - } - - setframerate(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure)); - - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->bridge == BRIDGE_TP6800) - reg_w(gspca_dev, TP6800_R2F_TIMING_CFG, 0x03); - set_led(gspca_dev, 0); - reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, - int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* the start of frame contains: - * ff d8 - * ff fe - * width / 16 - * height / 8 - * quality - */ - if (sd->bridge == BRIDGE_TP6810) { - if (*data != 0x5a) { -/*fixme: don't discard the whole frame..*/ - if (*data == 0xaa || *data == 0x00) - return; - if (*data > 0xc0) { - PDEBUG(D_FRAM, "bad frame"); - gspca_dev->last_packet_type = DISCARD_PACKET; - return; - } - } - data++; - len--; - if (*data == 0xff && data[1] == 0xd8) { -/*fixme: there may be information in the 4 high bits*/ - if ((data[6] & 0x0f) != sd->quality) - set_dqt(gspca_dev, data[6] & 0x0f); - gspca_frame_add(gspca_dev, FIRST_PACKET, - sd->jpeg_hdr, JPEG_HDR_SZ); - gspca_frame_add(gspca_dev, INTER_PACKET, - data + 7, len - 7); - } else if (data[len - 2] == 0xff && data[len - 1] == 0xd9) { - gspca_frame_add(gspca_dev, LAST_PACKET, - data, len); - } else { - gspca_frame_add(gspca_dev, INTER_PACKET, - data, len); - } - return; - } - - switch (*data) { - case 0x55: - gspca_frame_add(gspca_dev, LAST_PACKET, data, 0); - - if (len < 8 - || data[1] != 0xff || data[2] != 0xd8 - || data[3] != 0xff || data[4] != 0xfe) { - - /* Have only seen this with corrupt frames */ - gspca_dev->last_packet_type = DISCARD_PACKET; - return; - } - if (data[7] != sd->quality) - set_dqt(gspca_dev, data[7]); - gspca_frame_add(gspca_dev, FIRST_PACKET, - sd->jpeg_hdr, JPEG_HDR_SZ); - gspca_frame_add(gspca_dev, INTER_PACKET, - data + 8, len - 8); - break; - case 0xaa: - gspca_dev->last_packet_type = DISCARD_PACKET; - break; - case 0xcc: - if (data[1] != 0xff || data[2] != 0xd8) - gspca_frame_add(gspca_dev, INTER_PACKET, - data + 1, len - 1); - else - gspca_dev->last_packet_type = DISCARD_PACKET; - break; - } -} - -static void sd_dq_callback(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret, alen; - int luma, expo; - - if (sd->ag_cnt < 0) - return; - if (--sd->ag_cnt > 5) - return; - switch (sd->ag_cnt) { -/* case 5: */ - default: - reg_w(gspca_dev, 0x7d, 0x00); - break; - case 4: - reg_w(gspca_dev, 0x27, 0xb0); - break; - case 3: - reg_w(gspca_dev, 0x0c, 0x01); - break; - case 2: - ret = usb_bulk_msg(gspca_dev->dev, - usb_rcvbulkpipe(gspca_dev->dev, 0x02), - gspca_dev->usb_buf, - 32, - &alen, - 500); - if (ret < 0) { - pr_err("bulk err %d\n", ret); - break; - } - /* values not used (unknown) */ - break; - case 1: - reg_w(gspca_dev, 0x27, 0xd0); - break; - case 0: - ret = usb_bulk_msg(gspca_dev->dev, - usb_rcvbulkpipe(gspca_dev->dev, 0x02), - gspca_dev->usb_buf, - 32, - &alen, - 500); - if (ret < 0) { - pr_err("bulk err %d\n", ret); - break; - } - luma = ((gspca_dev->usb_buf[8] << 8) + gspca_dev->usb_buf[7] + - (gspca_dev->usb_buf[11] << 8) + gspca_dev->usb_buf[10] + - (gspca_dev->usb_buf[14] << 8) + gspca_dev->usb_buf[13] + - (gspca_dev->usb_buf[17] << 8) + gspca_dev->usb_buf[16] + - (gspca_dev->usb_buf[20] << 8) + gspca_dev->usb_buf[19] + - (gspca_dev->usb_buf[23] << 8) + gspca_dev->usb_buf[22] + - (gspca_dev->usb_buf[26] << 8) + gspca_dev->usb_buf[25] + - (gspca_dev->usb_buf[29] << 8) + gspca_dev->usb_buf[28]) - / 8; - if (gspca_dev->width == 640) - luma /= 4; - reg_w(gspca_dev, 0x7d, 0x00); - - expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure); - ret = gspca_expo_autogain(gspca_dev, luma, - 60, /* desired luma */ - 6, /* dead zone */ - 2, /* gain knee */ - 70); /* expo knee */ - sd->ag_cnt = AG_CNT_START; - if (sd->bridge == BRIDGE_TP6810) { - int new_expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure); - - if ((expo >= 128 && new_expo < 128) - || (expo < 128 && new_expo >= 128)) - setframerate(gspca_dev, new_expo); - } - break; - } -} - -/* get stream parameters (framerate) */ -static void sd_get_streamparm(struct gspca_dev *gspca_dev, - struct v4l2_streamparm *parm) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct v4l2_captureparm *cp = &parm->parm.capture; - struct v4l2_fract *tpf = &cp->timeperframe; - int fr, i; - - cp->capability |= V4L2_CAP_TIMEPERFRAME; - tpf->numerator = 1; - i = get_fr_idx(gspca_dev); - if (i & 0x80) { - if (sd->bridge == BRIDGE_TP6800) - fr = rates[6 - (i & 0x07)]; - else - fr = rates_6810[7 - (i & 0x07)]; - } else { - fr = rates[6 - i]; - } - tpf->denominator = fr; -} - -/* set stream parameters (framerate) */ -static void sd_set_streamparm(struct gspca_dev *gspca_dev, - struct v4l2_streamparm *parm) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct v4l2_captureparm *cp = &parm->parm.capture; - struct v4l2_fract *tpf = &cp->timeperframe; - int fr, i; - - sd->framerate = tpf->denominator / tpf->numerator; - if (gspca_dev->streaming) - setframerate(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure)); - - /* Return the actual framerate */ - i = get_fr_idx(gspca_dev); - if (i & 0x80) - fr = rates_6810[7 - (i & 0x07)]; - else - fr = rates[6 - i]; - tpf->numerator = 1; - tpf->denominator = fr; -} - -static int sd_set_jcomp(struct gspca_dev *gspca_dev, - struct v4l2_jpegcompression *jcomp) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor != SENSOR_SOI763A) - return -ENOTTY; - v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality); - return 0; -} - -static int sd_get_jcomp(struct gspca_dev *gspca_dev, - struct v4l2_jpegcompression *jcomp) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->sensor != SENSOR_SOI763A) - return -ENOTTY; - memset(jcomp, 0, sizeof *jcomp); - jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual); - jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT - | V4L2_JPEG_MARKER_DQT; - return 0; -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_SHARPNESS: - setsharpness(gspca_dev, ctrl->val); - break; - case V4L2_CID_GAMMA: - setgamma(gspca_dev, ctrl->val); - break; - case V4L2_CID_BLUE_BALANCE: - setbgain(gspca_dev, ctrl->val); - break; - case V4L2_CID_RED_BALANCE: - setrgain(gspca_dev, ctrl->val); - break; - case V4L2_CID_EXPOSURE: - sd_setgain(gspca_dev); - break; - case V4L2_CID_AUTOGAIN: - if (ctrl->val) - break; - sd_setgain(gspca_dev); - break; - case V4L2_CID_JPEG_COMPRESSION_QUALITY: - jpeg_set_qual(sd->jpeg_hdr, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 4); - gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, 1, 0xdc, 1, 0x4e); - if (sd->sensor == SENSOR_CX0342) { - sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_RED_BALANCE, 0, 4095, 1, 256); - sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BLUE_BALANCE, 0, 4095, 1, 256); - } - if (sd->sensor == SENSOR_SOI763A) - gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 15, 1, 3); - else - gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 4095, 1, 256); - sd->sharpness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SHARPNESS, 0, 3, 1, 2); - sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAMMA, 0, NGAMMA - 1, 1, - (sd->sensor == SENSOR_SOI763A && - sd->bridge == BRIDGE_TP6800) ? 0 : 1); - if (sd->bridge == BRIDGE_TP6810) - gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - if (sd->sensor == SENSOR_SOI763A) - sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_JPEG_COMPRESSION_QUALITY, - 0, 15, 1, (sd->bridge == BRIDGE_TP6810) ? 0 : 13); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - if (gspca_dev->autogain) - v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false); - else - v4l2_ctrl_cluster(2, &gspca_dev->exposure); - return 0; -} - -static const struct sd_desc sd_desc = { - .name = KBUILD_MODNAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .isoc_init = sd_isoc_init, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, - .dq_callback = sd_dq_callback, - .get_streamparm = sd_get_streamparm, - .set_streamparm = sd_set_streamparm, - .get_jcomp = sd_get_jcomp, - .set_jcomp = sd_set_jcomp, -}; - -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x06a2, 0x0003), .driver_info = BRIDGE_TP6800}, - {USB_DEVICE(0x06a2, 0x6810), .driver_info = BRIDGE_TP6810}, - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -static int sd_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - return gspca_dev_probe(interface, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = KBUILD_MODNAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); - -module_param(force_sensor, int, 0644); -MODULE_PARM_DESC(force_sensor, - "Force sensor. 0: cx0342, 1: soi763a"); diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c deleted file mode 100644 index 8591324a53e1..000000000000 --- a/drivers/media/video/gspca/tv8532.c +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Quickcam cameras initialization data - * - * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#define MODULE_NAME "tv8532" - -#include "gspca.h" - -MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); -MODULE_DESCRIPTION("TV8532 USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - __u8 packet; -}; - -static const struct v4l2_pix_format sif_mode[] = { - {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; - -/* TV-8532A (ICM532A) registers (LE) */ -#define R00_PART_CONTROL 0x00 -#define LATENT_CHANGE 0x80 -#define EXPO_CHANGE 0x04 -#define R01_TIMING_CONTROL_LOW 0x01 -#define CMD_EEprom_Open 0x30 -#define CMD_EEprom_Close 0x29 -#define R03_TABLE_ADDR 0x03 -#define R04_WTRAM_DATA_L 0x04 -#define R05_WTRAM_DATA_M 0x05 -#define R06_WTRAM_DATA_H 0x06 -#define R07_TABLE_LEN 0x07 -#define R08_RAM_WRITE_ACTION 0x08 -#define R0C_AD_WIDTHL 0x0c -#define R0D_AD_WIDTHH 0x0d -#define R0E_AD_HEIGHTL 0x0e -#define R0F_AD_HEIGHTH 0x0f -#define R10_AD_COL_BEGINL 0x10 -#define R11_AD_COL_BEGINH 0x11 -#define MIRROR 0x04 /* [10] */ -#define R14_AD_ROW_BEGINL 0x14 -#define R15_AD_ROWBEGINH 0x15 -#define R1C_AD_EXPOSE_TIMEL 0x1c -#define R20_GAIN_G1L 0x20 -#define R21_GAIN_G1H 0x21 -#define R22_GAIN_RL 0x22 -#define R23_GAIN_RH 0x23 -#define R24_GAIN_BL 0x24 -#define R25_GAIN_BH 0x25 -#define R26_GAIN_G2L 0x26 -#define R27_GAIN_G2H 0x27 -#define R28_QUANT 0x28 -#define R29_LINE 0x29 -#define R2C_POLARITY 0x2c -#define R2D_POINT 0x2d -#define R2E_POINTH 0x2e -#define R2F_POINTB 0x2f -#define R30_POINTBH 0x30 -#define R31_UPD 0x31 -#define R2A_HIGH_BUDGET 0x2a -#define R2B_LOW_BUDGET 0x2b -#define R34_VID 0x34 -#define R35_VIDH 0x35 -#define R36_PID 0x36 -#define R37_PIDH 0x37 -#define R39_Test1 0x39 /* GPIO */ -#define R3B_Test3 0x3b /* GPIO */ -#define R83_AD_IDH 0x83 -#define R91_AD_SLOPEREG 0x91 -#define R94_AD_BITCONTROL 0x94 - -static const u8 eeprom_data[][3] = { -/* dataH dataM dataL */ - {0x01, 0x00, 0x01}, - {0x01, 0x80, 0x11}, - {0x05, 0x00, 0x14}, - {0x05, 0x00, 0x1c}, - {0x0d, 0x00, 0x1e}, - {0x05, 0x00, 0x1f}, - {0x05, 0x05, 0x19}, - {0x05, 0x01, 0x1b}, - {0x05, 0x09, 0x1e}, - {0x0d, 0x89, 0x2e}, - {0x05, 0x89, 0x2f}, - {0x05, 0x0d, 0xd9}, - {0x05, 0x09, 0xf1}, -}; - - -/* write 1 byte */ -static void reg_w1(struct gspca_dev *gspca_dev, - __u16 index, __u8 value) -{ - gspca_dev->usb_buf[0] = value; - usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x02, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, /* value */ - index, gspca_dev->usb_buf, 1, 500); -} - -/* write 2 bytes */ -static void reg_w2(struct gspca_dev *gspca_dev, - u16 index, u16 value) -{ - gspca_dev->usb_buf[0] = value; - gspca_dev->usb_buf[1] = value >> 8; - usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x02, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, /* value */ - index, gspca_dev->usb_buf, 2, 500); -} - -static void tv_8532WriteEEprom(struct gspca_dev *gspca_dev) -{ - int i; - - reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Open); - for (i = 0; i < ARRAY_SIZE(eeprom_data); i++) { - reg_w1(gspca_dev, R03_TABLE_ADDR, i); - reg_w1(gspca_dev, R04_WTRAM_DATA_L, eeprom_data[i][2]); - reg_w1(gspca_dev, R05_WTRAM_DATA_M, eeprom_data[i][1]); - reg_w1(gspca_dev, R06_WTRAM_DATA_H, eeprom_data[i][0]); - reg_w1(gspca_dev, R08_RAM_WRITE_ACTION, 0); - } - reg_w1(gspca_dev, R07_TABLE_LEN, i); - reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Close); -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct cam *cam; - - cam = &gspca_dev->cam; - cam->cam_mode = sif_mode; - cam->nmodes = ARRAY_SIZE(sif_mode); - - return 0; -} - -static void tv_8532_setReg(struct gspca_dev *gspca_dev) -{ - reg_w1(gspca_dev, R3B_Test3, 0x0a); /* Test0Sel = 10 */ - /******************************************************/ - reg_w1(gspca_dev, R0E_AD_HEIGHTL, 0x90); - reg_w1(gspca_dev, R0F_AD_HEIGHTH, 0x01); - reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, 0x018f); - reg_w1(gspca_dev, R10_AD_COL_BEGINL, 0x44); - /* begin active line */ - reg_w1(gspca_dev, R11_AD_COL_BEGINH, 0x00); - /* mirror and digital gain */ - reg_w1(gspca_dev, R14_AD_ROW_BEGINL, 0x0a); - - reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x02); - reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x00); - reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); - /* = 0x84 */ -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - tv_8532WriteEEprom(gspca_dev); - - return 0; -} - -static void setexposure(struct gspca_dev *gspca_dev, s32 val) -{ - reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, val); - reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE); - /* 0x84 */ -} - -static void setgain(struct gspca_dev *gspca_dev, s32 val) -{ - reg_w2(gspca_dev, R20_GAIN_G1L, val); - reg_w2(gspca_dev, R22_GAIN_RL, val); - reg_w2(gspca_dev, R24_GAIN_BL, val); - reg_w2(gspca_dev, R26_GAIN_G2L, val); -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - reg_w1(gspca_dev, R0C_AD_WIDTHL, 0xe8); /* 0x20; 0x0c */ - reg_w1(gspca_dev, R0D_AD_WIDTHH, 0x03); - - /************************************************/ - reg_w1(gspca_dev, R28_QUANT, 0x90); - /* 0x72 compressed mode 0x28 */ - if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { - /* 176x144 */ - reg_w1(gspca_dev, R29_LINE, 0x41); - /* CIF - 2 lines/packet */ - } else { - /* 352x288 */ - reg_w1(gspca_dev, R29_LINE, 0x81); - /* CIF - 2 lines/packet */ - } - /************************************************/ - reg_w1(gspca_dev, R2C_POLARITY, 0x10); /* slow clock */ - reg_w1(gspca_dev, R2D_POINT, 0x14); - reg_w1(gspca_dev, R2E_POINTH, 0x01); - reg_w1(gspca_dev, R2F_POINTB, 0x12); - reg_w1(gspca_dev, R30_POINTBH, 0x01); - - tv_8532_setReg(gspca_dev); - - /************************************************/ - reg_w1(gspca_dev, R31_UPD, 0x01); /* update registers */ - msleep(200); - reg_w1(gspca_dev, R31_UPD, 0x00); /* end update */ - - gspca_dev->empty_packet = 0; /* check the empty packets */ - sd->packet = 0; /* ignore the first packets */ - - return 0; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - reg_w1(gspca_dev, R3B_Test3, 0x0b); /* Test0Sel = 11 = GPIO */ -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - int packet_type0, packet_type1; - - packet_type0 = packet_type1 = INTER_PACKET; - if (gspca_dev->empty_packet) { - gspca_dev->empty_packet = 0; - sd->packet = gspca_dev->height / 2; - packet_type0 = FIRST_PACKET; - } else if (sd->packet == 0) - return; /* 2 more lines in 352x288 ! */ - sd->packet--; - if (sd->packet == 0) - packet_type1 = LAST_PACKET; - - /* each packet contains: - * - header 2 bytes - * - RGRG line - * - 4 bytes - * - GBGB line - * - 4 bytes - */ - gspca_frame_add(gspca_dev, packet_type0, - data + 2, gspca_dev->width); - gspca_frame_add(gspca_dev, packet_type1, - data + gspca_dev->width + 5, gspca_dev->width); -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - setexposure(gspca_dev, ctrl->val); - break; - case V4L2_CID_GAIN: - setgain(gspca_dev, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 2); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 0x18f, 1, 0x18f); - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 0x7ff, 1, 0x100); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x046d, 0x0920)}, - {USB_DEVICE(0x046d, 0x0921)}, - {USB_DEVICE(0x0545, 0x808b)}, - {USB_DEVICE(0x0545, 0x8333)}, - {USB_DEVICE(0x0923, 0x010f)}, - {} -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c deleted file mode 100644 index e50079503d96..000000000000 --- a/drivers/media/video/gspca/vc032x.c +++ /dev/null @@ -1,3850 +0,0 @@ -/* - * Z-star vc0321 library - * - * Copyright (C) 2009-2010 Jean-François Moine <http://moinejf.free.fr> - * Copyright (C) 2006 Koninski Artur takeshi87@o2.pl - * Copyright (C) 2006 Michel Xhaard - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "vc032x" - -#include "gspca.h" - -MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); -MODULE_DESCRIPTION("GSPCA/VC032X USB Camera Driver"); -MODULE_LICENSE("GPL"); - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - struct { /* hvflip cluster */ - struct v4l2_ctrl *hflip; - struct v4l2_ctrl *vflip; - }; - - u8 image_offset; - - u8 bridge; - u8 sensor; - u8 flags; -#define FL_SAMSUNG 0x01 /* SamsungQ1 (2 sensors) */ -#define FL_HFLIP 0x02 /* mirrored by default */ -#define FL_VFLIP 0x04 /* vertical flipped by default */ -}; -enum bridges { - BRIDGE_VC0321, - BRIDGE_VC0323, -}; -enum sensors { - SENSOR_HV7131R, - SENSOR_MI0360, - SENSOR_MI1310_SOC, - SENSOR_MI1320, - SENSOR_MI1320_SOC, - SENSOR_OV7660, - SENSOR_OV7670, - SENSOR_PO1200, - SENSOR_PO3130NC, - SENSOR_POxxxx, - NSENSORS -}; - - -static const struct v4l2_pix_format vc0321_mode[] = { - {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; -static const struct v4l2_pix_format vc0323_mode[] = { - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, - {1280, 960, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, /* mi1310_soc only */ - .bytesperline = 1280, - .sizeimage = 1280 * 960 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 2}, -}; -static const struct v4l2_pix_format bi_mode[] = { - {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 2}, - {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 1}, - {1280, 1024, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, - .bytesperline = 1280, - .sizeimage = 1280 * 1024 * 2, - .colorspace = V4L2_COLORSPACE_SRGB, - .priv = 0}, -}; -static const struct v4l2_pix_format svga_mode[] = { - {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 800, - .sizeimage = 800 * 600 * 1 / 4 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; - -/* OV7660/7670 registers */ -#define OV7660_REG_MVFP 0x1e -#define OV7660_MVFP_MIRROR 0x20 -#define OV7660_MVFP_VFLIP 0x10 - -static const u8 mi0360_matrix[9] = { - 0x50, 0xf8, 0xf8, 0xf5, 0x50, 0xfb, 0xff, 0xf1, 0x50 -}; - -static const u8 mi0360_initVGA_JPG[][4] = { - {0xb0, 0x03, 0x19, 0xcc}, - {0xb0, 0x04, 0x02, 0xcc}, - {0xb3, 0x00, 0x24, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x03, 0xcc}, - {0xb3, 0x03, 0x0a, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, - {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x35, 0xdd, 0xcc}, /* i2c add: 5d */ - {0xb3, 0x34, 0x02, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, - {0xbc, 0x00, 0x71, 0xcc}, - {0xb8, 0x00, 0x13, 0xcc}, - {0xb8, 0x27, 0x20, 0xcc}, - {0xb8, 0x2c, 0x50, 0xcc}, - {0xb8, 0x2d, 0xf8, 0xcc}, - {0xb8, 0x2e, 0xf8, 0xcc}, - {0xb8, 0x2f, 0xf8, 0xcc}, - {0xb8, 0x30, 0x50, 0xcc}, - {0xb8, 0x31, 0xf8, 0xcc}, - {0xb8, 0x32, 0xf8, 0xcc}, - {0xb8, 0x33, 0xf8, 0xcc}, - {0xb8, 0x34, 0x50, 0xcc}, - {0xb8, 0x35, 0x00, 0xcc}, - {0xb8, 0x36, 0x00, 0xcc}, - {0xb8, 0x37, 0x00, 0xcc}, - {0xb8, 0x01, 0x79, 0xcc}, - {0xb8, 0x08, 0xe0, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, - {0xb8, 0x01, 0x79, 0xcc}, - {0xb8, 0x14, 0x18, 0xcc}, - {0xb8, 0xb2, 0x0a, 0xcc}, - {0xb8, 0xb4, 0x0a, 0xcc}, - {0xb8, 0xb5, 0x0a, 0xcc}, - {0xb8, 0xfe, 0x00, 0xcc}, - {0xb8, 0xff, 0x28, 0xcc}, - {0xb9, 0x00, 0x28, 0xcc}, - {0xb9, 0x01, 0x28, 0xcc}, - {0xb9, 0x02, 0x28, 0xcc}, - {0xb9, 0x03, 0x00, 0xcc}, - {0xb9, 0x04, 0x00, 0xcc}, - {0xb9, 0x05, 0x3c, 0xcc}, - {0xb9, 0x06, 0x3c, 0xcc}, - {0xb9, 0x07, 0x3c, 0xcc}, - {0xb9, 0x08, 0x3c, 0xcc}, - {0xb8, 0x8e, 0x00, 0xcc}, - {0xb8, 0x8f, 0xff, 0xcc}, - {0xb8, 0x81, 0x09, 0xcc}, - {0x31, 0x00, 0x00, 0xbb}, - {0x09, 0x01, 0xc7, 0xbb}, - {0x34, 0x01, 0x00, 0xbb}, - {0x2b, 0x00, 0x28, 0xbb}, - {0x2c, 0x00, 0x30, 0xbb}, - {0x2d, 0x00, 0x30, 0xbb}, - {0x2e, 0x00, 0x28, 0xbb}, - {0x62, 0x04, 0x11, 0xbb}, - {0x03, 0x01, 0xe0, 0xbb}, - {0x2c, 0x00, 0x2c, 0xbb}, - {0x20, 0xd0, 0x00, 0xbb}, - {0x01, 0x00, 0x08, 0xbb}, - {0x06, 0x00, 0x10, 0xbb}, - {0x05, 0x00, 0x20, 0xbb}, - {0x20, 0x00, 0x00, 0xbb}, - {0xb6, 0x00, 0x00, 0xcc}, - {0xb6, 0x03, 0x02, 0xcc}, - {0xb6, 0x02, 0x80, 0xcc}, - {0xb6, 0x05, 0x01, 0xcc}, - {0xb6, 0x04, 0xe0, 0xcc}, - {0xb6, 0x12, 0x78, 0xcc}, - {0xb6, 0x18, 0x02, 0xcc}, - {0xb6, 0x17, 0x58, 0xcc}, - {0xb6, 0x16, 0x00, 0xcc}, - {0xb6, 0x22, 0x12, 0xcc}, - {0xb6, 0x23, 0x0b, 0xcc}, - {0xb3, 0x02, 0x02, 0xcc}, - {0xbf, 0xc0, 0x39, 0xcc}, - {0xbf, 0xc1, 0x04, 0xcc}, - {0xbf, 0xcc, 0x10, 0xcc}, - {0xb9, 0x12, 0x00, 0xcc}, - {0xb9, 0x13, 0x0a, 0xcc}, - {0xb9, 0x14, 0x0a, 0xcc}, - {0xb9, 0x15, 0x0a, 0xcc}, - {0xb9, 0x16, 0x0a, 0xcc}, - {0xb9, 0x18, 0x00, 0xcc}, - {0xb9, 0x19, 0x0f, 0xcc}, - {0xb9, 0x1a, 0x0f, 0xcc}, - {0xb9, 0x1b, 0x0f, 0xcc}, - {0xb9, 0x1c, 0x0f, 0xcc}, - {0xb8, 0x8e, 0x00, 0xcc}, - {0xb8, 0x8f, 0xff, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, - {0xb8, 0x0c, 0x20, 0xcc}, - {0xb8, 0x0d, 0x70, 0xcc}, - {0xb6, 0x13, 0x13, 0xcc}, - {0x35, 0x00, 0x60, 0xbb}, - {0xb3, 0x5c, 0x01, 0xcc}, - {} -}; -static const u8 mi0360_initQVGA_JPG[][4] = { - {0xb0, 0x03, 0x19, 0xcc}, - {0xb0, 0x04, 0x02, 0xcc}, - {0xb3, 0x00, 0x24, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x03, 0xcc}, - {0xb3, 0x03, 0x0a, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, - {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x35, 0xdd, 0xcc}, - {0xb3, 0x34, 0x02, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, - {0xbc, 0x00, 0xd1, 0xcc}, - {0xb8, 0x00, 0x13, 0xcc}, - {0xb8, 0x27, 0x20, 0xcc}, - {0xb8, 0x2c, 0x50, 0xcc}, - {0xb8, 0x2d, 0xf8, 0xcc}, - {0xb8, 0x2e, 0xf8, 0xcc}, - {0xb8, 0x2f, 0xf8, 0xcc}, - {0xb8, 0x30, 0x50, 0xcc}, - {0xb8, 0x31, 0xf8, 0xcc}, - {0xb8, 0x32, 0xf8, 0xcc}, - {0xb8, 0x33, 0xf8, 0xcc}, - {0xb8, 0x34, 0x50, 0xcc}, - {0xb8, 0x35, 0x00, 0xcc}, - {0xb8, 0x36, 0x00, 0xcc}, - {0xb8, 0x37, 0x00, 0xcc}, - {0xb8, 0x01, 0x79, 0xcc}, - {0xb8, 0x08, 0xe0, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, - {0xb8, 0x01, 0x79, 0xcc}, - {0xb8, 0x14, 0x18, 0xcc}, - {0xb8, 0xb2, 0x0a, 0xcc}, - {0xb8, 0xb4, 0x0a, 0xcc}, - {0xb8, 0xb5, 0x0a, 0xcc}, - {0xb8, 0xfe, 0x00, 0xcc}, - {0xb8, 0xff, 0x28, 0xcc}, - {0xb9, 0x00, 0x28, 0xcc}, - {0xb9, 0x01, 0x28, 0xcc}, - {0xb9, 0x02, 0x28, 0xcc}, - {0xb9, 0x03, 0x00, 0xcc}, - {0xb9, 0x04, 0x00, 0xcc}, - {0xb9, 0x05, 0x3c, 0xcc}, - {0xb9, 0x06, 0x3c, 0xcc}, - {0xb9, 0x07, 0x3c, 0xcc}, - {0xb9, 0x08, 0x3c, 0xcc}, - {0xb8, 0x8e, 0x00, 0xcc}, - {0xb8, 0x8f, 0xff, 0xcc}, - {0xb8, 0x81, 0x09, 0xcc}, - {0x31, 0x00, 0x00, 0xbb}, - {0x09, 0x01, 0xc7, 0xbb}, - {0x34, 0x01, 0x00, 0xbb}, - {0x2b, 0x00, 0x28, 0xbb}, - {0x2c, 0x00, 0x30, 0xbb}, - {0x2d, 0x00, 0x30, 0xbb}, - {0x2e, 0x00, 0x28, 0xbb}, - {0x62, 0x04, 0x11, 0xbb}, - {0x03, 0x01, 0xe0, 0xbb}, - {0x2c, 0x00, 0x2c, 0xbb}, - {0x20, 0xd0, 0x00, 0xbb}, - {0x01, 0x00, 0x08, 0xbb}, - {0x06, 0x00, 0x10, 0xbb}, - {0x05, 0x00, 0x20, 0xbb}, - {0x20, 0x00, 0x00, 0xbb}, - {0xb6, 0x00, 0x00, 0xcc}, - {0xb6, 0x03, 0x01, 0xcc}, - {0xb6, 0x02, 0x40, 0xcc}, - {0xb6, 0x05, 0x00, 0xcc}, - {0xb6, 0x04, 0xf0, 0xcc}, - {0xb6, 0x12, 0x78, 0xcc}, - {0xb6, 0x18, 0x00, 0xcc}, - {0xb6, 0x17, 0x96, 0xcc}, - {0xb6, 0x16, 0x00, 0xcc}, - {0xb6, 0x22, 0x12, 0xcc}, - {0xb6, 0x23, 0x0b, 0xcc}, - {0xb3, 0x02, 0x02, 0xcc}, - {0xbf, 0xc0, 0x39, 0xcc}, - {0xbf, 0xc1, 0x04, 0xcc}, - {0xbf, 0xcc, 0x10, 0xcc}, - {0xb9, 0x12, 0x00, 0xcc}, - {0xb9, 0x13, 0x0a, 0xcc}, - {0xb9, 0x14, 0x0a, 0xcc}, - {0xb9, 0x15, 0x0a, 0xcc}, - {0xb9, 0x16, 0x0a, 0xcc}, - {0xb9, 0x18, 0x00, 0xcc}, - {0xb9, 0x19, 0x0f, 0xcc}, - {0xb9, 0x1a, 0x0f, 0xcc}, - {0xb9, 0x1b, 0x0f, 0xcc}, - {0xb9, 0x1c, 0x0f, 0xcc}, - {0xb8, 0x8e, 0x00, 0xcc}, - {0xb8, 0x8f, 0xff, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, - {0xb6, 0x13, 0x13, 0xcc}, - {0xbc, 0x02, 0x18, 0xcc}, - {0xbc, 0x03, 0x50, 0xcc}, - {0xbc, 0x04, 0x18, 0xcc}, - {0xbc, 0x05, 0x00, 0xcc}, - {0xbc, 0x06, 0x00, 0xcc}, - {0xbc, 0x08, 0x30, 0xcc}, - {0xbc, 0x09, 0x40, 0xcc}, - {0xbc, 0x0a, 0x10, 0xcc}, - {0xb8, 0x0c, 0x20, 0xcc}, - {0xb8, 0x0d, 0x70, 0xcc}, - {0xbc, 0x0b, 0x00, 0xcc}, - {0xbc, 0x0c, 0x00, 0xcc}, - {0x35, 0x00, 0xef, 0xbb}, - {0xb3, 0x5c, 0x01, 0xcc}, - {} -}; - -static const u8 mi1310_socinitVGA_JPG[][4] = { - {0xb0, 0x03, 0x19, 0xcc}, - {0xb0, 0x04, 0x02, 0xcc}, - {0xb3, 0x00, 0x64, 0xcc}, - {0xb3, 0x00, 0x65, 0xcc}, - {0xb3, 0x05, 0x00, 0xcc}, - {0xb3, 0x06, 0x00, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x34, 0x02, 0xcc}, - {0xb3, 0x35, 0xdd, 0xcc}, /* i2c add: 5d */ - {0xb3, 0x02, 0x00, 0xcc}, - {0xb3, 0x03, 0x0a, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x03, 0xcc}, - {0xb3, 0x23, 0xc0, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x04, 0xcc}, - {0xb3, 0x17, 0xff, 0xcc}, - {0xb3, 0x00, 0x65, 0xcc}, - {0xb8, 0x00, 0x00, 0xcc}, - {0xbc, 0x00, 0xd0, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, - {0xf0, 0x00, 0x02, 0xbb}, - {0xc8, 0x9f, 0x0b, 0xbb}, - {0x5b, 0x00, 0x01, 0xbb}, - {0x2f, 0xde, 0x20, 0xbb}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x20, 0x03, 0x02, 0xbb}, /* h/v flip */ - {0xf0, 0x00, 0x01, 0xbb}, - {0x05, 0x00, 0x07, 0xbb}, - {0x34, 0x00, 0x00, 0xbb}, - {0x35, 0xff, 0x00, 0xbb}, - {0xdc, 0x07, 0x02, 0xbb}, - {0xdd, 0x3c, 0x18, 0xbb}, - {0xde, 0x92, 0x6d, 0xbb}, - {0xdf, 0xcd, 0xb1, 0xbb}, - {0xe0, 0xff, 0xe7, 0xbb}, - {0x06, 0xf0, 0x0d, 0xbb}, - {0x06, 0x70, 0x0e, 0xbb}, - {0x4c, 0x00, 0x01, 0xbb}, - {0x4d, 0x00, 0x01, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x2e, 0x0c, 0x55, 0xbb}, - {0x21, 0xb6, 0x6e, 0xbb}, - {0x36, 0x30, 0x10, 0xbb}, - {0x37, 0x00, 0xc1, 0xbb}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x07, 0x00, 0x84, 0xbb}, - {0x08, 0x02, 0x4a, 0xbb}, - {0x05, 0x01, 0x10, 0xbb}, - {0x06, 0x00, 0x39, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x58, 0x02, 0x67, 0xbb}, - {0x57, 0x02, 0x00, 0xbb}, - {0x5a, 0x02, 0x67, 0xbb}, - {0x59, 0x02, 0x00, 0xbb}, - {0x5c, 0x12, 0x0d, 0xbb}, - {0x5d, 0x16, 0x11, 0xbb}, - {0x39, 0x06, 0x18, 0xbb}, - {0x3a, 0x06, 0x18, 0xbb}, - {0x3b, 0x06, 0x18, 0xbb}, - {0x3c, 0x06, 0x18, 0xbb}, - {0x64, 0x7b, 0x5b, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x36, 0x30, 0x10, 0xbb}, - {0x37, 0x00, 0xc0, 0xbb}, - {0xbc, 0x0e, 0x00, 0xcc}, - {0xbc, 0x0f, 0x05, 0xcc}, - {0xbc, 0x10, 0xc0, 0xcc}, - {0xbc, 0x11, 0x03, 0xcc}, - {0xb6, 0x00, 0x00, 0xcc}, - {0xb6, 0x03, 0x02, 0xcc}, - {0xb6, 0x02, 0x80, 0xcc}, - {0xb6, 0x05, 0x01, 0xcc}, - {0xb6, 0x04, 0xe0, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, - {0xb6, 0x13, 0x25, 0xcc}, - {0xb6, 0x18, 0x02, 0xcc}, - {0xb6, 0x17, 0x58, 0xcc}, - {0xb6, 0x16, 0x00, 0xcc}, - {0xb6, 0x22, 0x12, 0xcc}, - {0xb6, 0x23, 0x0b, 0xcc}, - {0xbf, 0xc0, 0x39, 0xcc}, - {0xbf, 0xc1, 0x04, 0xcc}, - {0xbf, 0xcc, 0x00, 0xcc}, - {0xbc, 0x02, 0x18, 0xcc}, - {0xbc, 0x03, 0x50, 0xcc}, - {0xbc, 0x04, 0x18, 0xcc}, - {0xbc, 0x05, 0x00, 0xcc}, - {0xbc, 0x06, 0x00, 0xcc}, - {0xbc, 0x08, 0x30, 0xcc}, - {0xbc, 0x09, 0x40, 0xcc}, - {0xbc, 0x0a, 0x10, 0xcc}, - {0xbc, 0x0b, 0x00, 0xcc}, - {0xbc, 0x0c, 0x00, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, - {0xf0, 0x00, 0x01, 0xbb}, - {0x80, 0x00, 0x03, 0xbb}, - {0x81, 0xc7, 0x14, 0xbb}, - {0x82, 0xeb, 0xe8, 0xbb}, - {0x83, 0xfe, 0xf4, 0xbb}, - {0x84, 0xcd, 0x10, 0xbb}, - {0x85, 0xf3, 0xee, 0xbb}, - {0x86, 0xff, 0xf1, 0xbb}, - {0x87, 0xcd, 0x10, 0xbb}, - {0x88, 0xf3, 0xee, 0xbb}, - {0x89, 0x01, 0xf1, 0xbb}, - {0x8a, 0xe5, 0x17, 0xbb}, - {0x8b, 0xe8, 0xe2, 0xbb}, - {0x8c, 0xf7, 0xed, 0xbb}, - {0x8d, 0x00, 0xff, 0xbb}, - {0x8e, 0xec, 0x10, 0xbb}, - {0x8f, 0xf0, 0xed, 0xbb}, - {0x90, 0xf9, 0xf2, 0xbb}, - {0x91, 0x00, 0x00, 0xbb}, - {0x92, 0xe9, 0x0d, 0xbb}, - {0x93, 0xf4, 0xf2, 0xbb}, - {0x94, 0xfb, 0xf5, 0xbb}, - {0x95, 0x00, 0xff, 0xbb}, - {0xb6, 0x0f, 0x08, 0xbb}, - {0xb7, 0x3d, 0x16, 0xbb}, - {0xb8, 0x0c, 0x04, 0xbb}, - {0xb9, 0x1c, 0x07, 0xbb}, - {0xba, 0x0a, 0x03, 0xbb}, - {0xbb, 0x1b, 0x09, 0xbb}, - {0xbc, 0x17, 0x0d, 0xbb}, - {0xbd, 0x23, 0x1d, 0xbb}, - {0xbe, 0x00, 0x28, 0xbb}, - {0xbf, 0x11, 0x09, 0xbb}, - {0xc0, 0x16, 0x15, 0xbb}, - {0xc1, 0x00, 0x1b, 0xbb}, - {0xc2, 0x0e, 0x07, 0xbb}, - {0xc3, 0x14, 0x10, 0xbb}, - {0xc4, 0x00, 0x17, 0xbb}, - {0x06, 0x74, 0x8e, 0xbb}, - {0xf0, 0x00, 0x01, 0xbb}, - {0x06, 0xf4, 0x8e, 0xbb}, - {0x00, 0x00, 0x50, 0xdd}, - {0x06, 0x74, 0x8e, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x24, 0x50, 0x20, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x34, 0x0c, 0x50, 0xbb}, - {0xb3, 0x01, 0x41, 0xcc}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x03, 0x03, 0xc0, 0xbb}, - {}, -}; -static const u8 mi1310_socinitQVGA_JPG[][4] = { - {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, - {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc}, - {0xb3, 0x05, 0x00, 0xcc}, {0xb3, 0x06, 0x00, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x34, 0x02, 0xcc}, {0xb3, 0x35, 0xdd, 0xcc}, - {0xb3, 0x02, 0x00, 0xcc}, {0xb3, 0x03, 0x0a, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x03, 0xcc}, - {0xb3, 0x23, 0xc0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, {0xb3, 0x16, 0x04, 0xcc}, - {0xb3, 0x17, 0xff, 0xcc}, {0xb3, 0x00, 0x65, 0xcc}, - {0xb8, 0x00, 0x00, 0xcc}, {0xbc, 0x00, 0xf0, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, {0xf0, 0x00, 0x02, 0xbb}, - {0xc8, 0x9f, 0x0b, 0xbb}, {0x5b, 0x00, 0x01, 0xbb}, - {0x2f, 0xde, 0x20, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, - {0x20, 0x03, 0x02, 0xbb}, /* h/v flip */ - {0xf0, 0x00, 0x01, 0xbb}, - {0x05, 0x00, 0x07, 0xbb}, {0x34, 0x00, 0x00, 0xbb}, - {0x35, 0xff, 0x00, 0xbb}, {0xdc, 0x07, 0x02, 0xbb}, - {0xdd, 0x3c, 0x18, 0xbb}, {0xde, 0x92, 0x6d, 0xbb}, - {0xdf, 0xcd, 0xb1, 0xbb}, {0xe0, 0xff, 0xe7, 0xbb}, - {0x06, 0xf0, 0x0d, 0xbb}, {0x06, 0x70, 0x0e, 0xbb}, - {0x4c, 0x00, 0x01, 0xbb}, {0x4d, 0x00, 0x01, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x2e, 0x0c, 0x55, 0xbb}, - {0x21, 0xb6, 0x6e, 0xbb}, {0x36, 0x30, 0x10, 0xbb}, - {0x37, 0x00, 0xc1, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, - {0x07, 0x00, 0x84, 0xbb}, {0x08, 0x02, 0x4a, 0xbb}, - {0x05, 0x01, 0x10, 0xbb}, {0x06, 0x00, 0x39, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x58, 0x02, 0x67, 0xbb}, - {0x57, 0x02, 0x00, 0xbb}, {0x5a, 0x02, 0x67, 0xbb}, - {0x59, 0x02, 0x00, 0xbb}, {0x5c, 0x12, 0x0d, 0xbb}, - {0x5d, 0x16, 0x11, 0xbb}, {0x39, 0x06, 0x18, 0xbb}, - {0x3a, 0x06, 0x18, 0xbb}, {0x3b, 0x06, 0x18, 0xbb}, - {0x3c, 0x06, 0x18, 0xbb}, {0x64, 0x7b, 0x5b, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x36, 0x30, 0x10, 0xbb}, - {0x37, 0x00, 0xc0, 0xbb}, {0xbc, 0x0e, 0x00, 0xcc}, - {0xbc, 0x0f, 0x05, 0xcc}, {0xbc, 0x10, 0xc0, 0xcc}, - {0xbc, 0x11, 0x03, 0xcc}, {0xb6, 0x00, 0x00, 0xcc}, - {0xb6, 0x03, 0x01, 0xcc}, {0xb6, 0x02, 0x40, 0xcc}, - {0xb6, 0x05, 0x00, 0xcc}, {0xb6, 0x04, 0xf0, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x25, 0xcc}, - {0xb6, 0x18, 0x00, 0xcc}, {0xb6, 0x17, 0x96, 0xcc}, - {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc}, - {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc}, - {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, {0xf0, 0x00, 0x01, 0xbb}, - {0x80, 0x00, 0x03, 0xbb}, {0x81, 0xc7, 0x14, 0xbb}, - {0x82, 0xeb, 0xe8, 0xbb}, {0x83, 0xfe, 0xf4, 0xbb}, - {0x84, 0xcd, 0x10, 0xbb}, {0x85, 0xf3, 0xee, 0xbb}, - {0x86, 0xff, 0xf1, 0xbb}, {0x87, 0xcd, 0x10, 0xbb}, - {0x88, 0xf3, 0xee, 0xbb}, {0x89, 0x01, 0xf1, 0xbb}, - {0x8a, 0xe5, 0x17, 0xbb}, {0x8b, 0xe8, 0xe2, 0xbb}, - {0x8c, 0xf7, 0xed, 0xbb}, {0x8d, 0x00, 0xff, 0xbb}, - {0x8e, 0xec, 0x10, 0xbb}, {0x8f, 0xf0, 0xed, 0xbb}, - {0x90, 0xf9, 0xf2, 0xbb}, {0x91, 0x00, 0x00, 0xbb}, - {0x92, 0xe9, 0x0d, 0xbb}, {0x93, 0xf4, 0xf2, 0xbb}, - {0x94, 0xfb, 0xf5, 0xbb}, {0x95, 0x00, 0xff, 0xbb}, - {0xb6, 0x0f, 0x08, 0xbb}, {0xb7, 0x3d, 0x16, 0xbb}, - {0xb8, 0x0c, 0x04, 0xbb}, {0xb9, 0x1c, 0x07, 0xbb}, - {0xba, 0x0a, 0x03, 0xbb}, {0xbb, 0x1b, 0x09, 0xbb}, - {0xbc, 0x17, 0x0d, 0xbb}, {0xbd, 0x23, 0x1d, 0xbb}, - {0xbe, 0x00, 0x28, 0xbb}, {0xbf, 0x11, 0x09, 0xbb}, - {0xc0, 0x16, 0x15, 0xbb}, {0xc1, 0x00, 0x1b, 0xbb}, - {0xc2, 0x0e, 0x07, 0xbb}, {0xc3, 0x14, 0x10, 0xbb}, - {0xc4, 0x00, 0x17, 0xbb}, {0x06, 0x74, 0x8e, 0xbb}, - {0xf0, 0x00, 0x01, 0xbb}, {0x06, 0xf4, 0x8e, 0xbb}, - {0x00, 0x00, 0x50, 0xdd}, {0x06, 0x74, 0x8e, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x24, 0x50, 0x20, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x34, 0x0c, 0x50, 0xbb}, - {0xb3, 0x01, 0x41, 0xcc}, {0xf0, 0x00, 0x00, 0xbb}, - {0x03, 0x03, 0xc0, 0xbb}, - {}, -}; -static const u8 mi1310_soc_InitSXGA_JPG[][4] = { - {0xb0, 0x03, 0x19, 0xcc}, - {0xb0, 0x04, 0x02, 0xcc}, - {0xb3, 0x00, 0x64, 0xcc}, - {0xb3, 0x00, 0x65, 0xcc}, - {0xb3, 0x05, 0x00, 0xcc}, - {0xb3, 0x06, 0x00, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x34, 0x02, 0xcc}, - {0xb3, 0x35, 0xdd, 0xcc}, - {0xb3, 0x02, 0x00, 0xcc}, - {0xb3, 0x03, 0x0a, 0xcc}, - {0xb3, 0x04, 0x0d, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x03, 0xcc}, - {0xb3, 0x23, 0xc0, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x04, 0xcc}, - {0xb3, 0x17, 0xff, 0xcc}, - {0xb3, 0x00, 0x65, 0xcc}, - {0xb8, 0x00, 0x00, 0xcc}, - {0xbc, 0x00, 0x70, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, - {0xf0, 0x00, 0x02, 0xbb}, - {0xc8, 0x9f, 0x0b, 0xbb}, - {0x5b, 0x00, 0x01, 0xbb}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x20, 0x03, 0x02, 0xbb}, /* h/v flip */ - {0xf0, 0x00, 0x01, 0xbb}, - {0x05, 0x00, 0x07, 0xbb}, - {0x34, 0x00, 0x00, 0xbb}, - {0x35, 0xff, 0x00, 0xbb}, - {0xdc, 0x07, 0x02, 0xbb}, - {0xdd, 0x3c, 0x18, 0xbb}, - {0xde, 0x92, 0x6d, 0xbb}, - {0xdf, 0xcd, 0xb1, 0xbb}, - {0xe0, 0xff, 0xe7, 0xbb}, - {0x06, 0xf0, 0x0d, 0xbb}, - {0x06, 0x70, 0x0e, 0xbb}, - {0x4c, 0x00, 0x01, 0xbb}, - {0x4d, 0x00, 0x01, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x2e, 0x0c, 0x60, 0xbb}, - {0x21, 0xb6, 0x6e, 0xbb}, - {0x37, 0x01, 0x40, 0xbb}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x07, 0x00, 0x84, 0xbb}, - {0x08, 0x02, 0x4a, 0xbb}, - {0x05, 0x01, 0x10, 0xbb}, - {0x06, 0x00, 0x39, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x58, 0x02, 0x67, 0xbb}, - {0x57, 0x02, 0x00, 0xbb}, - {0x5a, 0x02, 0x67, 0xbb}, - {0x59, 0x02, 0x00, 0xbb}, - {0x5c, 0x12, 0x0d, 0xbb}, - {0x5d, 0x16, 0x11, 0xbb}, - {0x39, 0x06, 0x18, 0xbb}, - {0x3a, 0x06, 0x18, 0xbb}, - {0x3b, 0x06, 0x18, 0xbb}, - {0x3c, 0x06, 0x18, 0xbb}, - {0x64, 0x7b, 0x5b, 0xbb}, - {0xb6, 0x00, 0x00, 0xcc}, - {0xb6, 0x03, 0x05, 0xcc}, - {0xb6, 0x02, 0x00, 0xcc}, - {0xb6, 0x05, 0x03, 0xcc}, - {0xb6, 0x04, 0xc0, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, - {0xb6, 0x13, 0x29, 0xcc}, - {0xb6, 0x18, 0x09, 0xcc}, - {0xb6, 0x17, 0x60, 0xcc}, - {0xb6, 0x16, 0x00, 0xcc}, - {0xb6, 0x22, 0x12, 0xcc}, - {0xb6, 0x23, 0x0b, 0xcc}, - {0xbf, 0xc0, 0x39, 0xcc}, - {0xbf, 0xc1, 0x04, 0xcc}, - {0xbf, 0xcc, 0x00, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, - {0x00, 0x00, 0x80, 0xdd}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x00, 0x00, 0x10, 0xdd}, - {0x22, 0xa0, 0x78, 0xbb}, - {0x23, 0xa0, 0x78, 0xbb}, - {0x24, 0x7f, 0x00, 0xbb}, - {0x28, 0xea, 0x02, 0xbb}, - {0x29, 0x86, 0x7a, 0xbb}, - {0x5e, 0x52, 0x4c, 0xbb}, - {0x5f, 0x20, 0x24, 0xbb}, - {0x60, 0x00, 0x02, 0xbb}, - {0x02, 0x00, 0xee, 0xbb}, - {0x03, 0x39, 0x23, 0xbb}, - {0x04, 0x07, 0x24, 0xbb}, - {0x09, 0x00, 0xc0, 0xbb}, - {0x0a, 0x00, 0x79, 0xbb}, - {0x0b, 0x00, 0x04, 0xbb}, - {0x0c, 0x00, 0x5c, 0xbb}, - {0x0d, 0x00, 0xd9, 0xbb}, - {0x0e, 0x00, 0x53, 0xbb}, - {0x0f, 0x00, 0x21, 0xbb}, - {0x10, 0x00, 0xa4, 0xbb}, - {0x11, 0x00, 0xe5, 0xbb}, - {0x15, 0x00, 0x00, 0xbb}, - {0x16, 0x00, 0x00, 0xbb}, - {0x17, 0x00, 0x00, 0xbb}, - {0x18, 0x00, 0x00, 0xbb}, - {0x19, 0x00, 0x00, 0xbb}, - {0x1a, 0x00, 0x00, 0xbb}, - {0x1b, 0x00, 0x00, 0xbb}, - {0x1c, 0x00, 0x00, 0xbb}, - {0x1d, 0x00, 0x00, 0xbb}, - {0x1e, 0x00, 0x00, 0xbb}, - {0xf0, 0x00, 0x01, 0xbb}, - {0x00, 0x00, 0x20, 0xdd}, - {0x06, 0xf0, 0x8e, 0xbb}, - {0x00, 0x00, 0x80, 0xdd}, - {0x06, 0x70, 0x8e, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x00, 0x00, 0x20, 0xdd}, - {0x5e, 0x6a, 0x53, 0xbb}, - {0x5f, 0x40, 0x2c, 0xbb}, - {0xf0, 0x00, 0x01, 0xbb}, - {0x00, 0x00, 0x20, 0xdd}, - {0x58, 0x00, 0x00, 0xbb}, - {0x53, 0x09, 0x03, 0xbb}, - {0x54, 0x31, 0x18, 0xbb}, - {0x55, 0x8b, 0x5f, 0xbb}, - {0x56, 0xc0, 0xa9, 0xbb}, - {0x57, 0xe0, 0xd2, 0xbb}, - {0xe1, 0x00, 0x00, 0xbb}, - {0xdc, 0x09, 0x03, 0xbb}, - {0xdd, 0x31, 0x18, 0xbb}, - {0xde, 0x8b, 0x5f, 0xbb}, - {0xdf, 0xc0, 0xa9, 0xbb}, - {0xe0, 0xe0, 0xd2, 0xbb}, - {0xb3, 0x5c, 0x01, 0xcc}, - {0xf0, 0x00, 0x01, 0xbb}, - {0x06, 0xf0, 0x8e, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x2f, 0xde, 0x20, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x24, 0x50, 0x20, 0xbb}, - {0xbc, 0x0e, 0x00, 0xcc}, - {0xbc, 0x0f, 0x05, 0xcc}, - {0xbc, 0x10, 0xc0, 0xcc}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x34, 0x0c, 0x50, 0xbb}, - {0xbc, 0x11, 0x03, 0xcc}, - {0xf0, 0x00, 0x01, 0xbb}, - {0x80, 0x00, 0x03, 0xbb}, - {0x81, 0xc7, 0x14, 0xbb}, - {0x82, 0xeb, 0xe8, 0xbb}, - {0x83, 0xfe, 0xf4, 0xbb}, - {0x84, 0xcd, 0x10, 0xbb}, - {0x85, 0xf3, 0xee, 0xbb}, - {0x86, 0xff, 0xf1, 0xbb}, - {0x87, 0xcd, 0x10, 0xbb}, - {0x88, 0xf3, 0xee, 0xbb}, - {0x89, 0x01, 0xf1, 0xbb}, - {0x8a, 0xe5, 0x17, 0xbb}, - {0x8b, 0xe8, 0xe2, 0xbb}, - {0x8c, 0xf7, 0xed, 0xbb}, - {0x8d, 0x00, 0xff, 0xbb}, - {0x8e, 0xec, 0x10, 0xbb}, - {0x8f, 0xf0, 0xed, 0xbb}, - {0x90, 0xf9, 0xf2, 0xbb}, - {0x91, 0x00, 0x00, 0xbb}, - {0x92, 0xe9, 0x0d, 0xbb}, - {0x93, 0xf4, 0xf2, 0xbb}, - {0x94, 0xfb, 0xf5, 0xbb}, - {0x95, 0x00, 0xff, 0xbb}, - {0xb6, 0x0f, 0x08, 0xbb}, - {0xb7, 0x3d, 0x16, 0xbb}, - {0xb8, 0x0c, 0x04, 0xbb}, - {0xb9, 0x1c, 0x07, 0xbb}, - {0xba, 0x0a, 0x03, 0xbb}, - {0xbb, 0x1b, 0x09, 0xbb}, - {0xbc, 0x17, 0x0d, 0xbb}, - {0xbd, 0x23, 0x1d, 0xbb}, - {0xbe, 0x00, 0x28, 0xbb}, - {0xbf, 0x11, 0x09, 0xbb}, - {0xc0, 0x16, 0x15, 0xbb}, - {0xc1, 0x00, 0x1b, 0xbb}, - {0xc2, 0x0e, 0x07, 0xbb}, - {0xc3, 0x14, 0x10, 0xbb}, - {0xc4, 0x00, 0x17, 0xbb}, - {0x06, 0x74, 0x8e, 0xbb}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x03, 0x03, 0xc0, 0xbb}, - {} -}; - -static const u8 mi1320_gamma[17] = { - 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, - 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff -}; -static const u8 mi1320_matrix[9] = { - 0x54, 0xda, 0x06, 0xf1, 0x50, 0xf4, 0xf7, 0xea, 0x52 -}; -static const u8 mi1320_initVGA_data[][4] = { - {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x33, 0xdd}, - {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x33, 0xdd}, - {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x33, 0xdd}, - {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc}, - {0xb0, 0x16, 0x03, 0xcc}, {0xb3, 0x05, 0x00, 0xcc}, - {0xb3, 0x06, 0x00, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc}, - {0xb3, 0x35, 0xc8, 0xcc}, /* i2c add: 48 */ - {0xb3, 0x02, 0x00, 0xcc}, - {0xb3, 0x03, 0x0a, 0xcc}, {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x03, 0xcc}, {0xb3, 0x23, 0xc0, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x04, 0xcc}, {0xb3, 0x17, 0xff, 0xcc}, - {0xb3, 0x00, 0x67, 0xcc}, {0xbc, 0x00, 0xd0, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, {0xf0, 0x00, 0x00, 0xbb}, - {0x0d, 0x00, 0x09, 0xbb}, {0x00, 0x01, 0x00, 0xdd}, - {0x0d, 0x00, 0x08, 0xbb}, {0xf0, 0x00, 0x01, 0xbb}, - {0xa1, 0x05, 0x00, 0xbb}, {0xa4, 0x03, 0xc0, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x00, 0x00, 0x10, 0xdd}, - {0xc8, 0x9f, 0x0b, 0xbb}, {0x00, 0x00, 0x10, 0xdd}, - {0xf0, 0x00, 0x00, 0xbb}, {0x00, 0x00, 0x10, 0xdd}, - {0x20, 0x01, 0x00, 0xbb}, {0x00, 0x00, 0x10, 0xdd}, - {0xf0, 0x00, 0x01, 0xbb}, {0x9d, 0x3c, 0xa0, 0xbb}, - {0x47, 0x30, 0x30, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, - {0x0a, 0x80, 0x11, 0xbb}, {0x35, 0x00, 0x22, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x9d, 0xc5, 0x05, 0xbb}, - {0xdc, 0x0f, 0xfc, 0xbb}, {0xf0, 0x00, 0x01, 0xbb}, - {0x06, 0x74, 0x0e, 0xbb}, {0x80, 0x00, 0x06, 0xbb}, - {0x81, 0x04, 0x00, 0xbb}, {0x82, 0x01, 0x02, 0xbb}, - {0x83, 0x03, 0x02, 0xbb}, {0x84, 0x05, 0x00, 0xbb}, - {0x85, 0x01, 0x00, 0xbb}, {0x86, 0x03, 0x02, 0xbb}, - {0x87, 0x05, 0x00, 0xbb}, {0x88, 0x01, 0x00, 0xbb}, - {0x89, 0x02, 0x02, 0xbb}, {0x8a, 0xfd, 0x04, 0xbb}, - {0x8b, 0xfc, 0xfd, 0xbb}, {0x8c, 0xff, 0xfd, 0xbb}, - {0x8d, 0x00, 0x00, 0xbb}, {0x8e, 0xfe, 0x05, 0xbb}, - {0x8f, 0xfc, 0xfd, 0xbb}, {0x90, 0xfe, 0xfd, 0xbb}, - {0x91, 0x00, 0x00, 0xbb}, {0x92, 0xfe, 0x03, 0xbb}, - {0x93, 0xfd, 0xfe, 0xbb}, {0x94, 0xff, 0xfd, 0xbb}, - {0x95, 0x00, 0x00, 0xbb}, {0xb6, 0x07, 0x05, 0xbb}, - {0xb7, 0x13, 0x06, 0xbb}, {0xb8, 0x08, 0x06, 0xbb}, - {0xb9, 0x14, 0x08, 0xbb}, {0xba, 0x06, 0x05, 0xbb}, - {0xbb, 0x13, 0x06, 0xbb}, {0xbc, 0x03, 0x01, 0xbb}, - {0xbd, 0x03, 0x04, 0xbb}, {0xbe, 0x00, 0x02, 0xbb}, - {0xbf, 0x03, 0x01, 0xbb}, {0xc0, 0x02, 0x04, 0xbb}, - {0xc1, 0x00, 0x04, 0xbb}, {0xc2, 0x02, 0x01, 0xbb}, - {0xc3, 0x01, 0x03, 0xbb}, {0xc4, 0x00, 0x04, 0xbb}, - {0xf0, 0x00, 0x00, 0xbb}, {0x05, 0x01, 0x13, 0xbb}, - {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x00, 0x85, 0xbb}, - {0x08, 0x00, 0x27, 0xbb}, - {0x20, 0x01, 0x00, 0xbb}, /* h/v flips - was 03 */ - {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb}, - {0x24, 0x80, 0x00, 0xbb}, {0x59, 0x00, 0xff, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x39, 0x03, 0x0d, 0xbb}, - {0x3a, 0x06, 0x1b, 0xbb}, {0x3b, 0x00, 0x95, 0xbb}, - {0x3c, 0x04, 0xdb, 0xbb}, {0x57, 0x02, 0x00, 0xbb}, - {0x58, 0x02, 0x66, 0xbb}, {0x59, 0x00, 0xff, 0xbb}, - {0x5a, 0x01, 0x33, 0xbb}, {0x5c, 0x12, 0x0d, 0xbb}, - {0x5d, 0x16, 0x11, 0xbb}, {0x64, 0x5e, 0x1c, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x2f, 0xd1, 0x00, 0xbb}, - {0x5b, 0x00, 0x01, 0xbb}, {0xf0, 0x00, 0x02, 0xbb}, - {0x36, 0x68, 0x10, 0xbb}, {0x00, 0x00, 0x30, 0xdd}, - {0x37, 0x82, 0x00, 0xbb}, {0xbc, 0x0e, 0x00, 0xcc}, - {0xbc, 0x0f, 0x05, 0xcc}, {0xbc, 0x10, 0xc0, 0xcc}, - {0xbc, 0x11, 0x03, 0xcc}, {0xb6, 0x00, 0x00, 0xcc}, - {0xb6, 0x03, 0x05, 0xcc}, {0xb6, 0x02, 0x00, 0xcc}, - {0xb6, 0x05, 0x04, 0xcc}, {0xb6, 0x04, 0x00, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x29, 0xcc}, - {0xb6, 0x18, 0x0a, 0xcc}, {0xb6, 0x17, 0x00, 0xcc}, - {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc}, - {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x26, 0xcc}, - {0xbf, 0xc1, 0x02, 0xcc}, {0xbf, 0xcc, 0x04, 0xcc}, - {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc}, - {0xbc, 0x04, 0x18, 0xcc}, {0xbc, 0x05, 0x00, 0xcc}, - {0xbc, 0x06, 0x00, 0xcc}, {0xbc, 0x08, 0x30, 0xcc}, - {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x10, 0xcc}, - {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x01, 0x41, 0xcc}, - {} -}; -static const u8 mi1320_initQVGA_data[][4] = { - {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x33, 0xdd}, - {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x33, 0xdd}, - {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x33, 0xdd}, - {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc}, - {0xb0, 0x16, 0x03, 0xcc}, {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc}, - {0xb3, 0x35, 0xc8, 0xcc}, {0xb3, 0x02, 0x00, 0xcc}, - {0xb3, 0x03, 0x0a, 0xcc}, {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x01, 0xcc}, {0xb3, 0x23, 0xe0, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x00, 0x65, 0xcc}, {0xb8, 0x00, 0x00, 0xcc}, - {0xbc, 0x00, 0xd0, 0xcc}, {0xbc, 0x01, 0x01, 0xcc}, - {0xf0, 0x00, 0x00, 0xbb}, {0x0d, 0x00, 0x09, 0xbb}, - {0x00, 0x01, 0x00, 0xdd}, {0x0d, 0x00, 0x08, 0xbb}, - {0xf0, 0x00, 0x00, 0xbb}, {0x02, 0x00, 0x64, 0xbb}, - {0x05, 0x01, 0x78, 0xbb}, {0x06, 0x00, 0x11, 0xbb}, - {0x07, 0x01, 0x42, 0xbb}, {0x08, 0x00, 0x11, 0xbb}, - {0x20, 0x01, 0x00, 0xbb}, {0x21, 0x80, 0x00, 0xbb}, - {0x22, 0x0d, 0x0f, 0xbb}, {0x24, 0x80, 0x00, 0xbb}, - {0x59, 0x00, 0xff, 0xbb}, {0xf0, 0x00, 0x01, 0xbb}, - {0x9d, 0x3c, 0xa0, 0xbb}, {0x47, 0x30, 0x30, 0xbb}, - {0xf0, 0x00, 0x00, 0xbb}, {0x0a, 0x80, 0x11, 0xbb}, - {0x35, 0x00, 0x22, 0xbb}, {0xf0, 0x00, 0x02, 0xbb}, - {0x9d, 0xc5, 0x05, 0xbb}, {0xdc, 0x0f, 0xfc, 0xbb}, - {0xf0, 0x00, 0x01, 0xbb}, {0x06, 0x74, 0x0e, 0xbb}, - {0x80, 0x00, 0x06, 0xbb}, {0x81, 0x04, 0x00, 0xbb}, - {0x82, 0x01, 0x02, 0xbb}, {0x83, 0x03, 0x02, 0xbb}, - {0x84, 0x05, 0x00, 0xbb}, {0x85, 0x01, 0x00, 0xbb}, - {0x86, 0x03, 0x02, 0xbb}, {0x87, 0x05, 0x00, 0xbb}, - {0x88, 0x01, 0x00, 0xbb}, {0x89, 0x02, 0x02, 0xbb}, - {0x8a, 0xfd, 0x04, 0xbb}, {0x8b, 0xfc, 0xfd, 0xbb}, - {0x8c, 0xff, 0xfd, 0xbb}, {0x8d, 0x00, 0x00, 0xbb}, - {0x8e, 0xfe, 0x05, 0xbb}, {0x8f, 0xfc, 0xfd, 0xbb}, - {0x90, 0xfe, 0xfd, 0xbb}, {0x91, 0x00, 0x00, 0xbb}, - {0x92, 0xfe, 0x03, 0xbb}, {0x93, 0xfd, 0xfe, 0xbb}, - {0x94, 0xff, 0xfd, 0xbb}, {0x95, 0x00, 0x00, 0xbb}, - {0xb6, 0x07, 0x05, 0xbb}, {0xb7, 0x13, 0x06, 0xbb}, - {0xb8, 0x08, 0x06, 0xbb}, {0xb9, 0x14, 0x08, 0xbb}, - {0xba, 0x06, 0x05, 0xbb}, {0xbb, 0x13, 0x06, 0xbb}, - {0xbc, 0x03, 0x01, 0xbb}, {0xbd, 0x03, 0x04, 0xbb}, - {0xbe, 0x00, 0x02, 0xbb}, {0xbf, 0x03, 0x01, 0xbb}, - {0xc0, 0x02, 0x04, 0xbb}, {0xc1, 0x00, 0x04, 0xbb}, - {0xc2, 0x02, 0x01, 0xbb}, {0xc3, 0x01, 0x03, 0xbb}, - {0xc4, 0x00, 0x04, 0xbb}, {0xf0, 0x00, 0x02, 0xbb}, - {0xc8, 0x00, 0x00, 0xbb}, {0x2e, 0x00, 0x00, 0xbb}, - {0x2e, 0x0c, 0x5b, 0xbb}, {0x2f, 0xd1, 0x00, 0xbb}, - {0x39, 0x03, 0xca, 0xbb}, {0x3a, 0x06, 0x80, 0xbb}, - {0x3b, 0x01, 0x52, 0xbb}, {0x3c, 0x05, 0x40, 0xbb}, - {0x57, 0x01, 0x9c, 0xbb}, {0x58, 0x01, 0xee, 0xbb}, - {0x59, 0x00, 0xf0, 0xbb}, {0x5a, 0x01, 0x20, 0xbb}, - {0x5c, 0x1d, 0x17, 0xbb}, {0x5d, 0x22, 0x1c, 0xbb}, - {0x64, 0x1e, 0x1c, 0xbb}, {0x5b, 0x00, 0x01, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x36, 0x68, 0x10, 0xbb}, - {0x00, 0x00, 0x30, 0xdd}, {0x37, 0x81, 0x00, 0xbb}, - {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc}, - {0xbc, 0x04, 0x18, 0xcc}, {0xbc, 0x05, 0x00, 0xcc}, - {0xbc, 0x06, 0x00, 0xcc}, {0xbc, 0x08, 0x30, 0xcc}, - {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x10, 0xcc}, - {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc}, - {0xbf, 0xc0, 0x26, 0xcc}, {0xbf, 0xc1, 0x02, 0xcc}, - {0xbf, 0xcc, 0x04, 0xcc}, {0xb3, 0x5c, 0x01, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, - {} -}; - -static const u8 mi1320_soc_InitVGA[][4] = { - {0xb3, 0x01, 0x01, 0xcc}, - {0xb0, 0x03, 0x19, 0xcc}, - {0xb0, 0x04, 0x02, 0xcc}, - {0x00, 0x00, 0x30, 0xdd}, - {0xb3, 0x00, 0x64, 0xcc}, - {0xb3, 0x00, 0x67, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x34, 0x02, 0xcc}, - {0xb3, 0x35, 0xc8, 0xcc}, /* i2c add: 48 */ - {0xb3, 0x02, 0x00, 0xcc}, - {0xb3, 0x03, 0x0a, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, - {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x00, 0x67, 0xcc}, - {0xb8, 0x00, 0x00, 0xcc}, - {0xbc, 0x00, 0x71, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x00, 0x00, 0x10, 0xdd}, - {0xc8, 0x00, 0x00, 0xbb}, - {0x00, 0x00, 0x30, 0xdd}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x00, 0x00, 0x10, 0xdd}, - {0x07, 0x00, 0xe0, 0xbb}, - {0x08, 0x00, 0x0b, 0xbb}, - {0x21, 0x00, 0x0c, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ - {0xbf, 0xc0, 0x26, 0xcc}, - {0xbf, 0xc1, 0x02, 0xcc}, - {0xbf, 0xcc, 0x04, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x05, 0x01, 0x78, 0xbb}, - {0x06, 0x00, 0x11, 0xbb}, - {0x07, 0x01, 0x42, 0xbb}, - {0x08, 0x00, 0x11, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ - {0x21, 0x80, 0x00, 0xbb}, - {0x22, 0x0d, 0x0f, 0xbb}, - {0x24, 0x80, 0x00, 0xbb}, - {0x59, 0x00, 0xff, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x39, 0x03, 0xca, 0xbb}, - {0x3a, 0x06, 0x80, 0xbb}, - {0x3b, 0x01, 0x52, 0xbb}, - {0x3c, 0x05, 0x40, 0xbb}, - {0x57, 0x01, 0x9c, 0xbb}, - {0x58, 0x01, 0xee, 0xbb}, - {0x59, 0x00, 0xf0, 0xbb}, - {0x5a, 0x01, 0x20, 0xbb}, - {0x5c, 0x1d, 0x17, 0xbb}, - {0x5d, 0x22, 0x1c, 0xbb}, - {0x64, 0x1e, 0x1c, 0xbb}, - {0x5b, 0x00, 0x00, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x22, 0xa0, 0x78, 0xbb}, - {0x23, 0xa0, 0x78, 0xbb}, - {0x24, 0x7f, 0x00, 0xbb}, - {0x28, 0xea, 0x02, 0xbb}, - {0x29, 0x86, 0x7a, 0xbb}, - {0x5e, 0x52, 0x4c, 0xbb}, - {0x5f, 0x20, 0x24, 0xbb}, - {0x60, 0x00, 0x02, 0xbb}, - {0x02, 0x00, 0xee, 0xbb}, - {0x03, 0x39, 0x23, 0xbb}, - {0x04, 0x07, 0x24, 0xbb}, - {0x09, 0x00, 0xc0, 0xbb}, - {0x0a, 0x00, 0x79, 0xbb}, - {0x0b, 0x00, 0x04, 0xbb}, - {0x0c, 0x00, 0x5c, 0xbb}, - {0x0d, 0x00, 0xd9, 0xbb}, - {0x0e, 0x00, 0x53, 0xbb}, - {0x0f, 0x00, 0x21, 0xbb}, - {0x10, 0x00, 0xa4, 0xbb}, - {0x11, 0x00, 0xe5, 0xbb}, - {0x15, 0x00, 0x00, 0xbb}, - {0x16, 0x00, 0x00, 0xbb}, - {0x17, 0x00, 0x00, 0xbb}, - {0x18, 0x00, 0x00, 0xbb}, - {0x19, 0x00, 0x00, 0xbb}, - {0x1a, 0x00, 0x00, 0xbb}, - {0x1b, 0x00, 0x00, 0xbb}, - {0x1c, 0x00, 0x00, 0xbb}, - {0x1d, 0x00, 0x00, 0xbb}, - {0x1e, 0x00, 0x00, 0xbb}, - {0xf0, 0x00, 0x01, 0xbb}, - {0x06, 0xe0, 0x0e, 0xbb}, - {0x06, 0x60, 0x0e, 0xbb}, - {0xb3, 0x5c, 0x01, 0xcc}, - {} -}; -static const u8 mi1320_soc_InitQVGA[][4] = { - {0xb3, 0x01, 0x01, 0xcc}, - {0xb0, 0x03, 0x19, 0xcc}, - {0xb0, 0x04, 0x02, 0xcc}, - {0x00, 0x00, 0x30, 0xdd}, - {0xb3, 0x00, 0x64, 0xcc}, - {0xb3, 0x00, 0x67, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x34, 0x02, 0xcc}, - {0xb3, 0x35, 0xc8, 0xcc}, - {0xb3, 0x02, 0x00, 0xcc}, - {0xb3, 0x03, 0x0a, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, - {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x00, 0x67, 0xcc}, - {0xb8, 0x00, 0x00, 0xcc}, - {0xbc, 0x00, 0xd1, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x00, 0x00, 0x10, 0xdd}, - {0xc8, 0x00, 0x00, 0xbb}, - {0x00, 0x00, 0x30, 0xdd}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x00, 0x00, 0x10, 0xdd}, - {0x07, 0x00, 0xe0, 0xbb}, - {0x08, 0x00, 0x0b, 0xbb}, - {0x21, 0x00, 0x0c, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ - {0xbf, 0xc0, 0x26, 0xcc}, - {0xbf, 0xc1, 0x02, 0xcc}, - {0xbf, 0xcc, 0x04, 0xcc}, - {0xbc, 0x02, 0x18, 0xcc}, - {0xbc, 0x03, 0x50, 0xcc}, - {0xbc, 0x04, 0x18, 0xcc}, - {0xbc, 0x05, 0x00, 0xcc}, - {0xbc, 0x06, 0x00, 0xcc}, - {0xbc, 0x08, 0x30, 0xcc}, - {0xbc, 0x09, 0x40, 0xcc}, - {0xbc, 0x0a, 0x10, 0xcc}, - {0xbc, 0x0b, 0x00, 0xcc}, - {0xbc, 0x0c, 0x00, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x05, 0x01, 0x78, 0xbb}, - {0x06, 0x00, 0x11, 0xbb}, - {0x07, 0x01, 0x42, 0xbb}, - {0x08, 0x00, 0x11, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ - {0x21, 0x80, 0x00, 0xbb}, - {0x22, 0x0d, 0x0f, 0xbb}, - {0x24, 0x80, 0x00, 0xbb}, - {0x59, 0x00, 0xff, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x39, 0x03, 0xca, 0xbb}, - {0x3a, 0x06, 0x80, 0xbb}, - {0x3b, 0x01, 0x52, 0xbb}, - {0x3c, 0x05, 0x40, 0xbb}, - {0x57, 0x01, 0x9c, 0xbb}, - {0x58, 0x01, 0xee, 0xbb}, - {0x59, 0x00, 0xf0, 0xbb}, - {0x5a, 0x01, 0x20, 0xbb}, - {0x5c, 0x1d, 0x17, 0xbb}, - {0x5d, 0x22, 0x1c, 0xbb}, - {0x64, 0x1e, 0x1c, 0xbb}, - {0x5b, 0x00, 0x00, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x22, 0xa0, 0x78, 0xbb}, - {0x23, 0xa0, 0x78, 0xbb}, - {0x24, 0x7f, 0x00, 0xbb}, - {0x28, 0xea, 0x02, 0xbb}, - {0x29, 0x86, 0x7a, 0xbb}, - {0x5e, 0x52, 0x4c, 0xbb}, - {0x5f, 0x20, 0x24, 0xbb}, - {0x60, 0x00, 0x02, 0xbb}, - {0x02, 0x00, 0xee, 0xbb}, - {0x03, 0x39, 0x23, 0xbb}, - {0x04, 0x07, 0x24, 0xbb}, - {0x09, 0x00, 0xc0, 0xbb}, - {0x0a, 0x00, 0x79, 0xbb}, - {0x0b, 0x00, 0x04, 0xbb}, - {0x0c, 0x00, 0x5c, 0xbb}, - {0x0d, 0x00, 0xd9, 0xbb}, - {0x0e, 0x00, 0x53, 0xbb}, - {0x0f, 0x00, 0x21, 0xbb}, - {0x10, 0x00, 0xa4, 0xbb}, - {0x11, 0x00, 0xe5, 0xbb}, - {0x15, 0x00, 0x00, 0xbb}, - {0x16, 0x00, 0x00, 0xbb}, - {0x17, 0x00, 0x00, 0xbb}, - {0x18, 0x00, 0x00, 0xbb}, - {0x19, 0x00, 0x00, 0xbb}, - {0x1a, 0x00, 0x00, 0xbb}, - {0x1b, 0x00, 0x00, 0xbb}, - {0x1c, 0x00, 0x00, 0xbb}, - {0x1d, 0x00, 0x00, 0xbb}, - {0x1e, 0x00, 0x00, 0xbb}, - {0xf0, 0x00, 0x01, 0xbb}, - {0x06, 0xe0, 0x0e, 0xbb}, - {0x06, 0x60, 0x0e, 0xbb}, - {0xb3, 0x5c, 0x01, 0xcc}, - {} -}; -static const u8 mi1320_soc_InitSXGA[][4] = { - {0xb3, 0x01, 0x01, 0xcc}, - {0xb0, 0x03, 0x19, 0xcc}, - {0x00, 0x00, 0x30, 0xdd}, - {0xb3, 0x00, 0x64, 0xcc}, - {0xb3, 0x00, 0x67, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x34, 0x02, 0xcc}, - {0xb3, 0x35, 0xc8, 0xcc}, - {0xb3, 0x02, 0x00, 0xcc}, - {0xb3, 0x03, 0x0a, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x04, 0xcc}, - {0xb3, 0x23, 0x00, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x04, 0xcc}, - {0xb3, 0x17, 0xff, 0xcc}, - {0xb3, 0x00, 0x67, 0xcc}, - {0xbc, 0x00, 0x71, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x00, 0x00, 0x30, 0xdd}, - {0xc8, 0x9f, 0x0b, 0xbb}, - {0x00, 0x00, 0x20, 0xdd}, - {0x5b, 0x00, 0x01, 0xbb}, - {0x00, 0x00, 0x20, 0xdd}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x00, 0x00, 0x30, 0xdd}, - {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ - {0x00, 0x00, 0x20, 0xdd}, - {0xbf, 0xc0, 0x26, 0xcc}, - {0xbf, 0xc1, 0x02, 0xcc}, - {0xbf, 0xcc, 0x04, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x05, 0x01, 0x78, 0xbb}, - {0x06, 0x00, 0x11, 0xbb}, - {0x07, 0x01, 0x42, 0xbb}, - {0x08, 0x00, 0x11, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ - {0x21, 0x80, 0x00, 0xbb}, - {0x22, 0x0d, 0x0f, 0xbb}, - {0x24, 0x80, 0x00, 0xbb}, - {0x59, 0x00, 0xff, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x39, 0x03, 0xca, 0xbb}, - {0x3a, 0x06, 0x80, 0xbb}, - {0x3b, 0x01, 0x52, 0xbb}, - {0x3c, 0x05, 0x40, 0xbb}, - {0x57, 0x01, 0x9c, 0xbb}, - {0x58, 0x01, 0xee, 0xbb}, - {0x59, 0x00, 0xf0, 0xbb}, - {0x5a, 0x01, 0x20, 0xbb}, - {0x5c, 0x1d, 0x17, 0xbb}, - {0x5d, 0x22, 0x1c, 0xbb}, - {0x64, 0x1e, 0x1c, 0xbb}, - {0x5b, 0x00, 0x00, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x22, 0xa0, 0x78, 0xbb}, - {0x23, 0xa0, 0x78, 0xbb}, - {0x24, 0x7f, 0x00, 0xbb}, - {0x28, 0xea, 0x02, 0xbb}, - {0x29, 0x86, 0x7a, 0xbb}, - {0x5e, 0x52, 0x4c, 0xbb}, - {0x5f, 0x20, 0x24, 0xbb}, - {0x60, 0x00, 0x02, 0xbb}, - {0x02, 0x00, 0xee, 0xbb}, - {0x03, 0x39, 0x23, 0xbb}, - {0x04, 0x07, 0x24, 0xbb}, - {0x09, 0x00, 0xc0, 0xbb}, - {0x0a, 0x00, 0x79, 0xbb}, - {0x0b, 0x00, 0x04, 0xbb}, - {0x0c, 0x00, 0x5c, 0xbb}, - {0x0d, 0x00, 0xd9, 0xbb}, - {0x0e, 0x00, 0x53, 0xbb}, - {0x0f, 0x00, 0x21, 0xbb}, - {0x10, 0x00, 0xa4, 0xbb}, - {0x11, 0x00, 0xe5, 0xbb}, - {0x15, 0x00, 0x00, 0xbb}, - {0x16, 0x00, 0x00, 0xbb}, - {0x17, 0x00, 0x00, 0xbb}, - {0x18, 0x00, 0x00, 0xbb}, - {0x19, 0x00, 0x00, 0xbb}, - {0x1a, 0x00, 0x00, 0xbb}, - {0x1b, 0x00, 0x00, 0xbb}, - {0x1c, 0x00, 0x00, 0xbb}, - {0x1d, 0x00, 0x00, 0xbb}, - {0x1e, 0x00, 0x00, 0xbb}, - {0xf0, 0x00, 0x01, 0xbb}, - {0x06, 0xe0, 0x0e, 0xbb}, - {0x06, 0x60, 0x0e, 0xbb}, - {0xb3, 0x5c, 0x01, 0xcc}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x05, 0x01, 0x13, 0xbb}, - {0x06, 0x00, 0x11, 0xbb}, - {0x07, 0x00, 0x85, 0xbb}, - {0x08, 0x00, 0x27, 0xbb}, - {0x20, 0x01, 0x03, 0xbb}, /* h/v flip */ - {0x21, 0x80, 0x00, 0xbb}, - {0x22, 0x0d, 0x0f, 0xbb}, - {0x24, 0x80, 0x00, 0xbb}, - {0x59, 0x00, 0xff, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x39, 0x03, 0x0d, 0xbb}, - {0x3a, 0x06, 0x1b, 0xbb}, - {0x3b, 0x00, 0x95, 0xbb}, - {0x3c, 0x04, 0xdb, 0xbb}, - {0x57, 0x02, 0x00, 0xbb}, - {0x58, 0x02, 0x66, 0xbb}, - {0x59, 0x00, 0xff, 0xbb}, - {0x5a, 0x01, 0x33, 0xbb}, - {0x5c, 0x12, 0x0d, 0xbb}, - {0x5d, 0x16, 0x11, 0xbb}, - {0x64, 0x5e, 0x1c, 0xbb}, - {} -}; -static const u8 po3130_gamma[17] = { - 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, - 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff -}; -static const u8 po3130_matrix[9] = { - 0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63 -}; - -static const u8 po3130_initVGA_data[][4] = { - {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc}, - {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc}, - {0xb3, 0x00, 0x04, 0xcc}, {0xb3, 0x00, 0x24, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, {0xb3, 0x03, 0x1a, 0xcc}, - {0xb3, 0x04, 0x15, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe8, 0xcc}, {0xb8, 0x08, 0xe8, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x34, 0x01, 0xcc}, - {0xb3, 0x35, 0xf6, 0xcc}, /* i2c add: 76 */ - {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0x71, 0xcc}, - {0xb8, 0x00, 0x21, 0xcc}, {0xb8, 0x27, 0x20, 0xcc}, - {0xb8, 0x01, 0x79, 0xcc}, {0xb8, 0x81, 0x09, 0xcc}, - {0xb8, 0x2c, 0x50, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc}, - {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc}, - {0xb8, 0x30, 0x50, 0xcc}, {0xb8, 0x31, 0xf8, 0xcc}, - {0xb8, 0x32, 0xf8, 0xcc}, {0xb8, 0x33, 0xf8, 0xcc}, - {0xb8, 0x34, 0x50, 0xcc}, {0xb8, 0x35, 0x00, 0xcc}, - {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc}, - {0x00, 0x1e, 0xc6, 0xaa}, {0x00, 0x20, 0x44, 0xaa}, - {0x00, 0xad, 0x02, 0xaa}, {0x00, 0xae, 0x2c, 0xaa}, - {0x00, 0x12, 0x08, 0xaa}, {0x00, 0x17, 0x41, 0xaa}, - {0x00, 0x19, 0x41, 0xaa}, {0x00, 0x1e, 0x06, 0xaa}, - {0x00, 0x21, 0x00, 0xaa}, {0x00, 0x36, 0xc0, 0xaa}, - {0x00, 0x37, 0xc8, 0xaa}, {0x00, 0x3b, 0x36, 0xaa}, - {0x00, 0x4b, 0xfe, 0xaa}, {0x00, 0x51, 0x1c, 0xaa}, - {0x00, 0x52, 0x01, 0xaa}, {0x00, 0x55, 0x0a, 0xaa}, - {0x00, 0x59, 0x02, 0xaa}, {0x00, 0x5a, 0x04, 0xaa}, - {0x00, 0x5c, 0x10, 0xaa}, {0x00, 0x5d, 0x10, 0xaa}, - {0x00, 0x5e, 0x10, 0xaa}, {0x00, 0x5f, 0x10, 0xaa}, - {0x00, 0x61, 0x00, 0xaa}, {0x00, 0x62, 0x18, 0xaa}, - {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x70, 0x68, 0xaa}, - {0x00, 0x80, 0x71, 0xaa}, {0x00, 0x81, 0x08, 0xaa}, - {0x00, 0x82, 0x00, 0xaa}, {0x00, 0x83, 0x55, 0xaa}, - {0x00, 0x84, 0x06, 0xaa}, {0x00, 0x85, 0x06, 0xaa}, - {0x00, 0x86, 0x13, 0xaa}, {0x00, 0x87, 0x18, 0xaa}, - {0x00, 0xaa, 0x3f, 0xaa}, {0x00, 0xab, 0x44, 0xaa}, - {0x00, 0xb0, 0x68, 0xaa}, {0x00, 0xb5, 0x10, 0xaa}, - {0x00, 0xb8, 0x20, 0xaa}, {0x00, 0xb9, 0xa0, 0xaa}, - {0x00, 0xbc, 0x04, 0xaa}, {0x00, 0x8b, 0x40, 0xaa}, - {0x00, 0x8c, 0x91, 0xaa}, {0x00, 0x8d, 0x8f, 0xaa}, - {0x00, 0x8e, 0x91, 0xaa}, {0x00, 0x8f, 0x43, 0xaa}, - {0x00, 0x90, 0x92, 0xaa}, {0x00, 0x91, 0x89, 0xaa}, - {0x00, 0x92, 0x9d, 0xaa}, {0x00, 0x93, 0x46, 0xaa}, - {0x00, 0xd6, 0x22, 0xaa}, {0x00, 0x73, 0x00, 0xaa}, - {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa}, - {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa}, - {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa}, - {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa}, - {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa}, - {0x00, 0x7e, 0xea, 0xaa}, {0x00, 0xd6, 0x62, 0xaa}, - {0x00, 0x73, 0x00, 0xaa}, {0x00, 0x74, 0x10, 0xaa}, - {0x00, 0x75, 0x20, 0xaa}, {0x00, 0x76, 0x2b, 0xaa}, - {0x00, 0x77, 0x36, 0xaa}, {0x00, 0x78, 0x49, 0xaa}, - {0x00, 0x79, 0x5a, 0xaa}, {0x00, 0x7a, 0x7f, 0xaa}, - {0x00, 0x7b, 0x9b, 0xaa}, {0x00, 0x7c, 0xba, 0xaa}, - {0x00, 0x7d, 0xd4, 0xaa}, {0x00, 0x7e, 0xea, 0xaa}, - {0x00, 0xd6, 0xa2, 0xaa}, {0x00, 0x73, 0x00, 0xaa}, - {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa}, - {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa}, - {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa}, - {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa}, - {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa}, - {0x00, 0x7e, 0xea, 0xaa}, - {0x00, 0x4c, 0x07, 0xaa}, - {0x00, 0x4b, 0xe0, 0xaa}, {0x00, 0x4e, 0x77, 0xaa}, - {0x00, 0x59, 0x02, 0xaa}, {0x00, 0x4d, 0x0a, 0xaa}, -/* {0x00, 0xd1, 0x00, 0xaa}, {0x00, 0x20, 0xc4, 0xaa}, - {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc}, */ - {0x00, 0xd1, 0x3c, 0xaa}, {0x00, 0x20, 0xc4, 0xaa}, - {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc}, - {0xb8, 0xfe, 0x00, 0xcc}, {0xb8, 0xff, 0x28, 0xcc}, - {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc}, - {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc}, - {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc}, - {0xb9, 0x06, 0x3c, 0xcc}, {0xb9, 0x07, 0x3c, 0xcc}, - {0xb9, 0x08, 0x3c, 0xcc}, {0x00, 0x05, 0x00, 0xaa}, - {0xb3, 0x5c, 0x00, 0xcc}, {0xb3, 0x01, 0x41, 0xcc}, - {} -}; -static const u8 po3130_rundata[][4] = { - {0x00, 0x47, 0x45, 0xaa}, {0x00, 0x48, 0x9b, 0xaa}, - {0x00, 0x49, 0x3a, 0xaa}, {0x00, 0x4a, 0x01, 0xaa}, - {0x00, 0x44, 0x40, 0xaa}, -/* {0x00, 0xd5, 0x7c, 0xaa}, */ - {0x00, 0xad, 0x04, 0xaa}, {0x00, 0xae, 0x00, 0xaa}, - {0x00, 0xb0, 0x78, 0xaa}, {0x00, 0x98, 0x02, 0xaa}, - {0x00, 0x94, 0x25, 0xaa}, {0x00, 0x95, 0x25, 0xaa}, - {0x00, 0x59, 0x68, 0xaa}, {0x00, 0x44, 0x20, 0xaa}, - {0x00, 0x17, 0x50, 0xaa}, {0x00, 0x19, 0x50, 0xaa}, - {0x00, 0xd1, 0x3c, 0xaa}, {0x00, 0xd1, 0x3c, 0xaa}, - {0x00, 0x1e, 0x06, 0xaa}, {0x00, 0x1e, 0x06, 0xaa}, - {} -}; - -static const u8 po3130_initQVGA_data[][4] = { - {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc}, - {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x09, 0xcc}, - {0xb3, 0x00, 0x04, 0xcc}, {0xb3, 0x00, 0x24, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, {0xb3, 0x03, 0x1a, 0xcc}, - {0xb3, 0x04, 0x15, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, {0xb8, 0x08, 0xe0, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x34, 0x01, 0xcc}, {0xb3, 0x35, 0xf6, 0xcc}, - {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0xd1, 0xcc}, - {0xb8, 0x00, 0x21, 0xcc}, {0xb8, 0x27, 0x20, 0xcc}, - {0xb8, 0x01, 0x79, 0xcc}, {0xb8, 0x81, 0x09, 0xcc}, - {0xb8, 0x2c, 0x50, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc}, - {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc}, - {0xb8, 0x30, 0x50, 0xcc}, {0xb8, 0x31, 0xf8, 0xcc}, - {0xb8, 0x32, 0xf8, 0xcc}, {0xb8, 0x33, 0xf8, 0xcc}, - {0xb8, 0x34, 0x50, 0xcc}, {0xb8, 0x35, 0x00, 0xcc}, - {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc}, - {0x00, 0x1e, 0xc6, 0xaa}, {0x00, 0x20, 0x44, 0xaa}, - {0x00, 0xad, 0x02, 0xaa}, {0x00, 0xae, 0x2c, 0xaa}, - {0x00, 0x12, 0x08, 0xaa}, {0x00, 0x17, 0x41, 0xaa}, - {0x00, 0x19, 0x41, 0xaa}, {0x00, 0x1e, 0x06, 0xaa}, - {0x00, 0x21, 0x00, 0xaa}, {0x00, 0x36, 0xc0, 0xaa}, - {0x00, 0x37, 0xc8, 0xaa}, {0x00, 0x3b, 0x36, 0xaa}, - {0x00, 0x4b, 0xfe, 0xaa}, {0x00, 0x51, 0x1c, 0xaa}, - {0x00, 0x52, 0x01, 0xaa}, {0x00, 0x55, 0x0a, 0xaa}, - {0x00, 0x59, 0x6f, 0xaa}, {0x00, 0x5a, 0x04, 0xaa}, - {0x00, 0x5c, 0x10, 0xaa}, {0x00, 0x5d, 0x10, 0xaa}, - {0x00, 0x5e, 0x10, 0xaa}, {0x00, 0x5f, 0x10, 0xaa}, - {0x00, 0x61, 0x00, 0xaa}, {0x00, 0x62, 0x18, 0xaa}, - {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x70, 0x68, 0xaa}, - {0x00, 0x80, 0x71, 0xaa}, {0x00, 0x81, 0x08, 0xaa}, - {0x00, 0x82, 0x00, 0xaa}, {0x00, 0x83, 0x55, 0xaa}, - {0x00, 0x84, 0x06, 0xaa}, {0x00, 0x85, 0x06, 0xaa}, - {0x00, 0x86, 0x13, 0xaa}, {0x00, 0x87, 0x18, 0xaa}, - {0x00, 0xaa, 0x3f, 0xaa}, {0x00, 0xab, 0x44, 0xaa}, - {0x00, 0xb0, 0x68, 0xaa}, {0x00, 0xb5, 0x10, 0xaa}, - {0x00, 0xb8, 0x20, 0xaa}, {0x00, 0xb9, 0xa0, 0xaa}, - {0x00, 0xbc, 0x04, 0xaa}, {0x00, 0x8b, 0x40, 0xaa}, - {0x00, 0x8c, 0x91, 0xaa}, {0x00, 0x8d, 0x8f, 0xaa}, - {0x00, 0x8e, 0x91, 0xaa}, {0x00, 0x8f, 0x43, 0xaa}, - {0x00, 0x90, 0x92, 0xaa}, {0x00, 0x91, 0x89, 0xaa}, - {0x00, 0x92, 0x9d, 0xaa}, {0x00, 0x93, 0x46, 0xaa}, - {0x00, 0xd6, 0x22, 0xaa}, {0x00, 0x73, 0x00, 0xaa}, - {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa}, - {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa}, - {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa}, - {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa}, - {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa}, - {0x00, 0x7e, 0xea, 0xaa}, {0x00, 0xd6, 0x62, 0xaa}, - {0x00, 0x73, 0x00, 0xaa}, {0x00, 0x74, 0x10, 0xaa}, - {0x00, 0x75, 0x20, 0xaa}, {0x00, 0x76, 0x2b, 0xaa}, - {0x00, 0x77, 0x36, 0xaa}, {0x00, 0x78, 0x49, 0xaa}, - {0x00, 0x79, 0x5a, 0xaa}, {0x00, 0x7a, 0x7f, 0xaa}, - {0x00, 0x7b, 0x9b, 0xaa}, {0x00, 0x7c, 0xba, 0xaa}, - {0x00, 0x7d, 0xd4, 0xaa}, {0x00, 0x7e, 0xea, 0xaa}, - {0x00, 0xd6, 0xa2, 0xaa}, {0x00, 0x73, 0x00, 0xaa}, - {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa}, - {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa}, - {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa}, - {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa}, - {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa}, - {0x00, 0x7e, 0xea, 0xaa}, {0x00, 0x4c, 0x07, 0xaa}, - {0x00, 0x4b, 0xe0, 0xaa}, {0x00, 0x4e, 0x77, 0xaa}, - {0x00, 0x59, 0x66, 0xaa}, {0x00, 0x4d, 0x0a, 0xaa}, - {0x00, 0xd1, 0x00, 0xaa}, {0x00, 0x20, 0xc4, 0xaa}, - {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc}, - {0xb8, 0xfe, 0x00, 0xcc}, {0xb8, 0xff, 0x28, 0xcc}, - {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc}, - {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc}, - {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc}, - {0xb9, 0x06, 0x3c, 0xcc}, {0xb9, 0x07, 0x3c, 0xcc}, - {0xb9, 0x08, 0x3c, 0xcc}, {0xbc, 0x02, 0x18, 0xcc}, - {0xbc, 0x03, 0x50, 0xcc}, {0xbc, 0x04, 0x18, 0xcc}, - {0xbc, 0x05, 0x00, 0xcc}, {0xbc, 0x06, 0x00, 0xcc}, - {0xbc, 0x08, 0x30, 0xcc}, {0xbc, 0x09, 0x40, 0xcc}, - {0xbc, 0x0a, 0x10, 0xcc}, {0xbc, 0x0b, 0x00, 0xcc}, - {0xbc, 0x0c, 0x00, 0xcc}, {0x00, 0x05, 0x00, 0xaa}, - {0xb3, 0x5c, 0x00, 0xcc}, {0xb3, 0x01, 0x41, 0xcc}, - {} -}; - -static const u8 hv7131r_gamma[17] = { - 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, - 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff -}; -static const u8 hv7131r_matrix[9] = { - 0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63 -}; -static const u8 hv7131r_initVGA_data[][4] = { - {0xb3, 0x01, 0x01, 0xcc}, - {0xb0, 0x03, 0x19, 0xcc}, - {0xb0, 0x04, 0x02, 0xcc}, - {0x00, 0x00, 0x20, 0xdd}, - {0xb3, 0x00, 0x24, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x03, 0xcc}, - {0xb3, 0x01, 0x45, 0xcc}, - {0xb3, 0x03, 0x0b, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x02, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, - {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x34, 0x01, 0xcc}, - {0xb3, 0x35, 0x91, 0xcc}, /* i2c add: 11 */ - {0xb3, 0x00, 0x27, 0xcc}, - {0xbc, 0x00, 0x73, 0xcc}, - {0xb8, 0x00, 0x23, 0xcc}, - {0xb8, 0x2c, 0x50, 0xcc}, - {0xb8, 0x2d, 0xf8, 0xcc}, - {0xb8, 0x2e, 0xf8, 0xcc}, - {0xb8, 0x2f, 0xf8, 0xcc}, - {0xb8, 0x30, 0x50, 0xcc}, - {0xb8, 0x31, 0xf8, 0xcc}, - {0xb8, 0x32, 0xf8, 0xcc}, - {0xb8, 0x33, 0xf8, 0xcc}, - {0xb8, 0x34, 0x58, 0xcc}, - {0xb8, 0x35, 0x00, 0xcc}, - {0xb8, 0x36, 0x00, 0xcc}, - {0xb8, 0x37, 0x00, 0xcc}, - {0xb8, 0x27, 0x20, 0xcc}, - {0xb8, 0x01, 0x7d, 0xcc}, - {0xb8, 0x81, 0x09, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, - {0xb8, 0x8e, 0x00, 0xcc}, - {0xb8, 0x8f, 0xff, 0xcc}, - {0x00, 0x01, 0x0c, 0xaa}, - {0x00, 0x14, 0x01, 0xaa}, - {0x00, 0x15, 0xe6, 0xaa}, - {0x00, 0x16, 0x02, 0xaa}, - {0x00, 0x17, 0x86, 0xaa}, - {0x00, 0x23, 0x00, 0xaa}, - {0x00, 0x25, 0x03, 0xaa}, - {0x00, 0x26, 0xa9, 0xaa}, - {0x00, 0x27, 0x80, 0xaa}, - {0x00, 0x30, 0x18, 0xaa}, - {0xb6, 0x00, 0x00, 0xcc}, - {0xb6, 0x03, 0x02, 0xcc}, - {0xb6, 0x02, 0x80, 0xcc}, - {0xb6, 0x05, 0x01, 0xcc}, - {0xb6, 0x04, 0xe0, 0xcc}, - {0xb6, 0x12, 0x78, 0xcc}, - {0xb6, 0x18, 0x02, 0xcc}, - {0xb6, 0x17, 0x58, 0xcc}, - {0xb6, 0x16, 0x00, 0xcc}, - {0xb6, 0x22, 0x12, 0xcc}, - {0xb6, 0x23, 0x0b, 0xcc}, - {0xb3, 0x02, 0x02, 0xcc}, - {0xbf, 0xc0, 0x39, 0xcc}, - {0xbf, 0xc1, 0x04, 0xcc}, - {0xbf, 0xcc, 0x10, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, - {0xb6, 0x13, 0x13, 0xcc}, - {0xb9, 0x12, 0x00, 0xcc}, - {0xb9, 0x13, 0x0a, 0xcc}, - {0xb9, 0x14, 0x0a, 0xcc}, - {0xb9, 0x15, 0x0a, 0xcc}, - {0xb9, 0x16, 0x0a, 0xcc}, - {0xb8, 0x0c, 0x20, 0xcc}, - {0xb8, 0x0d, 0x70, 0xcc}, - {0xb9, 0x18, 0x00, 0xcc}, - {0xb9, 0x19, 0x0f, 0xcc}, - {0xb9, 0x1a, 0x0f, 0xcc}, - {0xb9, 0x1b, 0x0f, 0xcc}, - {0xb9, 0x1c, 0x0f, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, - {} -}; - -static const u8 hv7131r_initQVGA_data[][4] = { - {0xb3, 0x01, 0x01, 0xcc}, - {0xb0, 0x03, 0x19, 0xcc}, - {0xb0, 0x04, 0x02, 0xcc}, - {0x00, 0x00, 0x20, 0xdd}, - {0xb3, 0x00, 0x24, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x03, 0xcc}, - {0xb3, 0x01, 0x45, 0xcc}, - {0xb3, 0x03, 0x0b, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x02, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, - {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x34, 0x01, 0xcc}, - {0xb3, 0x35, 0x91, 0xcc}, - {0xb3, 0x00, 0x27, 0xcc}, - {0xbc, 0x00, 0xd3, 0xcc}, - {0xb8, 0x00, 0x23, 0xcc}, - {0xb8, 0x2c, 0x50, 0xcc}, - {0xb8, 0x2d, 0xf8, 0xcc}, - {0xb8, 0x2e, 0xf8, 0xcc}, - {0xb8, 0x2f, 0xf8, 0xcc}, - {0xb8, 0x30, 0x50, 0xcc}, - {0xb8, 0x31, 0xf8, 0xcc}, - {0xb8, 0x32, 0xf8, 0xcc}, - {0xb8, 0x33, 0xf8, 0xcc}, - {0xb8, 0x34, 0x58, 0xcc}, - {0xb8, 0x35, 0x00, 0xcc}, - {0xb8, 0x36, 0x00, 0xcc}, - {0xb8, 0x37, 0x00, 0xcc}, - {0xb8, 0x27, 0x20, 0xcc}, - {0xb8, 0x01, 0x7d, 0xcc}, - {0xb8, 0x81, 0x09, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, - {0xb8, 0x8e, 0x00, 0xcc}, - {0xb8, 0x8f, 0xff, 0xcc}, - {0x00, 0x01, 0x0c, 0xaa}, - {0x00, 0x14, 0x01, 0xaa}, - {0x00, 0x15, 0xe6, 0xaa}, - {0x00, 0x16, 0x02, 0xaa}, - {0x00, 0x17, 0x86, 0xaa}, - {0x00, 0x23, 0x00, 0xaa}, - {0x00, 0x25, 0x03, 0xaa}, - {0x00, 0x26, 0xa9, 0xaa}, - {0x00, 0x27, 0x80, 0xaa}, - {0x00, 0x30, 0x18, 0xaa}, - {0xb6, 0x00, 0x00, 0xcc}, - {0xb6, 0x03, 0x01, 0xcc}, - {0xb6, 0x02, 0x40, 0xcc}, - {0xb6, 0x05, 0x00, 0xcc}, - {0xb6, 0x04, 0xf0, 0xcc}, - {0xb6, 0x12, 0x78, 0xcc}, - {0xb6, 0x18, 0x00, 0xcc}, - {0xb6, 0x17, 0x96, 0xcc}, - {0xb6, 0x16, 0x00, 0xcc}, - {0xb6, 0x22, 0x12, 0xcc}, - {0xb6, 0x23, 0x0b, 0xcc}, - {0xb3, 0x02, 0x02, 0xcc}, - {0xbf, 0xc0, 0x39, 0xcc}, - {0xbf, 0xc1, 0x04, 0xcc}, - {0xbf, 0xcc, 0x10, 0xcc}, - {0xbc, 0x02, 0x18, 0xcc}, - {0xbc, 0x03, 0x50, 0xcc}, - {0xbc, 0x04, 0x18, 0xcc}, - {0xbc, 0x05, 0x00, 0xcc}, - {0xbc, 0x06, 0x00, 0xcc}, - {0xbc, 0x08, 0x30, 0xcc}, - {0xbc, 0x09, 0x40, 0xcc}, - {0xbc, 0x0a, 0x10, 0xcc}, - {0xbc, 0x0b, 0x00, 0xcc}, - {0xbc, 0x0c, 0x00, 0xcc}, - {0xb9, 0x12, 0x00, 0xcc}, - {0xb9, 0x13, 0x0a, 0xcc}, - {0xb9, 0x14, 0x0a, 0xcc}, - {0xb9, 0x15, 0x0a, 0xcc}, - {0xb9, 0x16, 0x0a, 0xcc}, - {0xb9, 0x18, 0x00, 0xcc}, - {0xb9, 0x19, 0x0f, 0xcc}, - {0xb8, 0x0c, 0x20, 0xcc}, - {0xb8, 0x0d, 0x70, 0xcc}, - {0xb9, 0x1a, 0x0f, 0xcc}, - {0xb9, 0x1b, 0x0f, 0xcc}, - {0xb9, 0x1c, 0x0f, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, - {0xb6, 0x13, 0x13, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, - {} -}; - -static const u8 ov7660_gamma[17] = { - 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, - 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff -}; -static const u8 ov7660_matrix[9] = { - 0x5a, 0xf0, 0xf6, 0xf3, 0x57, 0xf6, 0xf3, 0xef, 0x62 -}; -static const u8 ov7660_initVGA_data[][4] = { - {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc}, - {0x00, 0x00, 0x50, 0xdd}, - {0xb0, 0x03, 0x01, 0xcc}, - {0xb3, 0x00, 0x21, 0xcc}, {0xb3, 0x00, 0x26, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x03, 0xcc}, - {0xb3, 0x03, 0x1f, 0xcc}, {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x05, 0x00, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc},/* 0xb315 <-0 href startl */ - {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x1d, 0x01, 0xcc}, - {0xb3, 0x1f, 0x02, 0xcc}, - {0xb3, 0x34, 0x01, 0xcc}, - {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */ - {0xb3, 0x00, 0x26, 0xcc}, - {0xb8, 0x00, 0x33, 0xcc}, /* 13 */ - {0xb8, 0x01, 0x7d, 0xcc}, - {0xbc, 0x00, 0x73, 0xcc}, {0xb8, 0x81, 0x09, 0xcc}, - {0xb8, 0x27, 0x20, 0xcc}, - {0xb8, 0x8f, 0x50, 0xcc}, - {0x00, 0x01, 0x80, 0xaa}, {0x00, 0x02, 0x80, 0xaa}, - {0x00, 0x12, 0x80, 0xaa}, - {0x00, 0x12, 0x05, 0xaa}, - {0x00, 0x1e, 0x01, 0xaa}, /* MVFP */ - {0x00, 0x3d, 0x40, 0xaa}, /* 0x3d <-40 gamma 01 */ - {0x00, 0x41, 0x00, 0xaa}, /* edge 00 */ - {0x00, 0x0d, 0x48, 0xaa}, {0x00, 0x0e, 0x04, 0xaa}, - {0x00, 0x13, 0xa7, 0xaa}, - {0x00, 0x40, 0xc1, 0xaa}, {0x00, 0x35, 0x00, 0xaa}, - {0x00, 0x36, 0x00, 0xaa}, - {0x00, 0x3c, 0x68, 0xaa}, {0x00, 0x1b, 0x05, 0xaa}, - {0x00, 0x39, 0x43, 0xaa}, - {0x00, 0x8d, 0xcf, 0xaa}, - {0x00, 0x8b, 0xcc, 0xaa}, {0x00, 0x8c, 0xcc, 0xaa}, - {0x00, 0x0f, 0x62, 0xaa}, - {0x00, 0x35, 0x84, 0xaa}, - {0x00, 0x3b, 0x08, 0xaa}, /* 0 * Nightframe 1/4 + 50Hz -> 0xC8 */ - {0x00, 0x3a, 0x00, 0xaa}, /* mx change yuyv format 00, 04, 01; 08, 0c*/ - {0x00, 0x14, 0x2a, 0xaa}, /* agc ampli */ - {0x00, 0x9e, 0x40, 0xaa}, {0xb8, 0x8f, 0x50, 0xcc}, - {0x00, 0x01, 0x80, 0xaa}, - {0x00, 0x02, 0x80, 0xaa}, - {0xb8, 0xfe, 0x00, 0xcc}, {0xb8, 0xff, 0x28, 0xcc}, - {0xb9, 0x00, 0x28, 0xcc}, - {0xb9, 0x01, 0x28, 0xcc}, {0xb9, 0x02, 0x28, 0xcc}, - {0xb9, 0x03, 0x00, 0xcc}, - {0xb9, 0x04, 0x00, 0xcc}, - {0xb9, 0x05, 0x3c, 0xcc}, {0xb9, 0x06, 0x3c, 0xcc}, - {0xb9, 0x07, 0x3c, 0xcc}, - {0xb9, 0x08, 0x3c, 0xcc}, - - {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc}, - - {0x00, 0x29, 0x3c, 0xaa}, {0xb3, 0x01, 0x45, 0xcc}, - {} -}; -static const u8 ov7660_initQVGA_data[][4] = { - {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc}, - {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc}, - {0xb3, 0x00, 0x21, 0xcc}, {0xb3, 0x00, 0x26, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x03, 0xcc}, - {0xb3, 0x03, 0x1f, 0xcc}, {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x05, 0x00, 0xcc}, {0xb3, 0x06, 0x01, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc},/* 0xb315 <-0 href startl */ - {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x1d, 0x01, 0xcc}, - {0xb3, 0x1f, 0x02, 0xcc}, {0xb3, 0x34, 0x01, 0xcc}, - {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x00, 0x26, 0xcc}, - {0xb8, 0x00, 0x33, 0xcc}, /* 13 */ - {0xb8, 0x01, 0x7d, 0xcc}, -/* sizer */ - {0xbc, 0x00, 0xd3, 0xcc}, - {0xb8, 0x81, 0x09, 0xcc}, {0xb8, 0x81, 0x09, 0xcc}, - {0xb8, 0x27, 0x20, 0xcc}, {0xb8, 0x8f, 0x50, 0xcc}, - {0x00, 0x01, 0x80, 0xaa}, {0x00, 0x02, 0x80, 0xaa}, - {0x00, 0x12, 0x80, 0xaa}, {0x00, 0x12, 0x05, 0xaa}, - {0x00, 0x1e, 0x01, 0xaa}, /* MVFP */ - {0x00, 0x3d, 0x40, 0xaa}, /* 0x3d <-40 gamma 01 */ - {0x00, 0x41, 0x00, 0xaa}, /* edge 00 */ - {0x00, 0x0d, 0x48, 0xaa}, {0x00, 0x0e, 0x04, 0xaa}, - {0x00, 0x13, 0xa7, 0xaa}, - {0x00, 0x40, 0xc1, 0xaa}, {0x00, 0x35, 0x00, 0xaa}, - {0x00, 0x36, 0x00, 0xaa}, - {0x00, 0x3c, 0x68, 0xaa}, {0x00, 0x1b, 0x05, 0xaa}, - {0x00, 0x39, 0x43, 0xaa}, {0x00, 0x8d, 0xcf, 0xaa}, - {0x00, 0x8b, 0xcc, 0xaa}, {0x00, 0x8c, 0xcc, 0xaa}, - {0x00, 0x0f, 0x62, 0xaa}, {0x00, 0x35, 0x84, 0xaa}, - {0x00, 0x3b, 0x08, 0xaa}, /* 0 * Nightframe 1/4 + 50Hz -> 0xC8 */ - {0x00, 0x3a, 0x00, 0xaa}, /* mx change yuyv format 00, 04, 01; 08, 0c*/ - {0x00, 0x14, 0x2a, 0xaa}, /* agc ampli */ - {0x00, 0x9e, 0x40, 0xaa}, {0xb8, 0x8f, 0x50, 0xcc}, - {0x00, 0x01, 0x80, 0xaa}, - {0x00, 0x02, 0x80, 0xaa}, -/* sizer filters */ - {0xbc, 0x02, 0x08, 0xcc}, - {0xbc, 0x03, 0x70, 0xcc}, - {0xb8, 0x35, 0x00, 0xcc}, - {0xb8, 0x36, 0x00, 0xcc}, - {0xb8, 0x37, 0x00, 0xcc}, - {0xbc, 0x04, 0x08, 0xcc}, - {0xbc, 0x05, 0x00, 0xcc}, - {0xbc, 0x06, 0x00, 0xcc}, - {0xbc, 0x08, 0x3c, 0xcc}, - {0xbc, 0x09, 0x40, 0xcc}, - {0xbc, 0x0a, 0x04, 0xcc}, - {0xbc, 0x0b, 0x00, 0xcc}, - {0xbc, 0x0c, 0x00, 0xcc}, -/* */ - {0xb8, 0xfe, 0x00, 0xcc}, - {0xb8, 0xff, 0x28, 0xcc}, -/* */ - {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc}, - {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc}, - {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc}, - {0xb9, 0x06, 0x3c, 0xcc}, {0xb9, 0x07, 0x3c, 0xcc}, - {0xb9, 0x08, 0x3c, 0xcc}, -/* */ - {0xb8, 0x8e, 0x00, 0xcc}, - {0xb8, 0x8f, 0xff, 0xcc}, /* ff */ - {0x00, 0x29, 0x3c, 0xaa}, - {0xb3, 0x01, 0x45, 0xcc}, /* 45 */ - {} -}; - -static const u8 ov7660_50HZ[][4] = { - {0x00, 0x3b, 0x08, 0xaa}, - {0x00, 0x9d, 0x40, 0xaa}, - {0x00, 0x13, 0xa7, 0xaa}, - {} -}; - -static const u8 ov7660_60HZ[][4] = { - {0x00, 0x3b, 0x00, 0xaa}, - {0x00, 0x9e, 0x40, 0xaa}, - {0x00, 0x13, 0xa7, 0xaa}, - {} -}; - -static const u8 ov7660_NoFliker[][4] = { - {0x00, 0x13, 0x87, 0xaa}, - {} -}; - -static const u8 ov7670_InitVGA[][4] = { - {0xb3, 0x01, 0x05, 0xcc}, - {0x00, 0x00, 0x30, 0xdd}, - {0xb0, 0x03, 0x19, 0xcc}, - {0x00, 0x00, 0x10, 0xdd}, - {0xb0, 0x04, 0x02, 0xcc}, - {0x00, 0x00, 0x10, 0xdd}, - {0xb3, 0x00, 0x66, 0xcc}, - {0xb3, 0x00, 0x67, 0xcc}, - {0xb0, 0x16, 0x01, 0xcc}, - {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */ - {0xb3, 0x34, 0x01, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x02, 0x02, 0xcc}, - {0xb3, 0x03, 0x1f, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, - {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, - {0xbc, 0x00, 0x41, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, - {0x00, 0x12, 0x80, 0xaa}, - {0x00, 0x00, 0x20, 0xdd}, - {0x00, 0x12, 0x00, 0xaa}, - {0x00, 0x11, 0x40, 0xaa}, - {0x00, 0x6b, 0x0a, 0xaa}, - {0x00, 0x3a, 0x04, 0xaa}, - {0x00, 0x40, 0xc0, 0xaa}, - {0x00, 0x8c, 0x00, 0xaa}, - {0x00, 0x7a, 0x29, 0xaa}, - {0x00, 0x7b, 0x0e, 0xaa}, - {0x00, 0x7c, 0x1a, 0xaa}, - {0x00, 0x7d, 0x31, 0xaa}, - {0x00, 0x7e, 0x53, 0xaa}, - {0x00, 0x7f, 0x60, 0xaa}, - {0x00, 0x80, 0x6b, 0xaa}, - {0x00, 0x81, 0x73, 0xaa}, - {0x00, 0x82, 0x7b, 0xaa}, - {0x00, 0x83, 0x82, 0xaa}, - {0x00, 0x84, 0x89, 0xaa}, - {0x00, 0x85, 0x96, 0xaa}, - {0x00, 0x86, 0xa1, 0xaa}, - {0x00, 0x87, 0xb7, 0xaa}, - {0x00, 0x88, 0xcc, 0xaa}, - {0x00, 0x89, 0xe1, 0xaa}, - {0x00, 0x13, 0xe0, 0xaa}, - {0x00, 0x00, 0x00, 0xaa}, - {0x00, 0x10, 0x00, 0xaa}, - {0x00, 0x0d, 0x40, 0xaa}, - {0x00, 0x14, 0x28, 0xaa}, - {0x00, 0xa5, 0x05, 0xaa}, - {0x00, 0xab, 0x07, 0xaa}, - {0x00, 0x24, 0x95, 0xaa}, - {0x00, 0x25, 0x33, 0xaa}, - {0x00, 0x26, 0xe3, 0xaa}, - {0x00, 0x9f, 0x88, 0xaa}, - {0x00, 0xa0, 0x78, 0xaa}, - {0x00, 0x55, 0x90, 0xaa}, - {0x00, 0xa1, 0x03, 0xaa}, - {0x00, 0xa6, 0xe0, 0xaa}, - {0x00, 0xa7, 0xd8, 0xaa}, - {0x00, 0xa8, 0xf0, 0xaa}, - {0x00, 0xa9, 0x90, 0xaa}, - {0x00, 0xaa, 0x14, 0xaa}, - {0x00, 0x13, 0xe5, 0xaa}, - {0x00, 0x0e, 0x61, 0xaa}, - {0x00, 0x0f, 0x4b, 0xaa}, - {0x00, 0x16, 0x02, 0xaa}, - {0x00, 0x1e, 0x07, 0xaa}, /* MVFP */ - {0x00, 0x21, 0x02, 0xaa}, - {0x00, 0x22, 0x91, 0xaa}, - {0x00, 0x29, 0x07, 0xaa}, - {0x00, 0x33, 0x0b, 0xaa}, - {0x00, 0x35, 0x0b, 0xaa}, - {0x00, 0x37, 0x1d, 0xaa}, - {0x00, 0x38, 0x71, 0xaa}, - {0x00, 0x39, 0x2a, 0xaa}, - {0x00, 0x3c, 0x78, 0xaa}, - {0x00, 0x4d, 0x40, 0xaa}, - {0x00, 0x4e, 0x20, 0xaa}, - {0x00, 0x74, 0x19, 0xaa}, - {0x00, 0x8d, 0x4f, 0xaa}, - {0x00, 0x8e, 0x00, 0xaa}, - {0x00, 0x8f, 0x00, 0xaa}, - {0x00, 0x90, 0x00, 0xaa}, - {0x00, 0x91, 0x00, 0xaa}, - {0x00, 0x96, 0x00, 0xaa}, - {0x00, 0x9a, 0x80, 0xaa}, - {0x00, 0xb0, 0x84, 0xaa}, - {0x00, 0xb1, 0x0c, 0xaa}, - {0x00, 0xb2, 0x0e, 0xaa}, - {0x00, 0xb3, 0x82, 0xaa}, - {0x00, 0xb8, 0x0a, 0xaa}, - {0x00, 0x43, 0x14, 0xaa}, - {0x00, 0x44, 0xf0, 0xaa}, - {0x00, 0x45, 0x45, 0xaa}, - {0x00, 0x46, 0x63, 0xaa}, - {0x00, 0x47, 0x2d, 0xaa}, - {0x00, 0x48, 0x46, 0xaa}, - {0x00, 0x59, 0x88, 0xaa}, - {0x00, 0x5a, 0xa0, 0xaa}, - {0x00, 0x5b, 0xc6, 0xaa}, - {0x00, 0x5c, 0x7d, 0xaa}, - {0x00, 0x5d, 0x5f, 0xaa}, - {0x00, 0x5e, 0x19, 0xaa}, - {0x00, 0x6c, 0x0a, 0xaa}, - {0x00, 0x6d, 0x55, 0xaa}, - {0x00, 0x6e, 0x11, 0xaa}, - {0x00, 0x6f, 0x9e, 0xaa}, - {0x00, 0x69, 0x00, 0xaa}, - {0x00, 0x6a, 0x40, 0xaa}, - {0x00, 0x01, 0x40, 0xaa}, - {0x00, 0x02, 0x40, 0xaa}, - {0x00, 0x13, 0xe7, 0xaa}, - {0x00, 0x5f, 0xf0, 0xaa}, - {0x00, 0x60, 0xf0, 0xaa}, - {0x00, 0x61, 0xf0, 0xaa}, - {0x00, 0x27, 0xa0, 0xaa}, - {0x00, 0x28, 0x80, 0xaa}, - {0x00, 0x2c, 0x90, 0xaa}, - {0x00, 0x4f, 0x66, 0xaa}, - {0x00, 0x50, 0x66, 0xaa}, - {0x00, 0x51, 0x00, 0xaa}, - {0x00, 0x52, 0x22, 0xaa}, - {0x00, 0x53, 0x5e, 0xaa}, - {0x00, 0x54, 0x80, 0xaa}, - {0x00, 0x58, 0x9e, 0xaa}, - {0x00, 0x41, 0x08, 0xaa}, - {0x00, 0x3f, 0x00, 0xaa}, - {0x00, 0x75, 0x85, 0xaa}, - {0x00, 0x76, 0xe1, 0xaa}, - {0x00, 0x4c, 0x00, 0xaa}, - {0x00, 0x77, 0x0a, 0xaa}, - {0x00, 0x3d, 0x88, 0xaa}, - {0x00, 0x4b, 0x09, 0xaa}, - {0x00, 0xc9, 0x60, 0xaa}, - {0x00, 0x41, 0x38, 0xaa}, - {0x00, 0x62, 0x30, 0xaa}, - {0x00, 0x63, 0x30, 0xaa}, - {0x00, 0x64, 0x08, 0xaa}, - {0x00, 0x94, 0x07, 0xaa}, - {0x00, 0x95, 0x0b, 0xaa}, - {0x00, 0x65, 0x00, 0xaa}, - {0x00, 0x66, 0x05, 0xaa}, - {0x00, 0x56, 0x50, 0xaa}, - {0x00, 0x34, 0x11, 0xaa}, - {0x00, 0xa4, 0x88, 0xaa}, - {0x00, 0x96, 0x00, 0xaa}, - {0x00, 0x97, 0x30, 0xaa}, - {0x00, 0x98, 0x20, 0xaa}, - {0x00, 0x99, 0x30, 0xaa}, - {0x00, 0x9a, 0x84, 0xaa}, - {0x00, 0x9b, 0x29, 0xaa}, - {0x00, 0x9c, 0x03, 0xaa}, - {0x00, 0x78, 0x04, 0xaa}, - {0x00, 0x79, 0x01, 0xaa}, - {0x00, 0xc8, 0xf0, 0xaa}, - {0x00, 0x79, 0x0f, 0xaa}, - {0x00, 0xc8, 0x00, 0xaa}, - {0x00, 0x79, 0x10, 0xaa}, - {0x00, 0xc8, 0x7e, 0xaa}, - {0x00, 0x79, 0x0a, 0xaa}, - {0x00, 0xc8, 0x80, 0xaa}, - {0x00, 0x79, 0x0b, 0xaa}, - {0x00, 0xc8, 0x01, 0xaa}, - {0x00, 0x79, 0x0c, 0xaa}, - {0x00, 0xc8, 0x0f, 0xaa}, - {0x00, 0x79, 0x0d, 0xaa}, - {0x00, 0xc8, 0x20, 0xaa}, - {0x00, 0x79, 0x09, 0xaa}, - {0x00, 0xc8, 0x80, 0xaa}, - {0x00, 0x79, 0x02, 0xaa}, - {0x00, 0xc8, 0xc0, 0xaa}, - {0x00, 0x79, 0x03, 0xaa}, - {0x00, 0xc8, 0x40, 0xaa}, - {0x00, 0x79, 0x05, 0xaa}, - {0x00, 0xc8, 0x30, 0xaa}, - {0x00, 0x79, 0x26, 0xaa}, - {0x00, 0x11, 0x40, 0xaa}, - {0x00, 0x3a, 0x04, 0xaa}, - {0x00, 0x12, 0x00, 0xaa}, - {0x00, 0x40, 0xc0, 0xaa}, - {0x00, 0x8c, 0x00, 0xaa}, - {0x00, 0x17, 0x14, 0xaa}, - {0x00, 0x18, 0x02, 0xaa}, - {0x00, 0x32, 0x92, 0xaa}, - {0x00, 0x19, 0x02, 0xaa}, - {0x00, 0x1a, 0x7a, 0xaa}, - {0x00, 0x03, 0x0a, 0xaa}, - {0x00, 0x0c, 0x00, 0xaa}, - {0x00, 0x3e, 0x00, 0xaa}, - {0x00, 0x70, 0x3a, 0xaa}, - {0x00, 0x71, 0x35, 0xaa}, - {0x00, 0x72, 0x11, 0xaa}, - {0x00, 0x73, 0xf0, 0xaa}, - {0x00, 0xa2, 0x02, 0xaa}, - {0x00, 0xb1, 0x00, 0xaa}, - {0x00, 0xb1, 0x0c, 0xaa}, - {0x00, 0x1e, 0x37, 0xaa}, /* MVFP */ - {0x00, 0xaa, 0x14, 0xaa}, - {0x00, 0x24, 0x80, 0xaa}, - {0x00, 0x25, 0x74, 0xaa}, - {0x00, 0x26, 0xd3, 0xaa}, - {0x00, 0x0d, 0x00, 0xaa}, - {0x00, 0x14, 0x18, 0xaa}, - {0x00, 0x9d, 0x99, 0xaa}, - {0x00, 0x9e, 0x7f, 0xaa}, - {0x00, 0x64, 0x08, 0xaa}, - {0x00, 0x94, 0x07, 0xaa}, - {0x00, 0x95, 0x06, 0xaa}, - {0x00, 0x66, 0x05, 0xaa}, - {0x00, 0x41, 0x08, 0xaa}, - {0x00, 0x3f, 0x00, 0xaa}, - {0x00, 0x75, 0x07, 0xaa}, - {0x00, 0x76, 0xe1, 0xaa}, - {0x00, 0x4c, 0x00, 0xaa}, - {0x00, 0x77, 0x00, 0xaa}, - {0x00, 0x3d, 0xc2, 0xaa}, - {0x00, 0x4b, 0x09, 0xaa}, - {0x00, 0xc9, 0x60, 0xaa}, - {0x00, 0x41, 0x38, 0xaa}, - {0xbf, 0xc0, 0x26, 0xcc}, - {0xbf, 0xc1, 0x02, 0xcc}, - {0xbf, 0xcc, 0x04, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, - {0xb3, 0x01, 0x45, 0xcc}, - {0x00, 0x77, 0x05, 0xaa}, - {}, -}; - -static const u8 ov7670_InitQVGA[][4] = { - {0xb3, 0x01, 0x05, 0xcc}, - {0x00, 0x00, 0x30, 0xdd}, - {0xb0, 0x03, 0x19, 0xcc}, - {0x00, 0x00, 0x10, 0xdd}, - {0xb0, 0x04, 0x02, 0xcc}, - {0x00, 0x00, 0x10, 0xdd}, - {0xb3, 0x00, 0x66, 0xcc}, - {0xb3, 0x00, 0x67, 0xcc}, - {0xb0, 0x16, 0x01, 0xcc}, - {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */ - {0xb3, 0x34, 0x01, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x02, 0x02, 0xcc}, - {0xb3, 0x03, 0x1f, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, - {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, - {0xbc, 0x00, 0xd1, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, - {0x00, 0x12, 0x80, 0xaa}, - {0x00, 0x00, 0x20, 0xdd}, - {0x00, 0x12, 0x00, 0xaa}, - {0x00, 0x11, 0x40, 0xaa}, - {0x00, 0x6b, 0x0a, 0xaa}, - {0x00, 0x3a, 0x04, 0xaa}, - {0x00, 0x40, 0xc0, 0xaa}, - {0x00, 0x8c, 0x00, 0xaa}, - {0x00, 0x7a, 0x29, 0xaa}, - {0x00, 0x7b, 0x0e, 0xaa}, - {0x00, 0x7c, 0x1a, 0xaa}, - {0x00, 0x7d, 0x31, 0xaa}, - {0x00, 0x7e, 0x53, 0xaa}, - {0x00, 0x7f, 0x60, 0xaa}, - {0x00, 0x80, 0x6b, 0xaa}, - {0x00, 0x81, 0x73, 0xaa}, - {0x00, 0x82, 0x7b, 0xaa}, - {0x00, 0x83, 0x82, 0xaa}, - {0x00, 0x84, 0x89, 0xaa}, - {0x00, 0x85, 0x96, 0xaa}, - {0x00, 0x86, 0xa1, 0xaa}, - {0x00, 0x87, 0xb7, 0xaa}, - {0x00, 0x88, 0xcc, 0xaa}, - {0x00, 0x89, 0xe1, 0xaa}, - {0x00, 0x13, 0xe0, 0xaa}, - {0x00, 0x00, 0x00, 0xaa}, - {0x00, 0x10, 0x00, 0xaa}, - {0x00, 0x0d, 0x40, 0xaa}, - {0x00, 0x14, 0x28, 0xaa}, - {0x00, 0xa5, 0x05, 0xaa}, - {0x00, 0xab, 0x07, 0xaa}, - {0x00, 0x24, 0x95, 0xaa}, - {0x00, 0x25, 0x33, 0xaa}, - {0x00, 0x26, 0xe3, 0xaa}, - {0x00, 0x9f, 0x88, 0xaa}, - {0x00, 0xa0, 0x78, 0xaa}, - {0x00, 0x55, 0x90, 0xaa}, - {0x00, 0xa1, 0x03, 0xaa}, - {0x00, 0xa6, 0xe0, 0xaa}, - {0x00, 0xa7, 0xd8, 0xaa}, - {0x00, 0xa8, 0xf0, 0xaa}, - {0x00, 0xa9, 0x90, 0xaa}, - {0x00, 0xaa, 0x14, 0xaa}, - {0x00, 0x13, 0xe5, 0xaa}, - {0x00, 0x0e, 0x61, 0xaa}, - {0x00, 0x0f, 0x4b, 0xaa}, - {0x00, 0x16, 0x02, 0xaa}, - {0x00, 0x1e, 0x07, 0xaa}, /* MVFP */ - {0x00, 0x21, 0x02, 0xaa}, - {0x00, 0x22, 0x91, 0xaa}, - {0x00, 0x29, 0x07, 0xaa}, - {0x00, 0x33, 0x0b, 0xaa}, - {0x00, 0x35, 0x0b, 0xaa}, - {0x00, 0x37, 0x1d, 0xaa}, - {0x00, 0x38, 0x71, 0xaa}, - {0x00, 0x39, 0x2a, 0xaa}, - {0x00, 0x3c, 0x78, 0xaa}, - {0x00, 0x4d, 0x40, 0xaa}, - {0x00, 0x4e, 0x20, 0xaa}, - {0x00, 0x74, 0x19, 0xaa}, - {0x00, 0x8d, 0x4f, 0xaa}, - {0x00, 0x8e, 0x00, 0xaa}, - {0x00, 0x8f, 0x00, 0xaa}, - {0x00, 0x90, 0x00, 0xaa}, - {0x00, 0x91, 0x00, 0xaa}, - {0x00, 0x96, 0x00, 0xaa}, - {0x00, 0x9a, 0x80, 0xaa}, - {0x00, 0xb0, 0x84, 0xaa}, - {0x00, 0xb1, 0x0c, 0xaa}, - {0x00, 0xb2, 0x0e, 0xaa}, - {0x00, 0xb3, 0x82, 0xaa}, - {0x00, 0xb8, 0x0a, 0xaa}, - {0x00, 0x43, 0x14, 0xaa}, - {0x00, 0x44, 0xf0, 0xaa}, - {0x00, 0x45, 0x45, 0xaa}, - {0x00, 0x46, 0x63, 0xaa}, - {0x00, 0x47, 0x2d, 0xaa}, - {0x00, 0x48, 0x46, 0xaa}, - {0x00, 0x59, 0x88, 0xaa}, - {0x00, 0x5a, 0xa0, 0xaa}, - {0x00, 0x5b, 0xc6, 0xaa}, - {0x00, 0x5c, 0x7d, 0xaa}, - {0x00, 0x5d, 0x5f, 0xaa}, - {0x00, 0x5e, 0x19, 0xaa}, - {0x00, 0x6c, 0x0a, 0xaa}, - {0x00, 0x6d, 0x55, 0xaa}, - {0x00, 0x6e, 0x11, 0xaa}, - {0x00, 0x6f, 0x9e, 0xaa}, - {0x00, 0x69, 0x00, 0xaa}, - {0x00, 0x6a, 0x40, 0xaa}, - {0x00, 0x01, 0x40, 0xaa}, - {0x00, 0x02, 0x40, 0xaa}, - {0x00, 0x13, 0xe7, 0xaa}, - {0x00, 0x5f, 0xf0, 0xaa}, - {0x00, 0x60, 0xf0, 0xaa}, - {0x00, 0x61, 0xf0, 0xaa}, - {0x00, 0x27, 0xa0, 0xaa}, - {0x00, 0x28, 0x80, 0xaa}, - {0x00, 0x2c, 0x90, 0xaa}, - {0x00, 0x4f, 0x66, 0xaa}, - {0x00, 0x50, 0x66, 0xaa}, - {0x00, 0x51, 0x00, 0xaa}, - {0x00, 0x52, 0x22, 0xaa}, - {0x00, 0x53, 0x5e, 0xaa}, - {0x00, 0x54, 0x80, 0xaa}, - {0x00, 0x58, 0x9e, 0xaa}, - {0x00, 0x41, 0x08, 0xaa}, - {0x00, 0x3f, 0x00, 0xaa}, - {0x00, 0x75, 0x85, 0xaa}, - {0x00, 0x76, 0xe1, 0xaa}, - {0x00, 0x4c, 0x00, 0xaa}, - {0x00, 0x77, 0x0a, 0xaa}, - {0x00, 0x3d, 0x88, 0xaa}, - {0x00, 0x4b, 0x09, 0xaa}, - {0x00, 0xc9, 0x60, 0xaa}, - {0x00, 0x41, 0x38, 0xaa}, - {0x00, 0x62, 0x30, 0xaa}, - {0x00, 0x63, 0x30, 0xaa}, - {0x00, 0x64, 0x08, 0xaa}, - {0x00, 0x94, 0x07, 0xaa}, - {0x00, 0x95, 0x0b, 0xaa}, - {0x00, 0x65, 0x00, 0xaa}, - {0x00, 0x66, 0x05, 0xaa}, - {0x00, 0x56, 0x50, 0xaa}, - {0x00, 0x34, 0x11, 0xaa}, - {0x00, 0xa4, 0x88, 0xaa}, - {0x00, 0x96, 0x00, 0xaa}, - {0x00, 0x97, 0x30, 0xaa}, - {0x00, 0x98, 0x20, 0xaa}, - {0x00, 0x99, 0x30, 0xaa}, - {0x00, 0x9a, 0x84, 0xaa}, - {0x00, 0x9b, 0x29, 0xaa}, - {0x00, 0x9c, 0x03, 0xaa}, - {0x00, 0x78, 0x04, 0xaa}, - {0x00, 0x79, 0x01, 0xaa}, - {0x00, 0xc8, 0xf0, 0xaa}, - {0x00, 0x79, 0x0f, 0xaa}, - {0x00, 0xc8, 0x00, 0xaa}, - {0x00, 0x79, 0x10, 0xaa}, - {0x00, 0xc8, 0x7e, 0xaa}, - {0x00, 0x79, 0x0a, 0xaa}, - {0x00, 0xc8, 0x80, 0xaa}, - {0x00, 0x79, 0x0b, 0xaa}, - {0x00, 0xc8, 0x01, 0xaa}, - {0x00, 0x79, 0x0c, 0xaa}, - {0x00, 0xc8, 0x0f, 0xaa}, - {0x00, 0x79, 0x0d, 0xaa}, - {0x00, 0xc8, 0x20, 0xaa}, - {0x00, 0x79, 0x09, 0xaa}, - {0x00, 0xc8, 0x80, 0xaa}, - {0x00, 0x79, 0x02, 0xaa}, - {0x00, 0xc8, 0xc0, 0xaa}, - {0x00, 0x79, 0x03, 0xaa}, - {0x00, 0xc8, 0x40, 0xaa}, - {0x00, 0x79, 0x05, 0xaa}, - {0x00, 0xc8, 0x30, 0xaa}, - {0x00, 0x79, 0x26, 0xaa}, - {0x00, 0x11, 0x40, 0xaa}, - {0x00, 0x3a, 0x04, 0xaa}, - {0x00, 0x12, 0x00, 0xaa}, - {0x00, 0x40, 0xc0, 0xaa}, - {0x00, 0x8c, 0x00, 0xaa}, - {0x00, 0x17, 0x14, 0xaa}, - {0x00, 0x18, 0x02, 0xaa}, - {0x00, 0x32, 0x92, 0xaa}, - {0x00, 0x19, 0x02, 0xaa}, - {0x00, 0x1a, 0x7a, 0xaa}, - {0x00, 0x03, 0x0a, 0xaa}, - {0x00, 0x0c, 0x00, 0xaa}, - {0x00, 0x3e, 0x00, 0xaa}, - {0x00, 0x70, 0x3a, 0xaa}, - {0x00, 0x71, 0x35, 0xaa}, - {0x00, 0x72, 0x11, 0xaa}, - {0x00, 0x73, 0xf0, 0xaa}, - {0x00, 0xa2, 0x02, 0xaa}, - {0x00, 0xb1, 0x00, 0xaa}, - {0x00, 0xb1, 0x0c, 0xaa}, - {0x00, 0x1e, 0x37, 0xaa}, /* MVFP */ - {0x00, 0xaa, 0x14, 0xaa}, - {0x00, 0x24, 0x80, 0xaa}, - {0x00, 0x25, 0x74, 0xaa}, - {0x00, 0x26, 0xd3, 0xaa}, - {0x00, 0x0d, 0x00, 0xaa}, - {0x00, 0x14, 0x18, 0xaa}, - {0x00, 0x9d, 0x99, 0xaa}, - {0x00, 0x9e, 0x7f, 0xaa}, - {0x00, 0x64, 0x08, 0xaa}, - {0x00, 0x94, 0x07, 0xaa}, - {0x00, 0x95, 0x06, 0xaa}, - {0x00, 0x66, 0x05, 0xaa}, - {0x00, 0x41, 0x08, 0xaa}, - {0x00, 0x3f, 0x00, 0xaa}, - {0x00, 0x75, 0x07, 0xaa}, - {0x00, 0x76, 0xe1, 0xaa}, - {0x00, 0x4c, 0x00, 0xaa}, - {0x00, 0x77, 0x00, 0xaa}, - {0x00, 0x3d, 0xc2, 0xaa}, - {0x00, 0x4b, 0x09, 0xaa}, - {0x00, 0xc9, 0x60, 0xaa}, - {0x00, 0x41, 0x38, 0xaa}, - {0xbc, 0x02, 0x18, 0xcc}, - {0xbc, 0x03, 0x50, 0xcc}, - {0xbc, 0x04, 0x18, 0xcc}, - {0xbc, 0x05, 0x00, 0xcc}, - {0xbc, 0x06, 0x00, 0xcc}, - {0xbc, 0x08, 0x30, 0xcc}, - {0xbc, 0x09, 0x40, 0xcc}, - {0xbc, 0x0a, 0x10, 0xcc}, - {0xbc, 0x0b, 0x00, 0xcc}, - {0xbc, 0x0c, 0x00, 0xcc}, - {0xbf, 0xc0, 0x26, 0xcc}, - {0xbf, 0xc1, 0x02, 0xcc}, - {0xbf, 0xcc, 0x04, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, - {0xb3, 0x01, 0x45, 0xcc}, - {0x00, 0x77, 0x05, 0xaa}, - {}, -}; - -/* PO1200 - values from usbvm326.inf and ms-win trace */ -static const u8 po1200_gamma[17] = { - 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, - 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff -}; -static const u8 po1200_matrix[9] = { - 0x60, 0xf9, 0xe5, 0xe7, 0x50, 0x05, 0xf3, 0xe6, 0x5e -}; -static const u8 po1200_initVGA_data[][4] = { - {0xb0, 0x03, 0x19, 0xcc}, /* reset? */ - {0xb0, 0x03, 0x19, 0xcc}, -/* {0x00, 0x00, 0x33, 0xdd}, */ - {0xb0, 0x04, 0x02, 0xcc}, - {0xb0, 0x02, 0x02, 0xcc}, - {0xb3, 0x5d, 0x00, 0xcc}, - {0xb3, 0x01, 0x01, 0xcc}, - {0xb3, 0x00, 0x64, 0xcc}, - {0xb3, 0x00, 0x65, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x00, 0x67, 0xcc}, - {0xb3, 0x02, 0xb2, 0xcc}, - {0xb3, 0x03, 0x18, 0xcc}, - {0xb3, 0x04, 0x15, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x02, 0xcc}, - {0xb3, 0x23, 0x58, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x03, 0xcc}, - {0xb3, 0x17, 0x1f, 0xcc}, - {0xbc, 0x00, 0x71, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, - {0xb0, 0x54, 0x13, 0xcc}, - {0xb3, 0x00, 0x67, 0xcc}, - {0xb3, 0x34, 0x01, 0xcc}, - {0xb3, 0x35, 0xdc, 0xcc}, /* i2c add: 5c */ - {0x00, 0x03, 0x00, 0xaa}, - {0x00, 0x12, 0x05, 0xaa}, - {0x00, 0x13, 0x02, 0xaa}, - {0x00, 0x1e, 0xc6, 0xaa}, /* h/v flip */ - {0x00, 0x21, 0x00, 0xaa}, - {0x00, 0x25, 0x02, 0xaa}, - {0x00, 0x3c, 0x4f, 0xaa}, - {0x00, 0x3f, 0xe0, 0xaa}, - {0x00, 0x42, 0xff, 0xaa}, - {0x00, 0x45, 0x34, 0xaa}, - {0x00, 0x55, 0xfe, 0xaa}, - {0x00, 0x59, 0xd3, 0xaa}, - {0x00, 0x5e, 0x04, 0xaa}, - {0x00, 0x61, 0xb8, 0xaa}, /* sharpness */ - {0x00, 0x62, 0x02, 0xaa}, - {0x00, 0xa7, 0x31, 0xaa}, - {0x00, 0xa9, 0x66, 0xaa}, - {0x00, 0xb0, 0x00, 0xaa}, - {0x00, 0xb1, 0x00, 0xaa}, - {0x00, 0xb3, 0x11, 0xaa}, - {0x00, 0xb6, 0x26, 0xaa}, - {0x00, 0xb7, 0x20, 0xaa}, - {0x00, 0xba, 0x04, 0xaa}, - {0x00, 0x88, 0x42, 0xaa}, - {0x00, 0x89, 0x9a, 0xaa}, - {0x00, 0x8a, 0x88, 0xaa}, - {0x00, 0x8b, 0x8e, 0xaa}, - {0x00, 0x8c, 0x3e, 0xaa}, - {0x00, 0x8d, 0x90, 0xaa}, - {0x00, 0x8e, 0x87, 0xaa}, - {0x00, 0x8f, 0x96, 0xaa}, - {0x00, 0x90, 0x3d, 0xaa}, - {0x00, 0x64, 0x00, 0xaa}, - {0x00, 0x65, 0x10, 0xaa}, - {0x00, 0x66, 0x20, 0xaa}, - {0x00, 0x67, 0x2b, 0xaa}, - {0x00, 0x68, 0x36, 0xaa}, - {0x00, 0x69, 0x49, 0xaa}, - {0x00, 0x6a, 0x5a, 0xaa}, - {0x00, 0x6b, 0x7f, 0xaa}, - {0x00, 0x6c, 0x9b, 0xaa}, - {0x00, 0x6d, 0xba, 0xaa}, - {0x00, 0x6e, 0xd4, 0xaa}, - {0x00, 0x6f, 0xea, 0xaa}, - {0x00, 0x70, 0x00, 0xaa}, - {0x00, 0x71, 0x10, 0xaa}, - {0x00, 0x72, 0x20, 0xaa}, - {0x00, 0x73, 0x2b, 0xaa}, - {0x00, 0x74, 0x36, 0xaa}, - {0x00, 0x75, 0x49, 0xaa}, - {0x00, 0x76, 0x5a, 0xaa}, - {0x00, 0x77, 0x7f, 0xaa}, - {0x00, 0x78, 0x9b, 0xaa}, - {0x00, 0x79, 0xba, 0xaa}, - {0x00, 0x7a, 0xd4, 0xaa}, - {0x00, 0x7b, 0xea, 0xaa}, - {0x00, 0x7c, 0x00, 0xaa}, - {0x00, 0x7d, 0x10, 0xaa}, - {0x00, 0x7e, 0x20, 0xaa}, - {0x00, 0x7f, 0x2b, 0xaa}, - {0x00, 0x80, 0x36, 0xaa}, - {0x00, 0x81, 0x49, 0xaa}, - {0x00, 0x82, 0x5a, 0xaa}, - {0x00, 0x83, 0x7f, 0xaa}, - {0x00, 0x84, 0x9b, 0xaa}, - {0x00, 0x85, 0xba, 0xaa}, - {0x00, 0x86, 0xd4, 0xaa}, - {0x00, 0x87, 0xea, 0xaa}, - {0x00, 0x57, 0x2a, 0xaa}, - {0x00, 0x03, 0x01, 0xaa}, - {0x00, 0x04, 0x10, 0xaa}, - {0x00, 0x05, 0x10, 0xaa}, - {0x00, 0x06, 0x10, 0xaa}, - {0x00, 0x07, 0x10, 0xaa}, - {0x00, 0x08, 0x13, 0xaa}, - {0x00, 0x0a, 0x00, 0xaa}, - {0x00, 0x0b, 0x10, 0xaa}, - {0x00, 0x0c, 0x20, 0xaa}, - {0x00, 0x0d, 0x18, 0xaa}, - {0x00, 0x22, 0x01, 0xaa}, - {0x00, 0x23, 0x60, 0xaa}, - {0x00, 0x25, 0x08, 0xaa}, - {0x00, 0x26, 0x82, 0xaa}, - {0x00, 0x2e, 0x0f, 0xaa}, - {0x00, 0x2f, 0x1e, 0xaa}, - {0x00, 0x30, 0x2d, 0xaa}, - {0x00, 0x31, 0x3c, 0xaa}, - {0x00, 0x32, 0x4b, 0xaa}, - {0x00, 0x33, 0x5a, 0xaa}, - {0x00, 0x34, 0x69, 0xaa}, - {0x00, 0x35, 0x78, 0xaa}, - {0x00, 0x36, 0x87, 0xaa}, - {0x00, 0x37, 0x96, 0xaa}, - {0x00, 0x38, 0xa5, 0xaa}, - {0x00, 0x39, 0xb4, 0xaa}, - {0x00, 0x3a, 0xc3, 0xaa}, - {0x00, 0x3b, 0xd2, 0xaa}, - {0x00, 0x3c, 0xe1, 0xaa}, - {0x00, 0x3e, 0xff, 0xaa}, - {0x00, 0x3f, 0xff, 0xaa}, - {0x00, 0x40, 0xff, 0xaa}, - {0x00, 0x41, 0xff, 0xaa}, - {0x00, 0x42, 0xff, 0xaa}, - {0x00, 0x43, 0xff, 0xaa}, - {0x00, 0x03, 0x00, 0xaa}, - {0x00, 0x03, 0x00, 0xaa}, - {0x00, 0x20, 0xc4, 0xaa}, - {0x00, 0x13, 0x03, 0xaa}, - {0x00, 0x3c, 0x50, 0xaa}, - {0x00, 0x61, 0x6a, 0xaa}, /* sharpness? */ - {0x00, 0x51, 0x5b, 0xaa}, - {0x00, 0x52, 0x91, 0xaa}, - {0x00, 0x53, 0x4c, 0xaa}, - {0x00, 0x54, 0x50, 0xaa}, - {0x00, 0x56, 0x02, 0xaa}, - {0xb6, 0x00, 0x00, 0xcc}, - {0xb6, 0x03, 0x03, 0xcc}, - {0xb6, 0x02, 0x20, 0xcc}, - {0xb6, 0x05, 0x02, 0xcc}, - {0xb6, 0x04, 0x58, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, - {0xb6, 0x13, 0x21, 0xcc}, - {0xb6, 0x18, 0x03, 0xcc}, - {0xb6, 0x17, 0xa9, 0xcc}, - {0xb6, 0x16, 0x80, 0xcc}, - {0xb6, 0x22, 0x12, 0xcc}, - {0xb6, 0x23, 0x0b, 0xcc}, - {0xbf, 0xc0, 0x39, 0xcc}, - {0xbf, 0xc1, 0x04, 0xcc}, - {0xbf, 0xcc, 0x00, 0xcc}, - {0xb8, 0x06, 0x20, 0xcc}, - {0xb8, 0x07, 0x03, 0xcc}, - {0xb8, 0x08, 0x58, 0xcc}, - {0xb8, 0x09, 0x02, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, - {0x00, 0x03, 0x00, 0xaa}, - {0x00, 0xd9, 0x0f, 0xaa}, - {0x00, 0xda, 0xaa, 0xaa}, - {0x00, 0xd9, 0x10, 0xaa}, - {0x00, 0xda, 0xaa, 0xaa}, - {0x00, 0xd9, 0x11, 0xaa}, - {0x00, 0xda, 0x00, 0xaa}, - {0x00, 0xd9, 0x12, 0xaa}, - {0x00, 0xda, 0xff, 0xaa}, - {0x00, 0xd9, 0x13, 0xaa}, - {0x00, 0xda, 0xff, 0xaa}, - {0x00, 0xe8, 0x11, 0xaa}, - {0x00, 0xe9, 0x12, 0xaa}, - {0x00, 0xea, 0x5c, 0xaa}, - {0x00, 0xeb, 0xff, 0xaa}, - {0x00, 0xd8, 0x80, 0xaa}, - {0x00, 0xe6, 0x02, 0xaa}, - {0x00, 0xd6, 0x40, 0xaa}, - {0x00, 0xe3, 0x05, 0xaa}, - {0x00, 0xe0, 0x40, 0xaa}, - {0x00, 0xde, 0x03, 0xaa}, - {0x00, 0xdf, 0x03, 0xaa}, - {0x00, 0xdb, 0x02, 0xaa}, - {0x00, 0xdc, 0x00, 0xaa}, - {0x00, 0xdd, 0x03, 0xaa}, - {0x00, 0xe1, 0x08, 0xaa}, - {0x00, 0xe2, 0x01, 0xaa}, - {0x00, 0xd6, 0x40, 0xaa}, - {0x00, 0xe4, 0x40, 0xaa}, - {0x00, 0xa8, 0x8f, 0xaa}, - {0x00, 0xb4, 0x16, 0xaa}, - {0xb0, 0x02, 0x06, 0xcc}, - {0xb0, 0x18, 0x06, 0xcc}, - {0xb0, 0x19, 0x06, 0xcc}, - {0xb3, 0x5d, 0x18, 0xcc}, - {0xb3, 0x05, 0x00, 0xcc}, - {0xb3, 0x06, 0x00, 0xcc}, - {0x00, 0xb4, 0x0e, 0xaa}, - {0x00, 0xb5, 0x49, 0xaa}, - {0x00, 0xb6, 0x1c, 0xaa}, - {0x00, 0xb7, 0x96, 0xaa}, -/* end of usbvm326.inf - start of ms-win trace */ - {0xb6, 0x12, 0xf8, 0xcc}, - {0xb6, 0x13, 0x3d, 0xcc}, -/*read b306*/ - {0x00, 0x03, 0x00, 0xaa}, - {0x00, 0x1a, 0x09, 0xaa}, - {0x00, 0x1b, 0x8a, 0xaa}, -/*read b827*/ - {0xb8, 0x27, 0x00, 0xcc}, - {0xb8, 0x26, 0x60, 0xcc}, - {0xb8, 0x26, 0x60, 0xcc}, -/*gamma - to do?*/ - {0x00, 0x03, 0x00, 0xaa}, - {0x00, 0xae, 0x84, 0xaa}, -/*gamma again*/ - {0x00, 0x03, 0x00, 0xaa}, - {0x00, 0x96, 0xa0, 0xaa}, -/*matrix*/ - {0x00, 0x03, 0x00, 0xaa}, - {0x00, 0x91, 0x35, 0xaa}, - {0x00, 0x92, 0x22, 0xaa}, -/*gamma*/ - {0x00, 0x03, 0x00, 0xaa}, - {0x00, 0x95, 0x85, 0xaa}, -/*matrix*/ - {0x00, 0x03, 0x00, 0xaa}, - {0x00, 0x4d, 0x20, 0xaa}, - {0xb8, 0x22, 0x40, 0xcc}, - {0xb8, 0x23, 0x40, 0xcc}, - {0xb8, 0x24, 0x40, 0xcc}, - {0xb8, 0x81, 0x09, 0xcc}, - {0x00, 0x00, 0x64, 0xdd}, - {0x00, 0x03, 0x01, 0xaa}, -/*read 46*/ - {0x00, 0x46, 0x3c, 0xaa}, - {0x00, 0x03, 0x00, 0xaa}, - {0x00, 0x16, 0x40, 0xaa}, - {0x00, 0x17, 0x40, 0xaa}, - {0x00, 0x18, 0x40, 0xaa}, - {0x00, 0x19, 0x41, 0xaa}, - {0x00, 0x03, 0x01, 0xaa}, - {0x00, 0x46, 0x3c, 0xaa}, - {0x00, 0x00, 0x18, 0xdd}, -/*read bfff*/ - {0x00, 0x03, 0x00, 0xaa}, - {0x00, 0xb4, 0x1c, 0xaa}, - {0x00, 0xb5, 0x92, 0xaa}, - {0x00, 0xb6, 0x39, 0xaa}, - {0x00, 0xb7, 0x24, 0xaa}, -/*write 89 0400 1415*/ - {} -}; - -static const u8 poxxxx_init_common[][4] = { - {0xb3, 0x00, 0x04, 0xcc}, - {0x00, 0x00, 0x10, 0xdd}, - {0xb3, 0x00, 0x64, 0xcc}, - {0x00, 0x00, 0x10, 0xdd}, - {0xb3, 0x00, 0x65, 0xcc}, - {0x00, 0x00, 0x10, 0xdd}, - {0xb3, 0x00, 0x67, 0xcc}, - {0xb0, 0x03, 0x09, 0xcc}, - {0xb3, 0x05, 0x00, 0xcc}, - {0xb3, 0x06, 0x00, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x34, 0x01, 0xcc}, - {0xb3, 0x35, 0xf6, 0xcc}, /* i2c add: 76 */ - {0xb3, 0x02, 0xb0, 0xcc}, - {0xb3, 0x03, 0x18, 0xcc}, - {0xb3, 0x04, 0x15, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x04, 0xcc}, /* sensor height = 1024 */ - {0xb3, 0x23, 0x00, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x04, 0xcc}, /* sensor width = 1280 */ - {0xb3, 0x17, 0xff, 0xcc}, - {0xb3, 0x2c, 0x03, 0xcc}, - {0xb3, 0x2d, 0x56, 0xcc}, - {0xb3, 0x2e, 0x02, 0xcc}, - {0xb3, 0x2f, 0x0a, 0xcc}, - {0xb3, 0x40, 0x00, 0xcc}, - {0xb3, 0x41, 0x34, 0xcc}, - {0xb3, 0x42, 0x01, 0xcc}, - {0xb3, 0x43, 0xe0, 0xcc}, - {0xbc, 0x00, 0x71, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, - {0xb3, 0x4d, 0x00, 0xcc}, - {0x00, 0x0b, 0x2a, 0xaa}, - {0x00, 0x0e, 0x03, 0xaa}, - {0x00, 0x0f, 0xea, 0xaa}, - {0x00, 0x12, 0x08, 0xaa}, - {0x00, 0x1e, 0x06, 0xaa}, - {0x00, 0x21, 0x00, 0xaa}, - {0x00, 0x31, 0x1f, 0xaa}, - {0x00, 0x33, 0x38, 0xaa}, - {0x00, 0x36, 0xc0, 0xaa}, - {0x00, 0x37, 0xc8, 0xaa}, - {0x00, 0x3b, 0x36, 0xaa}, - {0x00, 0x4b, 0xfe, 0xaa}, - {0x00, 0x4d, 0x2e, 0xaa}, - {0x00, 0x51, 0x1c, 0xaa}, - {0x00, 0x52, 0x01, 0xaa}, - {0x00, 0x55, 0x0a, 0xaa}, - {0x00, 0x56, 0x0a, 0xaa}, - {0x00, 0x57, 0x07, 0xaa}, - {0x00, 0x58, 0x07, 0xaa}, - {0x00, 0x59, 0x04, 0xaa}, - {0x00, 0x70, 0x68, 0xaa}, - {0x00, 0x71, 0x04, 0xaa}, - {0x00, 0x72, 0x10, 0xaa}, - {0x00, 0x80, 0x71, 0xaa}, - {0x00, 0x81, 0x08, 0xaa}, - {0x00, 0x82, 0x00, 0xaa}, - {0x00, 0x83, 0x55, 0xaa}, - {0x00, 0x84, 0x06, 0xaa}, - {0x00, 0x85, 0x06, 0xaa}, - {0x00, 0x8b, 0x25, 0xaa}, - {0x00, 0x8c, 0x00, 0xaa}, - {0x00, 0x8d, 0x86, 0xaa}, - {0x00, 0x8e, 0x82, 0xaa}, - {0x00, 0x8f, 0x2d, 0xaa}, - {0x00, 0x90, 0x8b, 0xaa}, - {0x00, 0x91, 0x81, 0xaa}, - {0x00, 0x92, 0x81, 0xaa}, - {0x00, 0x93, 0x23, 0xaa}, - {0x00, 0xa3, 0x2a, 0xaa}, - {0x00, 0xa4, 0x03, 0xaa}, - {0x00, 0xa5, 0xea, 0xaa}, - {0x00, 0xb0, 0x68, 0xaa}, - {0x00, 0xbc, 0x04, 0xaa}, - {0x00, 0xbe, 0x3b, 0xaa}, - {0x00, 0x4e, 0x40, 0xaa}, - {0x00, 0x06, 0x04, 0xaa}, - {0x00, 0x07, 0x03, 0xaa}, - {0x00, 0xcd, 0x18, 0xaa}, - {0x00, 0x28, 0x03, 0xaa}, - {0x00, 0x29, 0xef, 0xaa}, -/* reinit on alt 2 (qvga) or alt7 (vga) */ - {0xb3, 0x05, 0x00, 0xcc}, - {0xb3, 0x06, 0x00, 0xcc}, - {0xb8, 0x00, 0x01, 0xcc}, - - {0x00, 0x1d, 0x85, 0xaa}, - {0x00, 0x1e, 0xc6, 0xaa}, - {0x00, 0x00, 0x40, 0xdd}, - {0x00, 0x1d, 0x05, 0xaa}, - {} -}; -static const u8 poxxxx_gamma[][4] = { - {0x00, 0xd6, 0x22, 0xaa}, /* gamma 0 */ - {0x00, 0x73, 0x00, 0xaa}, - {0x00, 0x74, 0x0a, 0xaa}, - {0x00, 0x75, 0x16, 0xaa}, - {0x00, 0x76, 0x25, 0xaa}, - {0x00, 0x77, 0x34, 0xaa}, - {0x00, 0x78, 0x49, 0xaa}, - {0x00, 0x79, 0x5a, 0xaa}, - {0x00, 0x7a, 0x7f, 0xaa}, - {0x00, 0x7b, 0x9b, 0xaa}, - {0x00, 0x7c, 0xba, 0xaa}, - {0x00, 0x7d, 0xd4, 0xaa}, - {0x00, 0x7e, 0xea, 0xaa}, - - {0x00, 0xd6, 0x62, 0xaa}, /* gamma 1 */ - {0x00, 0x73, 0x00, 0xaa}, - {0x00, 0x74, 0x0a, 0xaa}, - {0x00, 0x75, 0x16, 0xaa}, - {0x00, 0x76, 0x25, 0xaa}, - {0x00, 0x77, 0x34, 0xaa}, - {0x00, 0x78, 0x49, 0xaa}, - {0x00, 0x79, 0x5a, 0xaa}, - {0x00, 0x7a, 0x7f, 0xaa}, - {0x00, 0x7b, 0x9b, 0xaa}, - {0x00, 0x7c, 0xba, 0xaa}, - {0x00, 0x7d, 0xd4, 0xaa}, - {0x00, 0x7e, 0xea, 0xaa}, - - {0x00, 0xd6, 0xa2, 0xaa}, /* gamma 2 */ - {0x00, 0x73, 0x00, 0xaa}, - {0x00, 0x74, 0x0a, 0xaa}, - {0x00, 0x75, 0x16, 0xaa}, - {0x00, 0x76, 0x25, 0xaa}, - {0x00, 0x77, 0x34, 0xaa}, - {0x00, 0x78, 0x49, 0xaa}, - {0x00, 0x79, 0x5a, 0xaa}, - {0x00, 0x7a, 0x7f, 0xaa}, - {0x00, 0x7b, 0x9b, 0xaa}, - {0x00, 0x7c, 0xba, 0xaa}, - {0x00, 0x7d, 0xd4, 0xaa}, - {0x00, 0x7e, 0xea, 0xaa}, - {} -}; -static const u8 poxxxx_init_start_3[][4] = { - {0x00, 0xb8, 0x28, 0xaa}, - {0x00, 0xb9, 0x1e, 0xaa}, - {0x00, 0xb6, 0x14, 0xaa}, - {0x00, 0xb7, 0x0f, 0xaa}, - {0x00, 0x5c, 0x10, 0xaa}, - {0x00, 0x5d, 0x18, 0xaa}, - {0x00, 0x5e, 0x24, 0xaa}, - {0x00, 0x5f, 0x24, 0xaa}, - {0x00, 0x86, 0x1a, 0xaa}, - {0x00, 0x60, 0x00, 0xaa}, - {0x00, 0x61, 0x1b, 0xaa}, - {0x00, 0x62, 0x30, 0xaa}, - {0x00, 0x63, 0x40, 0xaa}, - {0x00, 0x87, 0x1a, 0xaa}, - {0x00, 0x64, 0x00, 0xaa}, - {0x00, 0x65, 0x08, 0xaa}, - {0x00, 0x66, 0x10, 0xaa}, - {0x00, 0x67, 0x20, 0xaa}, - {0x00, 0x88, 0x10, 0xaa}, - {0x00, 0x68, 0x00, 0xaa}, - {0x00, 0x69, 0x08, 0xaa}, - {0x00, 0x6a, 0x0f, 0xaa}, - {0x00, 0x6b, 0x0f, 0xaa}, - {0x00, 0x89, 0x07, 0xaa}, - {0x00, 0xd5, 0x4c, 0xaa}, - {0x00, 0x0a, 0x00, 0xaa}, - {0x00, 0x0b, 0x2a, 0xaa}, - {0x00, 0x0e, 0x03, 0xaa}, - {0x00, 0x0f, 0xea, 0xaa}, - {0x00, 0xa2, 0x00, 0xaa}, - {0x00, 0xa3, 0x2a, 0xaa}, - {0x00, 0xa4, 0x03, 0xaa}, - {0x00, 0xa5, 0xea, 0xaa}, - {} -}; -static const u8 poxxxx_initVGA[][4] = { - {0x00, 0x20, 0x11, 0xaa}, - {0x00, 0x33, 0x38, 0xaa}, - {0x00, 0xbb, 0x0d, 0xaa}, - {0xb3, 0x22, 0x01, 0xcc}, /* change to 640x480 */ - {0xb3, 0x23, 0xe0, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, - {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x02, 0xb0, 0xcc}, - {0xb3, 0x06, 0x00, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, - {0x00, 0x04, 0x06, 0xaa}, - {0x00, 0x05, 0x3f, 0xaa}, - {0x00, 0x04, 0x00, 0xdd}, /* delay 1s */ - {} -}; -static const u8 poxxxx_initQVGA[][4] = { - {0x00, 0x20, 0x33, 0xaa}, - {0x00, 0x33, 0x38, 0xaa}, - {0x00, 0xbb, 0x0d, 0xaa}, - {0xb3, 0x22, 0x00, 0xcc}, /* change to 320x240 */ - {0xb3, 0x23, 0xf0, 0xcc}, - {0xb3, 0x16, 0x01, 0xcc}, - {0xb3, 0x17, 0x3f, 0xcc}, - {0xb3, 0x02, 0xb0, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, - {0xb3, 0x5c, 0x00, 0xcc}, - {0x00, 0x04, 0x06, 0xaa}, - {0x00, 0x05, 0x3f, 0xaa}, - {0x00, 0x04, 0x00, 0xdd}, /* delay 1s */ - {} -}; -static const u8 poxxxx_init_end_1[][4] = { - {0x00, 0x47, 0x25, 0xaa}, - {0x00, 0x48, 0x80, 0xaa}, - {0x00, 0x49, 0x1f, 0xaa}, - {0x00, 0x4a, 0x40, 0xaa}, - {0x00, 0x44, 0x40, 0xaa}, - {0x00, 0xab, 0x4a, 0xaa}, - {0x00, 0xb1, 0x00, 0xaa}, - {0x00, 0xb2, 0x04, 0xaa}, - {0x00, 0xb3, 0x08, 0xaa}, - {0x00, 0xb4, 0x0b, 0xaa}, - {0x00, 0xb5, 0x0d, 0xaa}, - {} -}; -static const u8 poxxxx_init_end_2[][4] = { - {0x00, 0x1d, 0x85, 0xaa}, - {0x00, 0x1e, 0x06, 0xaa}, - {0x00, 0x1d, 0x05, 0xaa}, - {} -}; - -struct sensor_info { - s8 sensorId; - u8 I2cAdd; - u8 IdAdd; - u16 VpId; - u8 m1; - u8 m2; - u8 op; -}; - -/* probe values */ -static const struct sensor_info vc0321_probe_data[] = { -/* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */ -/* 0 OV9640 */ - {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, -/* 1 ICM108T (may respond on IdAdd == 0x83 - tested in vc032x_probe_sensor) */ - {-1, 0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01}, -/* 2 PO2130 (may detect PO3130NC - tested in vc032x_probe_sensor)*/ - {-1, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01}, -/* 3 MI1310 */ - {-1, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01}, -/* 4 MI360 - tested in vc032x_probe_sensor */ -/* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */ -/* 5 7131R */ - {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01}, -/* 6 OV7649 */ - {-1, 0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05}, -/* 7 PAS302BCW */ - {-1, 0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05}, -/* 8 OV7660 */ - {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05}, -/* 9 PO3130NC - (tested in vc032x_probe_sensor) */ -/* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, */ -/* 10 PO1030KC */ - {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, -/* 11 MI1310_SOC */ - {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01}, -/* 12 OV9650 */ - {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, -/* 13 S5K532 */ - {-1, 0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01}, -/* 14 MI360_SOC - ??? */ -/* 15 PO1200N */ - {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01}, -/* 16 PO3030K */ - {-1, 0x80 | 0x18, 0x00, 0x0000, 0x24, 0x25, 0x01}, -/* 17 PO2030 */ - {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, -/* ?? */ - {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01}, - {SENSOR_MI1320, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01}, -}; -static const struct sensor_info vc0323_probe_data[] = { -/* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */ -/* 0 OV9640 */ - {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, -/* 1 ICM108T (may respond on IdAdd == 0x83 - tested in vc032x_probe_sensor) */ - {-1, 0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01}, -/* 2 PO2130 (may detect PO3130NC - tested in vc032x_probe_sensor)*/ - {-1, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01}, -/* 3 MI1310 */ - {-1, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01}, -/* 4 MI360 - tested in vc032x_probe_sensor */ -/* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */ -/* 5 7131R */ - {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01}, -/* 6 OV7649 */ - {-1, 0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05}, -/* 7 PAS302BCW */ - {-1, 0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05}, -/* 8 OV7660 */ - {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05}, -/* 9 PO3130NC - (tested in vc032x_probe_sensor) */ -/* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, */ -/* 10 PO1030KC */ - {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, -/* 11 MI1310_SOC */ - {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01}, -/* 12 OV9650 */ - {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, -/* 13 S5K532 */ - {-1, 0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01}, -/* 14 MI360_SOC - ??? */ -/* 15 PO1200N */ - {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01}, -/* 16 ?? */ - {-1, 0x80 | 0x2d, 0x00, 0x0000, 0x65, 0x67, 0x01}, -/* 17 PO2030 */ - {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, -/* ?? */ - {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01}, - {SENSOR_MI1320_SOC, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x67, 0x01}, -/*fixme: not in the ms-win probe - may be found before? */ - {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05}, -}; - -/* read 'len' bytes in gspca_dev->usb_buf */ -static void reg_r_i(struct gspca_dev *gspca_dev, - u16 req, - u16 index, - u16 len) -{ - int ret; - - if (gspca_dev->usb_err < 0) - return; - ret = usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 1, /* value */ - index, gspca_dev->usb_buf, len, - 500); - if (ret < 0) { - pr_err("reg_r err %d\n", ret); - gspca_dev->usb_err = ret; - } -} -static void reg_r(struct gspca_dev *gspca_dev, - u16 req, - u16 index, - u16 len) -{ - reg_r_i(gspca_dev, req, index, len); -#ifdef GSPCA_DEBUG - if (gspca_dev->usb_err < 0) - return; - if (len == 1) - PDEBUG(D_USBI, "GET %02x 0001 %04x %02x", req, index, - gspca_dev->usb_buf[0]); - else - PDEBUG(D_USBI, "GET %02x 0001 %04x %*ph", - req, index, 3, gspca_dev->usb_buf); -#endif -} - -static void reg_w_i(struct gspca_dev *gspca_dev, - u16 req, - u16 value, - u16 index) -{ - int ret; - - if (gspca_dev->usb_err < 0) - return; - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, NULL, 0, - 500); - if (ret < 0) { - pr_err("reg_w err %d\n", ret); - gspca_dev->usb_err = ret; - } -} -static void reg_w(struct gspca_dev *gspca_dev, - u16 req, - u16 value, - u16 index) -{ -#ifdef GSPCA_DEBUG - if (gspca_dev->usb_err < 0) - return; - PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index); -#endif - reg_w_i(gspca_dev, req, value, index); -} - -static u16 read_sensor_register(struct gspca_dev *gspca_dev, - u16 address) -{ - u8 ldata, mdata, hdata; - int retry = 50; - - reg_r(gspca_dev, 0xa1, 0xb33f, 1); - if (!(gspca_dev->usb_buf[0] & 0x02)) { - pr_err("I2c Bus Busy Wait %02x\n", gspca_dev->usb_buf[0]); - return 0; - } - reg_w(gspca_dev, 0xa0, address, 0xb33a); - reg_w(gspca_dev, 0xa0, 0x02, 0xb339); - - do { - reg_r(gspca_dev, 0xa1, 0xb33b, 1); - if (gspca_dev->usb_buf[0] == 0x00) - break; - msleep(40); - } while (--retry >= 0); - - reg_r(gspca_dev, 0xa1, 0xb33e, 1); - ldata = gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0xa1, 0xb33d, 1); - mdata = gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0xa1, 0xb33c, 1); - hdata = gspca_dev->usb_buf[0]; - if (hdata != 0 && mdata != 0 && ldata != 0) - PDEBUG(D_PROBE, "Read Sensor %02x%02x %02x", - hdata, mdata, ldata); - reg_r(gspca_dev, 0xa1, 0xb334, 1); - if (gspca_dev->usb_buf[0] == 0x02) - return (hdata << 8) + mdata; - return hdata; -} - -static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i, n; - u16 value; - const struct sensor_info *ptsensor_info; - -/*fixme: should also check the other sensor (back mi1320_soc, front mc501cb)*/ - if (sd->flags & FL_SAMSUNG) { - reg_w(gspca_dev, 0xa0, 0x01, 0xb301); - reg_w(gspca_dev, 0x89, 0xf0ff, 0xffff); - /* select the back sensor */ - } - - reg_r(gspca_dev, 0xa1, 0xbfcf, 1); - PDEBUG(D_PROBE, "vc032%d check sensor header %02x", - sd->bridge == BRIDGE_VC0321 ? 1 : 3, gspca_dev->usb_buf[0]); - if (sd->bridge == BRIDGE_VC0321) { - ptsensor_info = vc0321_probe_data; - n = ARRAY_SIZE(vc0321_probe_data); - } else { - ptsensor_info = vc0323_probe_data; - n = ARRAY_SIZE(vc0323_probe_data); - } - for (i = 0; i < n; i++) { - reg_w(gspca_dev, 0xa0, 0x02, 0xb334); - reg_w(gspca_dev, 0xa0, ptsensor_info->m1, 0xb300); - reg_w(gspca_dev, 0xa0, ptsensor_info->m2, 0xb300); - reg_w(gspca_dev, 0xa0, 0x01, 0xb308); - reg_w(gspca_dev, 0xa0, 0x0c, 0xb309); - reg_w(gspca_dev, 0xa0, ptsensor_info->I2cAdd, 0xb335); - reg_w(gspca_dev, 0xa0, ptsensor_info->op, 0xb301); - value = read_sensor_register(gspca_dev, ptsensor_info->IdAdd); - if (value == 0 && ptsensor_info->IdAdd == 0x82) - value = read_sensor_register(gspca_dev, 0x83); - if (value != 0) { - PDEBUG(D_ERR|D_PROBE, "Sensor ID %04x (%d)", - value, i); - if (value == ptsensor_info->VpId) - return ptsensor_info->sensorId; - - switch (value) { - case 0x3130: - return SENSOR_PO3130NC; - case 0x7673: - return SENSOR_OV7670; - case 0x8243: - return SENSOR_MI0360; - } - } - ptsensor_info++; - } - return -1; -} - -static void i2c_write(struct gspca_dev *gspca_dev, - u8 reg, const u8 *val, - u8 size) /* 1 or 2 */ -{ - int retry; - -#ifdef GSPCA_DEBUG - if (gspca_dev->usb_err < 0) - return; - if (size == 1) - PDEBUG(D_USBO, "i2c_w %02x %02x", reg, *val); - else - PDEBUG(D_USBO, "i2c_w %02x %02x%02x", reg, *val, val[1]); -#endif - reg_r_i(gspca_dev, 0xa1, 0xb33f, 1); -/*fixme:should check if (!(gspca_dev->usb_buf[0] & 0x02)) error*/ - reg_w_i(gspca_dev, 0xa0, size, 0xb334); - reg_w_i(gspca_dev, 0xa0, reg, 0xb33a); - reg_w_i(gspca_dev, 0xa0, val[0], 0xb336); - if (size > 1) - reg_w_i(gspca_dev, 0xa0, val[1], 0xb337); - reg_w_i(gspca_dev, 0xa0, 0x01, 0xb339); - retry = 4; - do { - reg_r_i(gspca_dev, 0xa1, 0xb33b, 1); - if (gspca_dev->usb_buf[0] == 0) - break; - msleep(20); - } while (--retry > 0); - if (retry <= 0) - pr_err("i2c_write timeout\n"); -} - -static void put_tab_to_reg(struct gspca_dev *gspca_dev, - const u8 *tab, u8 tabsize, u16 addr) -{ - int j; - u16 ad = addr; - - for (j = 0; j < tabsize; j++) - reg_w(gspca_dev, 0xa0, tab[j], ad++); -} - -static void usb_exchange(struct gspca_dev *gspca_dev, - const u8 data[][4]) -{ - int i = 0; - - for (;;) { - switch (data[i][3]) { - default: - return; - case 0xcc: /* normal write */ - reg_w(gspca_dev, 0xa0, data[i][2], - (data[i][0]) << 8 | data[i][1]); - break; - case 0xaa: /* i2c op */ - i2c_write(gspca_dev, data[i][1], &data[i][2], 1); - break; - case 0xbb: /* i2c op */ - i2c_write(gspca_dev, data[i][0], &data[i][1], 2); - break; - case 0xdd: - msleep(data[i][1] * 256 + data[i][2] + 10); - break; - } - i++; - } - /*not reached*/ -} - - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - - sd->bridge = id->driver_info >> 8; - sd->flags = id->driver_info & 0xff; - - if (id->idVendor == 0x046d && - (id->idProduct == 0x0892 || id->idProduct == 0x0896)) - sd->sensor = SENSOR_POxxxx; /* no probe */ - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - int sensor; - /* number of packets per ISOC message */ - static u8 npkt[NSENSORS] = { - [SENSOR_HV7131R] = 64, - [SENSOR_MI0360] = 32, - [SENSOR_MI1310_SOC] = 32, - [SENSOR_MI1320] = 64, - [SENSOR_MI1320_SOC] = 128, - [SENSOR_OV7660] = 32, - [SENSOR_OV7670] = 64, - [SENSOR_PO1200] = 128, - [SENSOR_PO3130NC] = 128, - [SENSOR_POxxxx] = 128, - }; - - if (sd->sensor != SENSOR_POxxxx) - sensor = vc032x_probe_sensor(gspca_dev); - else - sensor = sd->sensor; - - switch (sensor) { - case -1: - pr_err("Unknown sensor...\n"); - return -EINVAL; - case SENSOR_HV7131R: - PDEBUG(D_PROBE, "Find Sensor HV7131R"); - break; - case SENSOR_MI0360: - PDEBUG(D_PROBE, "Find Sensor MI0360"); - sd->bridge = BRIDGE_VC0323; - break; - case SENSOR_MI1310_SOC: - PDEBUG(D_PROBE, "Find Sensor MI1310_SOC"); - break; - case SENSOR_MI1320: - PDEBUG(D_PROBE, "Find Sensor MI1320"); - break; - case SENSOR_MI1320_SOC: - PDEBUG(D_PROBE, "Find Sensor MI1320_SOC"); - break; - case SENSOR_OV7660: - PDEBUG(D_PROBE, "Find Sensor OV7660"); - break; - case SENSOR_OV7670: - PDEBUG(D_PROBE, "Find Sensor OV7670"); - break; - case SENSOR_PO1200: - PDEBUG(D_PROBE, "Find Sensor PO1200"); - break; - case SENSOR_PO3130NC: - PDEBUG(D_PROBE, "Find Sensor PO3130NC"); - break; - case SENSOR_POxxxx: - PDEBUG(D_PROBE, "Sensor POxxxx"); - break; - } - sd->sensor = sensor; - - cam = &gspca_dev->cam; - if (sd->bridge == BRIDGE_VC0321) { - cam->cam_mode = vc0321_mode; - cam->nmodes = ARRAY_SIZE(vc0321_mode); - } else { - switch (sensor) { - case SENSOR_PO1200: - cam->cam_mode = svga_mode; - cam->nmodes = ARRAY_SIZE(svga_mode); - break; - case SENSOR_MI1310_SOC: - cam->cam_mode = vc0323_mode; - cam->nmodes = ARRAY_SIZE(vc0323_mode); - break; - case SENSOR_MI1320_SOC: - cam->cam_mode = bi_mode; - cam->nmodes = ARRAY_SIZE(bi_mode); - break; - case SENSOR_OV7670: - cam->cam_mode = bi_mode; - cam->nmodes = ARRAY_SIZE(bi_mode) - 1; - break; - default: - cam->cam_mode = vc0323_mode; - cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1; - break; - } - } - cam->npkt = npkt[sd->sensor]; - - if (sd->sensor == SENSOR_OV7670) - sd->flags |= FL_HFLIP | FL_VFLIP; - - if (sd->bridge == BRIDGE_VC0321) { - reg_r(gspca_dev, 0x8a, 0, 3); - reg_w(gspca_dev, 0x87, 0x00, 0x0f0f); - reg_r(gspca_dev, 0x8b, 0, 3); - reg_w(gspca_dev, 0x88, 0x00, 0x0202); - if (sd->sensor == SENSOR_POxxxx) { - reg_r(gspca_dev, 0xa1, 0xb300, 1); - if (gspca_dev->usb_buf[0] != 0) { - reg_w(gspca_dev, 0xa0, 0x26, 0xb300); - reg_w(gspca_dev, 0xa0, 0x04, 0xb300); - } - reg_w(gspca_dev, 0xa0, 0x00, 0xb300); - } - } - return gspca_dev->usb_err; -} - -static void setbrightness(struct gspca_dev *gspca_dev, s32 val) -{ - u8 data; - - data = val; - if (data >= 0x80) - data &= 0x7f; - else - data = 0xff ^ data; - i2c_write(gspca_dev, 0x98, &data, 1); -} - -static void setcontrast(struct gspca_dev *gspca_dev, u8 val) -{ - i2c_write(gspca_dev, 0x99, &val, 1); -} - -static void setcolors(struct gspca_dev *gspca_dev, u8 val) -{ - u8 data; - - data = val - (val >> 3) - 1; - i2c_write(gspca_dev, 0x94, &data, 1); - i2c_write(gspca_dev, 0x95, &val, 1); -} - -static void sethvflip(struct gspca_dev *gspca_dev, bool hflip, bool vflip) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 data[2]; - - if (sd->flags & FL_HFLIP) - hflip = !hflip; - if (sd->flags & FL_VFLIP) - vflip = !vflip; - switch (sd->sensor) { - case SENSOR_MI1310_SOC: - case SENSOR_MI1320: - case SENSOR_MI1320_SOC: - data[0] = data[1] = 0; /* select page 0 */ - i2c_write(gspca_dev, 0xf0, data, 2); - data[0] = sd->sensor == SENSOR_MI1310_SOC ? 0x03 : 0x01; - data[1] = 0x02 * hflip - | 0x01 * vflip; - i2c_write(gspca_dev, 0x20, data, 2); - break; - case SENSOR_OV7660: - case SENSOR_OV7670: - data[0] = sd->sensor == SENSOR_OV7660 ? 0x01 : 0x07; - data[0] |= OV7660_MVFP_MIRROR * hflip - | OV7660_MVFP_VFLIP * vflip; - i2c_write(gspca_dev, OV7660_REG_MVFP, data, 1); - break; - case SENSOR_PO1200: - data[0] = 0; - i2c_write(gspca_dev, 0x03, data, 1); - data[0] = 0x80 * hflip - | 0x40 * vflip - | 0x06; - i2c_write(gspca_dev, 0x1e, data, 1); - break; - } -} - -static void setlightfreq(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - static const u8 (*ov7660_freq_tb[3])[4] = - {ov7660_NoFliker, ov7660_50HZ, ov7660_60HZ}; - - if (sd->sensor != SENSOR_OV7660) - return; - usb_exchange(gspca_dev, ov7660_freq_tb[val]); -} - -static void setsharpness(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 data; - - switch (sd->sensor) { - case SENSOR_PO1200: - data = 0; - i2c_write(gspca_dev, 0x03, &data, 1); - if (val < 0) - data = 0x6a; - else - data = 0xb5 + val * 3; - i2c_write(gspca_dev, 0x61, &data, 1); - break; - case SENSOR_POxxxx: - if (val < 0) - data = 0x7e; /* def = max */ - else - data = 0x60 + val * 0x0f; - i2c_write(gspca_dev, 0x59, &data, 1); - break; - } -} -static void setgain(struct gspca_dev *gspca_dev, u8 val) -{ - i2c_write(gspca_dev, 0x15, &val, 1); -} - -static void setexposure(struct gspca_dev *gspca_dev, s32 val) -{ - u8 data; - - data = val >> 8; - i2c_write(gspca_dev, 0x1a, &data, 1); - data = val; - i2c_write(gspca_dev, 0x1b, &data, 1); -} - -static void setautogain(struct gspca_dev *gspca_dev, s32 val) -{ - static const u8 data[2] = {0x28, 0x3c}; - - i2c_write(gspca_dev, 0xd1, &data[val], 1); -} - -static void setgamma(struct gspca_dev *gspca_dev) -{ -/*fixme:to do */ - usb_exchange(gspca_dev, poxxxx_gamma); -} - -static void setbacklight(struct gspca_dev *gspca_dev, s32 val) -{ - u16 v; - u8 data; - - data = (val << 4) | 0x0f; - i2c_write(gspca_dev, 0xaa, &data, 1); - v = 613 + 12 * val; - data = v >> 8; - i2c_write(gspca_dev, 0xc4, &data, 1); - data = v; - i2c_write(gspca_dev, 0xc5, &data, 1); - v = 1093 - 12 * val; - data = v >> 8; - i2c_write(gspca_dev, 0xc6, &data, 1); - data = v; - i2c_write(gspca_dev, 0xc7, &data, 1); - v = 342 + 9 * val; - data = v >> 8; - i2c_write(gspca_dev, 0xc8, &data, 1); - data = v; - i2c_write(gspca_dev, 0xc9, &data, 1); - v = 702 - 9 * val; - data = v >> 8; - i2c_write(gspca_dev, 0xca, &data, 1); - data = v; - i2c_write(gspca_dev, 0xcb, &data, 1); -} - -static void setwb(struct gspca_dev *gspca_dev) -{ -/*fixme:to do - valid when reg d1 = 0x1c - (reg16 + reg15 = 0xa3)*/ - static const u8 data[2] = {0x00, 0x00}; - - i2c_write(gspca_dev, 0x16, &data[0], 1); - i2c_write(gspca_dev, 0x18, &data[1], 1); -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - const u8 (*init)[4]; - const u8 *GammaT = NULL; - const u8 *MatrixT = NULL; - int mode; - static const u8 (*mi1320_soc_init[])[4] = { - mi1320_soc_InitSXGA, - mi1320_soc_InitVGA, - mi1320_soc_InitQVGA, - }; - -/*fixme: back sensor only*/ - if (sd->flags & FL_SAMSUNG) { - reg_w(gspca_dev, 0x89, 0xf0ff, 0xffff); - reg_w(gspca_dev, 0xa9, 0x8348, 0x000e); - reg_w(gspca_dev, 0xa9, 0x0000, 0x001a); - } - - /* Assume start use the good resolution from gspca_dev->mode */ - if (sd->bridge == BRIDGE_VC0321) { - reg_w(gspca_dev, 0xa0, 0xff, 0xbfec); - reg_w(gspca_dev, 0xa0, 0xff, 0xbfed); - reg_w(gspca_dev, 0xa0, 0xff, 0xbfee); - reg_w(gspca_dev, 0xa0, 0xff, 0xbfef); - sd->image_offset = 46; - } else { - if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].pixelformat - == V4L2_PIX_FMT_JPEG) - sd->image_offset = 0; - else - sd->image_offset = 32; - } - - mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; - switch (sd->sensor) { - case SENSOR_HV7131R: - GammaT = hv7131r_gamma; - MatrixT = hv7131r_matrix; - if (mode) - init = hv7131r_initQVGA_data; /* 320x240 */ - else - init = hv7131r_initVGA_data; /* 640x480 */ - break; - case SENSOR_OV7660: - GammaT = ov7660_gamma; - MatrixT = ov7660_matrix; - if (mode) - init = ov7660_initQVGA_data; /* 320x240 */ - else - init = ov7660_initVGA_data; /* 640x480 */ - break; - case SENSOR_MI0360: - GammaT = mi1320_gamma; - MatrixT = mi0360_matrix; - if (mode) - init = mi0360_initQVGA_JPG; /* 320x240 */ - else - init = mi0360_initVGA_JPG; /* 640x480 */ - break; - case SENSOR_MI1310_SOC: - GammaT = mi1320_gamma; - MatrixT = mi1320_matrix; - switch (mode) { - case 1: - init = mi1310_socinitQVGA_JPG; /* 320x240 */ - break; - case 0: - init = mi1310_socinitVGA_JPG; /* 640x480 */ - break; - default: - init = mi1310_soc_InitSXGA_JPG; /* 1280x1024 */ - break; - } - break; - case SENSOR_MI1320: - GammaT = mi1320_gamma; - MatrixT = mi1320_matrix; - if (mode) - init = mi1320_initQVGA_data; /* 320x240 */ - else - init = mi1320_initVGA_data; /* 640x480 */ - break; - case SENSOR_MI1320_SOC: - GammaT = mi1320_gamma; - MatrixT = mi1320_matrix; - init = mi1320_soc_init[mode]; - break; - case SENSOR_OV7670: - init = mode == 1 ? ov7670_InitVGA : ov7670_InitQVGA; - break; - case SENSOR_PO3130NC: - GammaT = po3130_gamma; - MatrixT = po3130_matrix; - if (mode) - init = po3130_initQVGA_data; /* 320x240 */ - else - init = po3130_initVGA_data; /* 640x480 */ - usb_exchange(gspca_dev, init); - init = po3130_rundata; - break; - case SENSOR_PO1200: - GammaT = po1200_gamma; - MatrixT = po1200_matrix; - init = po1200_initVGA_data; - break; - default: -/* case SENSOR_POxxxx: */ - usb_exchange(gspca_dev, poxxxx_init_common); - setgamma(gspca_dev); - usb_exchange(gspca_dev, poxxxx_init_start_3); - if (mode) - init = poxxxx_initQVGA; - else - init = poxxxx_initVGA; - usb_exchange(gspca_dev, init); - reg_r(gspca_dev, 0x8c, 0x0000, 3); - reg_w(gspca_dev, 0xa0, - gspca_dev->usb_buf[2] & 1 ? 0 : 1, - 0xb35c); - msleep(300); -/*fixme: i2c read 04 and 05*/ - init = poxxxx_init_end_1; - break; - } - usb_exchange(gspca_dev, init); - if (GammaT && MatrixT) { - put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a); - put_tab_to_reg(gspca_dev, GammaT, 17, 0xb85b); - put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c); - put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c); - - switch (sd->sensor) { - case SENSOR_PO1200: - case SENSOR_HV7131R: - reg_w(gspca_dev, 0x89, 0x0400, 0x1415); - break; - case SENSOR_MI1310_SOC: - reg_w(gspca_dev, 0x89, 0x058c, 0x0000); - break; - } - msleep(100); - } - switch (sd->sensor) { - case SENSOR_OV7670: - reg_w(gspca_dev, 0x87, 0xffff, 0xffff); - reg_w(gspca_dev, 0x88, 0xff00, 0xf0f1); - reg_w(gspca_dev, 0xa0, 0x0000, 0xbfff); - break; - case SENSOR_POxxxx: - usb_exchange(gspca_dev, poxxxx_init_end_2); - setwb(gspca_dev); - msleep(80); /* led on */ - reg_w(gspca_dev, 0x89, 0xffff, 0xfdff); - break; - } - return gspca_dev->usb_err; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->sensor) { - case SENSOR_MI1310_SOC: - reg_w(gspca_dev, 0x89, 0x058c, 0x00ff); - break; - case SENSOR_POxxxx: - return; - default: - if (!(sd->flags & FL_SAMSUNG)) - reg_w(gspca_dev, 0x89, 0xffff, 0xffff); - break; - } - reg_w(gspca_dev, 0xa0, 0x01, 0xb301); - reg_w(gspca_dev, 0xa0, 0x09, 0xb003); -} - -/* called on streamoff with alt 0 and on disconnect */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (!gspca_dev->present) - return; -/*fixme: is this useful?*/ - if (sd->sensor == SENSOR_MI1310_SOC) - reg_w(gspca_dev, 0x89, 0x058c, 0x00ff); - else if (!(sd->flags & FL_SAMSUNG)) - reg_w(gspca_dev, 0x89, 0xffff, 0xffff); - - if (sd->sensor == SENSOR_POxxxx) { - reg_w(gspca_dev, 0xa0, 0x26, 0xb300); - reg_w(gspca_dev, 0xa0, 0x04, 0xb300); - reg_w(gspca_dev, 0xa0, 0x00, 0xb300); - } -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso pkt length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (data[0] == 0xff && data[1] == 0xd8) { - PDEBUG(D_PACK, - "vc032x header packet found len %d", len); - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - data += sd->image_offset; - len -= sd->image_offset; - gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); - return; - } - - /* The vc0321 sends some additional data after sending the complete - * frame, we ignore this. */ - if (sd->bridge == BRIDGE_VC0321) { - int size, l; - - l = gspca_dev->image_len; - size = gspca_dev->frsz; - if (len > size - l) - len = size - l; - } - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming && ctrl->id != V4L2_CID_POWER_LINE_FREQUENCY) - return 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - setbrightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_CONTRAST: - setcontrast(gspca_dev, ctrl->val); - break; - case V4L2_CID_SATURATION: - setcolors(gspca_dev, ctrl->val); - break; - case V4L2_CID_HFLIP: - sethvflip(gspca_dev, sd->hflip->val, sd->vflip->val); - break; - case V4L2_CID_SHARPNESS: - setsharpness(gspca_dev, ctrl->val); - break; - case V4L2_CID_AUTOGAIN: - setautogain(gspca_dev, ctrl->val); - break; - case V4L2_CID_GAIN: - setgain(gspca_dev, ctrl->val); - break; - case V4L2_CID_EXPOSURE: - setexposure(gspca_dev, ctrl->val); - break; - case V4L2_CID_BACKLIGHT_COMPENSATION: - setbacklight(gspca_dev, ctrl->val); - break; - case V4L2_CID_POWER_LINE_FREQUENCY: - setlightfreq(gspca_dev, ctrl->val); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - bool has_brightness = false; - bool has_contrast = false; - bool has_sat = false; - bool has_hvflip = false; - bool has_freq = false; - bool has_backlight = false; - bool has_exposure = false; - bool has_autogain = false; - bool has_gain = false; - bool has_sharpness = false; - - switch (sd->sensor) { - case SENSOR_HV7131R: - case SENSOR_MI0360: - case SENSOR_PO3130NC: - break; - case SENSOR_MI1310_SOC: - case SENSOR_MI1320: - case SENSOR_MI1320_SOC: - case SENSOR_OV7660: - has_hvflip = true; - break; - case SENSOR_OV7670: - has_hvflip = has_freq = true; - break; - case SENSOR_PO1200: - has_hvflip = has_sharpness = true; - break; - case SENSOR_POxxxx: - has_brightness = has_contrast = has_sat = has_backlight = - has_exposure = has_autogain = has_gain = - has_sharpness = true; - break; - } - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 8); - if (has_brightness) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); - if (has_contrast) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 255, 1, 127); - if (has_sat) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SATURATION, 1, 127, 1, 63); - if (has_hvflip) { - sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_HFLIP, 0, 1, 1, 0); - sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_VFLIP, 0, 1, 1, 0); - } - if (has_sharpness) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SHARPNESS, -1, 2, 1, -1); - if (has_freq) - v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, - V4L2_CID_POWER_LINE_FREQUENCY, - V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, - V4L2_CID_POWER_LINE_FREQUENCY_50HZ); - if (has_autogain) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - if (has_gain) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_GAIN, 0, 78, 1, 0); - if (has_exposure) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 4095, 1, 450); - if (has_backlight) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BACKLIGHT_COMPENSATION, 0, 15, 1, 15); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - if (sd->hflip) - v4l2_ctrl_cluster(2, &sd->hflip); - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .init_controls = sd_init_controls, - .config = sd_config, - .init = sd_init, - .start = sd_start, - .stopN = sd_stopN, - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, -}; - -/* -- module initialisation -- */ -#define BF(bridge, flags) \ - .driver_info = (BRIDGE_ ## bridge << 8) \ - | (flags) -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x041e, 0x405b), BF(VC0323, FL_VFLIP)}, - {USB_DEVICE(0x046d, 0x0892), BF(VC0321, 0)}, - {USB_DEVICE(0x046d, 0x0896), BF(VC0321, 0)}, - {USB_DEVICE(0x046d, 0x0897), BF(VC0321, 0)}, - {USB_DEVICE(0x0ac8, 0x0321), BF(VC0321, 0)}, - {USB_DEVICE(0x0ac8, 0x0323), BF(VC0323, 0)}, - {USB_DEVICE(0x0ac8, 0x0328), BF(VC0321, 0)}, - {USB_DEVICE(0x0ac8, 0xc001), BF(VC0321, 0)}, - {USB_DEVICE(0x0ac8, 0xc002), BF(VC0321, 0)}, - {USB_DEVICE(0x0ac8, 0xc301), BF(VC0323, FL_SAMSUNG)}, - {USB_DEVICE(0x15b8, 0x6001), BF(VC0323, 0)}, - {USB_DEVICE(0x15b8, 0x6002), BF(VC0323, 0)}, - {USB_DEVICE(0x17ef, 0x4802), BF(VC0323, 0)}, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/vicam.c b/drivers/media/video/gspca/vicam.c deleted file mode 100644 index b1a64b912666..000000000000 --- a/drivers/media/video/gspca/vicam.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * gspca ViCam subdriver - * - * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com> - * - * Based on the usbvideo vicam driver, which is: - * - * Copyright (c) 2002 Joe Burks (jburks@wavicle.org), - * Christopher L Cheney (ccheney@cheney.cx), - * Pavel Machek (pavel@ucw.cz), - * John Tyner (jtyner@cs.ucr.edu), - * Monroe Williams (monroe@pobox.com) - * - * 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "vicam" -#define HEADER_SIZE 64 - -#include <linux/workqueue.h> -#include <linux/slab.h> -#include <linux/firmware.h> -#include <linux/ihex.h> -#include "gspca.h" - -#define VICAM_FIRMWARE "vicam/firmware.fw" - -MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); -MODULE_DESCRIPTION("GSPCA ViCam USB Camera Driver"); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(VICAM_FIRMWARE); - -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - struct work_struct work_struct; - struct workqueue_struct *work_thread; -}; - -/* The vicam sensor has a resolution of 512 x 244, with I believe square - pixels, but this is forced to a 4:3 ratio by optics. So it has - non square pixels :( */ -static struct v4l2_pix_format vicam_mode[] = { - { 256, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, - .bytesperline = 256, - .sizeimage = 256 * 122, - .colorspace = V4L2_COLORSPACE_SRGB,}, - /* 2 modes with somewhat more square pixels */ - { 256, 200, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, - .bytesperline = 256, - .sizeimage = 256 * 200, - .colorspace = V4L2_COLORSPACE_SRGB,}, - { 256, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, - .bytesperline = 256, - .sizeimage = 256 * 240, - .colorspace = V4L2_COLORSPACE_SRGB,}, -#if 0 /* This mode has extremely non square pixels, testing use only */ - { 512, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, - .bytesperline = 512, - .sizeimage = 512 * 122, - .colorspace = V4L2_COLORSPACE_SRGB,}, -#endif - { 512, 244, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, - .bytesperline = 512, - .sizeimage = 512 * 244, - .colorspace = V4L2_COLORSPACE_SRGB,}, -}; - -static int vicam_control_msg(struct gspca_dev *gspca_dev, u8 request, - u16 value, u16 index, u8 *data, u16 len) -{ - int ret; - - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - request, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, data, len, 1000); - if (ret < 0) - pr_err("control msg req %02X error %d\n", request, ret); - - return ret; -} - -static int vicam_set_camera_power(struct gspca_dev *gspca_dev, int state) -{ - int ret; - - ret = vicam_control_msg(gspca_dev, 0x50, state, 0, NULL, 0); - if (ret < 0) - return ret; - - if (state) - ret = vicam_control_msg(gspca_dev, 0x55, 1, 0, NULL, 0); - - return ret; -} - -/* - * request and read a block of data - see warning on vicam_command. - */ -static int vicam_read_frame(struct gspca_dev *gspca_dev, u8 *data, int size) -{ - int ret, unscaled_height, act_len = 0; - u8 *req_data = gspca_dev->usb_buf; - s32 expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure); - s32 gain = v4l2_ctrl_g_ctrl(gspca_dev->gain); - - memset(req_data, 0, 16); - req_data[0] = gain; - if (gspca_dev->width == 256) - req_data[1] |= 0x01; /* low nibble x-scale */ - if (gspca_dev->height <= 122) { - req_data[1] |= 0x10; /* high nibble y-scale */ - unscaled_height = gspca_dev->height * 2; - } else - unscaled_height = gspca_dev->height; - req_data[2] = 0x90; /* unknown, does not seem to do anything */ - if (unscaled_height <= 200) - req_data[3] = 0x06; /* vend? */ - else if (unscaled_height <= 242) /* Yes 242 not 240 */ - req_data[3] = 0x07; /* vend? */ - else /* Up to 244 lines with req_data[3] == 0x08 */ - req_data[3] = 0x08; /* vend? */ - - if (expo < 256) { - /* Frame rate maxed out, use partial frame expo time */ - req_data[4] = 255 - expo; - req_data[5] = 0x00; - req_data[6] = 0x00; - req_data[7] = 0x01; - } else { - /* Modify frame rate */ - req_data[4] = 0x00; - req_data[5] = 0x00; - req_data[6] = expo & 0xFF; - req_data[7] = expo >> 8; - } - req_data[8] = ((244 - unscaled_height) / 2) & ~0x01; /* vstart */ - /* bytes 9-15 do not seem to affect exposure or image quality */ - - mutex_lock(&gspca_dev->usb_lock); - ret = vicam_control_msg(gspca_dev, 0x51, 0x80, 0, req_data, 16); - mutex_unlock(&gspca_dev->usb_lock); - if (ret < 0) - return ret; - - ret = usb_bulk_msg(gspca_dev->dev, - usb_rcvbulkpipe(gspca_dev->dev, 0x81), - data, size, &act_len, 10000); - /* successful, it returns 0, otherwise negative */ - if (ret < 0 || act_len != size) { - pr_err("bulk read fail (%d) len %d/%d\n", - ret, act_len, size); - return -EIO; - } - return 0; -} - -/* This function is called as a workqueue function and runs whenever the camera - * is streaming data. Because it is a workqueue function it is allowed to sleep - * so we can use synchronous USB calls. To avoid possible collisions with other - * threads attempting to use the camera's USB interface we take the gspca - * usb_lock when performing USB operations. In practice the only thing we need - * to protect against is the usb_set_interface call that gspca makes during - * stream_off as the camera doesn't provide any controls that the user could try - * to change. - */ -static void vicam_dostream(struct work_struct *work) -{ - struct sd *sd = container_of(work, struct sd, work_struct); - struct gspca_dev *gspca_dev = &sd->gspca_dev; - int ret, frame_sz; - u8 *buffer; - - frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage + - HEADER_SIZE; - buffer = kmalloc(frame_sz, GFP_KERNEL | GFP_DMA); - if (!buffer) { - pr_err("Couldn't allocate USB buffer\n"); - goto exit; - } - - while (gspca_dev->dev && gspca_dev->streaming) { -#ifdef CONFIG_PM - if (gspca_dev->frozen) - break; -#endif - ret = vicam_read_frame(gspca_dev, buffer, frame_sz); - if (ret < 0) - break; - - /* Note the frame header contents seem to be completely - constant, they do not change with either image, or - settings. So we simply discard it. The frames have - a very similar 64 byte footer, which we don't even - bother reading from the cam */ - gspca_frame_add(gspca_dev, FIRST_PACKET, - buffer + HEADER_SIZE, - frame_sz - HEADER_SIZE); - gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); - } -exit: - kfree(buffer); -} - -/* This function is called at probe time just before sd_init */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct cam *cam = &gspca_dev->cam; - struct sd *sd = (struct sd *)gspca_dev; - - /* We don't use the buffer gspca allocates so make it small. */ - cam->bulk = 1; - cam->bulk_size = 64; - cam->cam_mode = vicam_mode; - cam->nmodes = ARRAY_SIZE(vicam_mode); - - INIT_WORK(&sd->work_struct, vicam_dostream); - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - int ret; - const struct ihex_binrec *rec; - const struct firmware *uninitialized_var(fw); - u8 *firmware_buf; - - ret = request_ihex_firmware(&fw, VICAM_FIRMWARE, - &gspca_dev->dev->dev); - if (ret) { - pr_err("Failed to load \"vicam/firmware.fw\": %d\n", ret); - return ret; - } - - firmware_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!firmware_buf) { - ret = -ENOMEM; - goto exit; - } - for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) { - memcpy(firmware_buf, rec->data, be16_to_cpu(rec->len)); - ret = vicam_control_msg(gspca_dev, 0xff, 0, 0, firmware_buf, - be16_to_cpu(rec->len)); - if (ret < 0) - break; - } - - kfree(firmware_buf); -exit: - release_firmware(fw); - return ret; -} - -/* Set up for getting frames. */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - int ret; - - ret = vicam_set_camera_power(gspca_dev, 1); - if (ret < 0) - return ret; - - /* Start the workqueue function to do the streaming */ - sd->work_thread = create_singlethread_workqueue(MODULE_NAME); - queue_work(sd->work_thread, &sd->work_struct); - - return 0; -} - -/* called on streamoff with alt==0 and on disconnect */ -/* the usb_lock is held at entry - restore on exit */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct sd *dev = (struct sd *)gspca_dev; - - /* wait for the work queue to terminate */ - mutex_unlock(&gspca_dev->usb_lock); - /* This waits for vicam_dostream to finish */ - destroy_workqueue(dev->work_thread); - dev->work_thread = NULL; - mutex_lock(&gspca_dev->usb_lock); - - if (gspca_dev->dev) - vicam_set_camera_power(gspca_dev, 0); -} - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 2); - gspca_dev->exposure = v4l2_ctrl_new_std(hdl, NULL, - V4L2_CID_EXPOSURE, 0, 2047, 1, 256); - gspca_dev->gain = v4l2_ctrl_new_std(hdl, NULL, - V4L2_CID_GAIN, 0, 255, 1, 200); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -/* Table of supported USB devices */ -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x04c1, 0x009d)}, - {USB_DEVICE(0x0602, 0x1001)}, - {} -}; - -MODULE_DEVICE_TABLE(usb, device_table); - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stop0 = sd_stop0, -}; - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, - &sd_desc, - sizeof(struct sd), - THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c deleted file mode 100644 index 9e3a909e0a00..000000000000 --- a/drivers/media/video/gspca/w996Xcf.c +++ /dev/null @@ -1,567 +0,0 @@ -/** - * - * GSPCA sub driver for W996[78]CF JPEG USB Dual Mode Camera Chip. - * - * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> - * - * This module is adapted from the in kernel v4l1 w9968cf driver: - * - * Copyright (C) 2002-2004 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 - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* Note this is not a stand alone driver, it gets included in ov519.c, this - is a bit of a hack, but it needs the driver code for a lot of different - ov sensors which is already present in ov519.c (the old v4l1 driver used - the ovchipcam framework). When we have the time we really should move - the sensor drivers to v4l2 sub drivers, and properly split of this - driver from ov519.c */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */ - -#define Y_QUANTABLE (&sd->jpeg_hdr[JPEG_QT0_OFFSET]) -#define UV_QUANTABLE (&sd->jpeg_hdr[JPEG_QT1_OFFSET]) - -static const struct v4l2_pix_format w9968cf_vga_mode[] = { - {160, 120, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, - .bytesperline = 160 * 2, - .sizeimage = 160 * 120 * 2, - .colorspace = V4L2_COLORSPACE_JPEG}, - {176, 144, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, - .bytesperline = 176 * 2, - .sizeimage = 176 * 144 * 2, - .colorspace = V4L2_COLORSPACE_JPEG}, - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320 * 2, - .sizeimage = 320 * 240 * 2, - .colorspace = V4L2_COLORSPACE_JPEG}, - {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 352 * 2, - .sizeimage = 352 * 288 * 2, - .colorspace = V4L2_COLORSPACE_JPEG}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640 * 2, - .sizeimage = 640 * 480 * 2, - .colorspace = V4L2_COLORSPACE_JPEG}, -}; - -static void reg_w(struct sd *sd, u16 index, u16 value); - -/*-------------------------------------------------------------------------- - Write 64-bit data to the fast serial bus registers. - Return 0 on success, -1 otherwise. - --------------------------------------------------------------------------*/ -static void w9968cf_write_fsb(struct sd *sd, u16* data) -{ - struct usb_device *udev = sd->gspca_dev.dev; - u16 value; - int ret; - - if (sd->gspca_dev.usb_err < 0) - return; - - value = *data++; - memcpy(sd->gspca_dev.usb_buf, data, 6); - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, - USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, - value, 0x06, sd->gspca_dev.usb_buf, 6, 500); - if (ret < 0) { - pr_err("Write FSB registers failed (%d)\n", ret); - sd->gspca_dev.usb_err = ret; - } -} - -/*-------------------------------------------------------------------------- - Write data to the serial bus control register. - Return 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static void w9968cf_write_sb(struct sd *sd, u16 value) -{ - int ret; - - if (sd->gspca_dev.usb_err < 0) - return; - - /* We don't use reg_w here, as that would cause all writes when - bitbanging i2c to be logged, making the logs impossible to read */ - ret = usb_control_msg(sd->gspca_dev.dev, - usb_sndctrlpipe(sd->gspca_dev.dev, 0), - 0, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, 0x01, NULL, 0, 500); - - udelay(W9968CF_I2C_BUS_DELAY); - - if (ret < 0) { - pr_err("Write SB reg [01] %04x failed\n", value); - sd->gspca_dev.usb_err = ret; - } -} - -/*-------------------------------------------------------------------------- - Read data from the serial bus control register. - Return 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static int w9968cf_read_sb(struct sd *sd) -{ - int ret; - - if (sd->gspca_dev.usb_err < 0) - return -1; - - /* We don't use reg_r here, as the w9968cf is special and has 16 - bit registers instead of 8 bit */ - ret = usb_control_msg(sd->gspca_dev.dev, - usb_rcvctrlpipe(sd->gspca_dev.dev, 0), - 1, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, 0x01, sd->gspca_dev.usb_buf, 2, 500); - if (ret >= 0) { - ret = sd->gspca_dev.usb_buf[0] | - (sd->gspca_dev.usb_buf[1] << 8); - } else { - pr_err("Read SB reg [01] failed\n"); - sd->gspca_dev.usb_err = ret; - } - - udelay(W9968CF_I2C_BUS_DELAY); - - return ret; -} - -/*-------------------------------------------------------------------------- - Upload quantization tables for the JPEG compression. - This function is called by w9968cf_start_transfer(). - Return 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static void w9968cf_upload_quantizationtables(struct sd *sd) -{ - u16 a, b; - int i, j; - - reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */ - - for (i = 0, j = 0; i < 32; i++, j += 2) { - a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j + 1]) << 8); - b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j + 1]) << 8); - reg_w(sd, 0x40 + i, a); - reg_w(sd, 0x60 + i, b); - } - reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */ -} - -/**************************************************************************** - * Low-level I2C I/O functions. * - * The adapter supports the following I2C transfer functions: * - * i2c_adap_fastwrite_byte_data() (at 400 kHz bit frequency only) * - * i2c_adap_read_byte_data() * - * i2c_adap_read_byte() * - ****************************************************************************/ - -static void w9968cf_smbus_start(struct sd *sd) -{ - w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ - w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ -} - -static void w9968cf_smbus_stop(struct sd *sd) -{ - w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ - w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ - w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ -} - -static void w9968cf_smbus_write_byte(struct sd *sd, u8 v) -{ - u8 bit; - int sda; - - for (bit = 0 ; bit < 8 ; bit++) { - sda = (v & 0x80) ? 2 : 0; - v <<= 1; - /* SDE=1, SDA=sda, SCL=0 */ - w9968cf_write_sb(sd, 0x10 | sda); - /* SDE=1, SDA=sda, SCL=1 */ - w9968cf_write_sb(sd, 0x11 | sda); - /* SDE=1, SDA=sda, SCL=0 */ - w9968cf_write_sb(sd, 0x10 | sda); - } -} - -static void w9968cf_smbus_read_byte(struct sd *sd, u8 *v) -{ - u8 bit; - - /* No need to ensure SDA is high as we are always called after - read_ack which ends with SDA high */ - *v = 0; - for (bit = 0 ; bit < 8 ; bit++) { - *v <<= 1; - /* SDE=1, SDA=1, SCL=1 */ - w9968cf_write_sb(sd, 0x0013); - *v |= (w9968cf_read_sb(sd) & 0x0008) ? 1 : 0; - /* SDE=1, SDA=1, SCL=0 */ - w9968cf_write_sb(sd, 0x0012); - } -} - -static void w9968cf_smbus_write_nack(struct sd *sd) -{ - /* No need to ensure SDA is high as we are always called after - read_byte which ends with SDA high */ - w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ - w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ -} - -static void w9968cf_smbus_read_ack(struct sd *sd) -{ - int sda; - - /* Ensure SDA is high before raising clock to avoid a spurious stop */ - w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ - w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ - sda = w9968cf_read_sb(sd); - w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ - if (sda >= 0 && (sda & 0x08)) { - PDEBUG(D_USBI, "Did not receive i2c ACK"); - sd->gspca_dev.usb_err = -EIO; - } -} - -/* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */ -static void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) -{ - u16* data = (u16 *)sd->gspca_dev.usb_buf; - - data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0); - data[0] |= (sd->sensor_addr & 0x40) ? 0x4000 : 0x0; - data[1] = 0x2082 | ((sd->sensor_addr & 0x40) ? 0x0005 : 0x0); - data[1] |= (sd->sensor_addr & 0x20) ? 0x0150 : 0x0; - data[1] |= (sd->sensor_addr & 0x10) ? 0x5400 : 0x0; - data[2] = 0x8208 | ((sd->sensor_addr & 0x08) ? 0x0015 : 0x0); - data[2] |= (sd->sensor_addr & 0x04) ? 0x0540 : 0x0; - data[2] |= (sd->sensor_addr & 0x02) ? 0x5000 : 0x0; - data[3] = 0x1d20 | ((sd->sensor_addr & 0x02) ? 0x0001 : 0x0); - data[3] |= (sd->sensor_addr & 0x01) ? 0x0054 : 0x0; - - w9968cf_write_fsb(sd, data); - - data[0] = 0x8208 | ((reg & 0x80) ? 0x0015 : 0x0); - data[0] |= (reg & 0x40) ? 0x0540 : 0x0; - data[0] |= (reg & 0x20) ? 0x5000 : 0x0; - data[1] = 0x0820 | ((reg & 0x20) ? 0x0001 : 0x0); - data[1] |= (reg & 0x10) ? 0x0054 : 0x0; - data[1] |= (reg & 0x08) ? 0x1500 : 0x0; - data[1] |= (reg & 0x04) ? 0x4000 : 0x0; - data[2] = 0x2082 | ((reg & 0x04) ? 0x0005 : 0x0); - data[2] |= (reg & 0x02) ? 0x0150 : 0x0; - data[2] |= (reg & 0x01) ? 0x5400 : 0x0; - data[3] = 0x001d; - - w9968cf_write_fsb(sd, data); - - data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0); - data[0] |= (value & 0x40) ? 0x0540 : 0x0; - data[0] |= (value & 0x20) ? 0x5000 : 0x0; - data[1] = 0x0820 | ((value & 0x20) ? 0x0001 : 0x0); - data[1] |= (value & 0x10) ? 0x0054 : 0x0; - data[1] |= (value & 0x08) ? 0x1500 : 0x0; - data[1] |= (value & 0x04) ? 0x4000 : 0x0; - data[2] = 0x2082 | ((value & 0x04) ? 0x0005 : 0x0); - data[2] |= (value & 0x02) ? 0x0150 : 0x0; - data[2] |= (value & 0x01) ? 0x5400 : 0x0; - data[3] = 0xfe1d; - - w9968cf_write_fsb(sd, data); - - PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); -} - -/* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */ -static int w9968cf_i2c_r(struct sd *sd, u8 reg) -{ - int ret = 0; - u8 value; - - /* Fast serial bus data control disable */ - w9968cf_write_sb(sd, 0x0013); /* don't change ! */ - - w9968cf_smbus_start(sd); - w9968cf_smbus_write_byte(sd, sd->sensor_addr); - w9968cf_smbus_read_ack(sd); - w9968cf_smbus_write_byte(sd, reg); - w9968cf_smbus_read_ack(sd); - w9968cf_smbus_stop(sd); - w9968cf_smbus_start(sd); - w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1); - w9968cf_smbus_read_ack(sd); - w9968cf_smbus_read_byte(sd, &value); - /* signal we don't want to read anymore, the v4l1 driver used to - send an ack here which is very wrong! (and then fixed - the issues this gave by retrying reads) */ - w9968cf_smbus_write_nack(sd); - w9968cf_smbus_stop(sd); - - /* Fast serial bus data control re-enable */ - w9968cf_write_sb(sd, 0x0030); - - if (sd->gspca_dev.usb_err >= 0) { - ret = value; - PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); - } else - PDEBUG(D_ERR, "i2c read [0x%02x] failed", reg); - - return ret; -} - -/*-------------------------------------------------------------------------- - Turn on the LED on some webcams. A beep should be heard too. - Return 0 on success, a negative number otherwise. - --------------------------------------------------------------------------*/ -static void w9968cf_configure(struct sd *sd) -{ - reg_w(sd, 0x00, 0xff00); /* power-down */ - reg_w(sd, 0x00, 0xbf17); /* reset everything */ - reg_w(sd, 0x00, 0xbf10); /* normal operation */ - reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */ - reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */ - reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */ - reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */ - - sd->stopped = 1; -} - -static void w9968cf_init(struct sd *sd) -{ - unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2), - y0 = 0x0000, - u0 = y0 + hw_bufsize / 2, - v0 = u0 + hw_bufsize / 4, - y1 = v0 + hw_bufsize / 4, - u1 = y1 + hw_bufsize / 2, - v1 = u1 + hw_bufsize / 4; - - reg_w(sd, 0x00, 0xff00); /* power off */ - reg_w(sd, 0x00, 0xbf10); /* power on */ - - reg_w(sd, 0x03, 0x405d); /* DRAM timings */ - reg_w(sd, 0x04, 0x0030); /* SDRAM timings */ - - reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */ - reg_w(sd, 0x21, y0 >> 16); /* Y buf.0, high */ - reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */ - reg_w(sd, 0x25, u0 >> 16); /* U buf.0, high */ - reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */ - reg_w(sd, 0x29, v0 >> 16); /* V buf.0, high */ - - reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */ - reg_w(sd, 0x23, y1 >> 16); /* Y buf.1, high */ - reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */ - reg_w(sd, 0x27, u1 >> 16); /* U buf.1, high */ - reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */ - reg_w(sd, 0x2b, v1 >> 16); /* V buf.1, high */ - - reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */ - reg_w(sd, 0x33, y1 >> 16); /* JPEG buf 0 high */ - - reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */ - reg_w(sd, 0x35, y1 >> 16); /* JPEG bug 1 high */ - - reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */ - reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/ - reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */ - reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */ -} - -static void w9968cf_set_crop_window(struct sd *sd) -{ - int start_cropx, start_cropy, x, y, fw, fh, cw, ch, - max_width, max_height; - - if (sd->sif) { - max_width = 352; - max_height = 288; - } else { - max_width = 640; - max_height = 480; - } - - if (sd->sensor == SEN_OV7620) { - /* - * Sigh, this is dependend on the clock / framerate changes - * made by the frequency control, sick. - * - * Note we cannot use v4l2_ctrl_g_ctrl here, as we get called - * from ov519.c:setfreq() with the ctrl lock held! - */ - if (sd->freq->val == 1) { - start_cropx = 277; - start_cropy = 37; - } else { - start_cropx = 105; - start_cropy = 37; - } - } else { - start_cropx = 320; - start_cropy = 35; - } - - /* Work around to avoid FP arithmetics */ - #define SC(x) ((x) << 10) - - /* Scaling factors */ - fw = SC(sd->gspca_dev.width) / max_width; - fh = SC(sd->gspca_dev.height) / max_height; - - cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width) / fh; - ch = (fw >= fh) ? SC(sd->gspca_dev.height) / fw : max_height; - - sd->sensor_width = max_width; - sd->sensor_height = max_height; - - x = (max_width - cw) / 2; - y = (max_height - ch) / 2; - - reg_w(sd, 0x10, start_cropx + x); - reg_w(sd, 0x11, start_cropy + y); - reg_w(sd, 0x12, start_cropx + x + cw); - reg_w(sd, 0x13, start_cropy + y + ch); -} - -static void w9968cf_mode_init_regs(struct sd *sd) -{ - int val, vs_polarity, hs_polarity; - - w9968cf_set_crop_window(sd); - - reg_w(sd, 0x14, sd->gspca_dev.width); - reg_w(sd, 0x15, sd->gspca_dev.height); - - /* JPEG width & height */ - reg_w(sd, 0x30, sd->gspca_dev.width); - reg_w(sd, 0x31, sd->gspca_dev.height); - - /* Y & UV frame buffer strides (in WORD) */ - if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == - V4L2_PIX_FMT_JPEG) { - reg_w(sd, 0x2c, sd->gspca_dev.width / 2); - reg_w(sd, 0x2d, sd->gspca_dev.width / 4); - } else - reg_w(sd, 0x2c, sd->gspca_dev.width); - - reg_w(sd, 0x00, 0xbf17); /* reset everything */ - reg_w(sd, 0x00, 0xbf10); /* normal operation */ - - /* Transfer size in WORDS (for UYVY format only) */ - val = sd->gspca_dev.width * sd->gspca_dev.height; - reg_w(sd, 0x3d, val & 0xffff); /* low bits */ - reg_w(sd, 0x3e, val >> 16); /* high bits */ - - if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == - V4L2_PIX_FMT_JPEG) { - /* We may get called multiple times (usb isoc bw negotiat.) */ - jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height, - sd->gspca_dev.width, 0x22); /* JPEG 420 */ - jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual)); - w9968cf_upload_quantizationtables(sd); - v4l2_ctrl_grab(sd->jpegqual, true); - } - - /* Video Capture Control Register */ - if (sd->sensor == SEN_OV7620) { - /* Seems to work around a bug in the image sensor */ - vs_polarity = 1; - hs_polarity = 1; - } else { - vs_polarity = 1; - hs_polarity = 0; - } - - val = (vs_polarity << 12) | (hs_polarity << 11); - - /* NOTE: We may not have enough memory to do double buffering while - doing compression (amount of memory differs per model cam). - So we use the second image buffer also as jpeg stream buffer - (see w9968cf_init), and disable double buffering. */ - if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == - V4L2_PIX_FMT_JPEG) { - /* val |= 0x0002; YUV422P */ - val |= 0x0003; /* YUV420P */ - } else - val |= 0x0080; /* Enable HW double buffering */ - - /* val |= 0x0020; enable clamping */ - /* val |= 0x0008; enable (1-2-1) filter */ - /* val |= 0x000c; enable (2-3-6-3-2) filter */ - - val |= 0x8000; /* capt. enable */ - - reg_w(sd, 0x16, val); - - sd->gspca_dev.empty_packet = 0; -} - -static void w9968cf_stop0(struct sd *sd) -{ - v4l2_ctrl_grab(sd->jpegqual, false); - reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */ - reg_w(sd, 0x16, 0x0000); /* stop video capture */ -} - -/* The w9968cf docs say that a 0 sized packet means EOF (and also SOF - for the next frame). This seems to simply not be true when operating - in JPEG mode, in this case there may be empty packets within the - frame. So in JPEG mode use the JPEG SOI marker to detect SOF. - - Note to make things even more interesting the w9968cf sends *PLANAR* jpeg, - to be precise it sends: SOI, SOF, DRI, SOS, Y-data, SOS, U-data, SOS, - V-data, EOI. */ -static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* isoc packet */ - int len) /* iso packet length */ -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (w9968cf_vga_mode[gspca_dev->curr_mode].pixelformat == - V4L2_PIX_FMT_JPEG) { - if (len >= 2 && - data[0] == 0xff && - data[1] == 0xd8) { - gspca_frame_add(gspca_dev, LAST_PACKET, - NULL, 0); - gspca_frame_add(gspca_dev, FIRST_PACKET, - sd->jpeg_hdr, JPEG_HDR_SZ); - /* Strip the ff d8, our own header (which adds - huffman and quantization tables) already has this */ - len -= 2; - data += 2; - } - } else { - /* In UYVY mode an empty packet signals EOF */ - if (gspca_dev->empty_packet) { - gspca_frame_add(gspca_dev, LAST_PACKET, - NULL, 0); - gspca_frame_add(gspca_dev, FIRST_PACKET, - NULL, 0); - gspca_dev->empty_packet = 0; - } - } - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c deleted file mode 100644 index 13b8d395d210..000000000000 --- a/drivers/media/video/gspca/xirlink_cit.c +++ /dev/null @@ -1,3145 +0,0 @@ -/* - * USB IBM C-It Video Camera driver - * - * Supports Xirlink C-It Video Camera, IBM PC Camera, - * IBM NetCamera and Veo Stingray. - * - * Copyright (C) 2010 Hans de Goede <hdegoede@redhat.com> - * - * This driver is based on earlier work of: - * - * (C) Copyright 1999 Johannes Erdfelt - * (C) Copyright 1999 Randy Dunlap - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define MODULE_NAME "xirlink-cit" - -#include <linux/input.h> -#include "gspca.h" - -MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); -MODULE_DESCRIPTION("Xirlink C-IT"); -MODULE_LICENSE("GPL"); - -/* FIXME we should autodetect this */ -static int ibm_netcam_pro; -module_param(ibm_netcam_pro, int, 0); -MODULE_PARM_DESC(ibm_netcam_pro, - "Use IBM Netcamera Pro init sequences for Model 3 cams"); - -/* FIXME this should be handled through the V4L2 input selection API */ -static int rca_input; -module_param(rca_input, int, 0644); -MODULE_PARM_DESC(rca_input, - "Use rca input instead of ccd sensor on Model 3 cams"); - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - struct v4l2_ctrl *lighting; - u8 model; -#define CIT_MODEL0 0 /* bcd version 0.01 cams ie the xvp-500 */ -#define CIT_MODEL1 1 /* The model 1 - 4 nomenclature comes from the old */ -#define CIT_MODEL2 2 /* ibmcam driver */ -#define CIT_MODEL3 3 -#define CIT_MODEL4 4 -#define CIT_IBM_NETCAM_PRO 5 - u8 input_index; - u8 button_state; - u8 stop_on_control_change; - u8 sof_read; - u8 sof_len; -}; - -static void sd_stop0(struct gspca_dev *gspca_dev); - -static const struct v4l2_pix_format cif_yuv_mode[] = { - {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 2 + 4, - .colorspace = V4L2_COLORSPACE_SRGB}, - {352, 288, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 3 / 2 + 4, - .colorspace = V4L2_COLORSPACE_SRGB}, -}; - -static const struct v4l2_pix_format vga_yuv_mode[] = { - {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 2 + 4, - .colorspace = V4L2_COLORSPACE_SRGB}, - {320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 2 + 4, - .colorspace = V4L2_COLORSPACE_SRGB}, - {640, 480, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 2 + 4, - .colorspace = V4L2_COLORSPACE_SRGB}, -}; - -static const struct v4l2_pix_format model0_mode[] = { - {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 2 + 4, - .colorspace = V4L2_COLORSPACE_SRGB}, - {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 2 + 4, - .colorspace = V4L2_COLORSPACE_SRGB}, - {320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 2 + 4, - .colorspace = V4L2_COLORSPACE_SRGB}, -}; - -static const struct v4l2_pix_format model2_mode[] = { - {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, - .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 2 + 4, - .colorspace = V4L2_COLORSPACE_SRGB}, - {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 2 + 4, - .colorspace = V4L2_COLORSPACE_SRGB}, - {320, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 + 4, - .colorspace = V4L2_COLORSPACE_SRGB}, - {352, 288, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 + 4, - .colorspace = V4L2_COLORSPACE_SRGB}, -}; - -/* - * 01.01.08 - Added for RCA video in support -LO - * This struct is used to init the Model3 cam to use the RCA video in port - * instead of the CCD sensor. - */ -static const u16 rca_initdata[][3] = { - {0, 0x0000, 0x010c}, - {0, 0x0006, 0x012c}, - {0, 0x0078, 0x012d}, - {0, 0x0046, 0x012f}, - {0, 0xd141, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfea8, 0x0124}, - {1, 0x0000, 0x0116}, - {0, 0x0064, 0x0116}, - {1, 0x0000, 0x0115}, - {0, 0x0003, 0x0115}, - {0, 0x0008, 0x0123}, - {0, 0x0000, 0x0117}, - {0, 0x0000, 0x0112}, - {0, 0x0080, 0x0100}, - {0, 0x0000, 0x0100}, - {1, 0x0000, 0x0116}, - {0, 0x0060, 0x0116}, - {0, 0x0002, 0x0112}, - {0, 0x0000, 0x0123}, - {0, 0x0001, 0x0117}, - {0, 0x0040, 0x0108}, - {0, 0x0019, 0x012c}, - {0, 0x0040, 0x0116}, - {0, 0x000a, 0x0115}, - {0, 0x000b, 0x0115}, - {0, 0x0078, 0x012d}, - {0, 0x0046, 0x012f}, - {0, 0xd141, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfea8, 0x0124}, - {0, 0x0064, 0x0116}, - {0, 0x0000, 0x0115}, - {0, 0x0001, 0x0115}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00aa, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00f2, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x000f, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00f8, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00fc, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00f9, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x003c, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xffff, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0027, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0019, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0021, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0006, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0045, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002a, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x000e, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002b, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00f4, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002c, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0004, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002d, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0014, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002e, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0003, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x002f, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0003, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0014, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0053, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0x0000, 0x0101}, - {0, 0x00a0, 0x0103}, - {0, 0x0078, 0x0105}, - {0, 0x0000, 0x010a}, - {0, 0x0024, 0x010b}, - {0, 0x0028, 0x0119}, - {0, 0x0088, 0x011b}, - {0, 0x0002, 0x011d}, - {0, 0x0003, 0x011e}, - {0, 0x0000, 0x0129}, - {0, 0x00fc, 0x012b}, - {0, 0x0008, 0x0102}, - {0, 0x0000, 0x0104}, - {0, 0x0008, 0x011a}, - {0, 0x0028, 0x011c}, - {0, 0x0021, 0x012a}, - {0, 0x0000, 0x0118}, - {0, 0x0000, 0x0132}, - {0, 0x0000, 0x0109}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0031, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x00dc, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0032, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0020, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0001, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0040, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0037, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0030, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0xfff9, 0x0124}, - {0, 0x0086, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0038, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0008, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0x0000, 0x0127}, - {0, 0xfff8, 0x0124}, - {0, 0xfffd, 0x0124}, - {0, 0xfffa, 0x0124}, - {0, 0x0003, 0x0111}, -}; - -/* TESTME the old ibmcam driver repeats certain commands to Model1 cameras, we - do the same for now (testing needed to see if this is really necessary) */ -static const int cit_model1_ntries = 5; -static const int cit_model1_ntries2 = 2; - -static int cit_write_reg(struct gspca_dev *gspca_dev, u16 value, u16 index) -{ - struct usb_device *udev = gspca_dev->dev; - int err; - - err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, - value, index, NULL, 0, 1000); - if (err < 0) - pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n", - index, value, err); - - return 0; -} - -static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index, int verbose) -{ - struct usb_device *udev = gspca_dev->dev; - __u8 *buf = gspca_dev->usb_buf; - int res; - - res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x01, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, - 0x00, index, buf, 8, 1000); - if (res < 0) { - pr_err("Failed to read a register (index 0x%04X, error %d)\n", - index, res); - return res; - } - - if (verbose) - PDEBUG(D_PROBE, "Register %04x value: %02x", index, buf[0]); - - return 0; -} - -/* - * cit_send_FF_04_02() - * - * This procedure sends magic 3-command prefix to the camera. - * The purpose of this prefix is not known. - * - * History: - * 1/2/00 Created. - */ -static void cit_send_FF_04_02(struct gspca_dev *gspca_dev) -{ - cit_write_reg(gspca_dev, 0x00FF, 0x0127); - cit_write_reg(gspca_dev, 0x0004, 0x0124); - cit_write_reg(gspca_dev, 0x0002, 0x0124); -} - -static void cit_send_00_04_06(struct gspca_dev *gspca_dev) -{ - cit_write_reg(gspca_dev, 0x0000, 0x0127); - cit_write_reg(gspca_dev, 0x0004, 0x0124); - cit_write_reg(gspca_dev, 0x0006, 0x0124); -} - -static void cit_send_x_00(struct gspca_dev *gspca_dev, unsigned short x) -{ - cit_write_reg(gspca_dev, x, 0x0127); - cit_write_reg(gspca_dev, 0x0000, 0x0124); -} - -static void cit_send_x_00_05(struct gspca_dev *gspca_dev, unsigned short x) -{ - cit_send_x_00(gspca_dev, x); - cit_write_reg(gspca_dev, 0x0005, 0x0124); -} - -static void cit_send_x_00_05_02(struct gspca_dev *gspca_dev, unsigned short x) -{ - cit_write_reg(gspca_dev, x, 0x0127); - cit_write_reg(gspca_dev, 0x0000, 0x0124); - cit_write_reg(gspca_dev, 0x0005, 0x0124); - cit_write_reg(gspca_dev, 0x0002, 0x0124); -} - -static void cit_send_x_01_00_05(struct gspca_dev *gspca_dev, u16 x) -{ - cit_write_reg(gspca_dev, x, 0x0127); - cit_write_reg(gspca_dev, 0x0001, 0x0124); - cit_write_reg(gspca_dev, 0x0000, 0x0124); - cit_write_reg(gspca_dev, 0x0005, 0x0124); -} - -static void cit_send_x_00_05_02_01(struct gspca_dev *gspca_dev, u16 x) -{ - cit_write_reg(gspca_dev, x, 0x0127); - cit_write_reg(gspca_dev, 0x0000, 0x0124); - cit_write_reg(gspca_dev, 0x0005, 0x0124); - cit_write_reg(gspca_dev, 0x0002, 0x0124); - cit_write_reg(gspca_dev, 0x0001, 0x0124); -} - -static void cit_send_x_00_05_02_08_01(struct gspca_dev *gspca_dev, u16 x) -{ - cit_write_reg(gspca_dev, x, 0x0127); - cit_write_reg(gspca_dev, 0x0000, 0x0124); - cit_write_reg(gspca_dev, 0x0005, 0x0124); - cit_write_reg(gspca_dev, 0x0002, 0x0124); - cit_write_reg(gspca_dev, 0x0008, 0x0124); - cit_write_reg(gspca_dev, 0x0001, 0x0124); -} - -static void cit_Packet_Format1(struct gspca_dev *gspca_dev, u16 fkey, u16 val) -{ - cit_send_x_01_00_05(gspca_dev, 0x0088); - cit_send_x_00_05(gspca_dev, fkey); - cit_send_x_00_05_02_08_01(gspca_dev, val); - cit_send_x_00_05(gspca_dev, 0x0088); - cit_send_x_00_05_02_01(gspca_dev, fkey); - cit_send_x_00_05(gspca_dev, 0x0089); - cit_send_x_00(gspca_dev, fkey); - cit_send_00_04_06(gspca_dev); - cit_read_reg(gspca_dev, 0x0126, 0); - cit_send_FF_04_02(gspca_dev); -} - -static void cit_PacketFormat2(struct gspca_dev *gspca_dev, u16 fkey, u16 val) -{ - cit_send_x_01_00_05(gspca_dev, 0x0088); - cit_send_x_00_05(gspca_dev, fkey); - cit_send_x_00_05_02(gspca_dev, val); -} - -static void cit_model2_Packet2(struct gspca_dev *gspca_dev) -{ - cit_write_reg(gspca_dev, 0x00ff, 0x012d); - cit_write_reg(gspca_dev, 0xfea3, 0x0124); -} - -static void cit_model2_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2) -{ - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x00ff, 0x012e); - cit_write_reg(gspca_dev, v1, 0x012f); - cit_write_reg(gspca_dev, 0x00ff, 0x0130); - cit_write_reg(gspca_dev, 0xc719, 0x0124); - cit_write_reg(gspca_dev, v2, 0x0127); - - cit_model2_Packet2(gspca_dev); -} - -/* - * cit_model3_Packet1() - * - * 00_0078_012d - * 00_0097_012f - * 00_d141_0124 - * 00_0096_0127 - * 00_fea8_0124 -*/ -static void cit_model3_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2) -{ - cit_write_reg(gspca_dev, 0x0078, 0x012d); - cit_write_reg(gspca_dev, v1, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, v2, 0x0127); - cit_write_reg(gspca_dev, 0xfea8, 0x0124); -} - -static void cit_model4_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2) -{ - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, v1, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, v2, 0x0127); - cit_write_reg(gspca_dev, 0xfea8, 0x0124); -} - -static void cit_model4_BrightnessPacket(struct gspca_dev *gspca_dev, u16 val) -{ - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x0026, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, val, 0x0127); - cit_write_reg(gspca_dev, 0x00aa, 0x0130); - cit_write_reg(gspca_dev, 0x82a8, 0x0124); - cit_write_reg(gspca_dev, 0x0038, 0x012d); - cit_write_reg(gspca_dev, 0x0004, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0xfffa, 0x0124); -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - - sd->model = id->driver_info; - if (sd->model == CIT_MODEL3 && ibm_netcam_pro) - sd->model = CIT_IBM_NETCAM_PRO; - - cam = &gspca_dev->cam; - switch (sd->model) { - case CIT_MODEL0: - cam->cam_mode = model0_mode; - cam->nmodes = ARRAY_SIZE(model0_mode); - sd->sof_len = 4; - break; - case CIT_MODEL1: - cam->cam_mode = cif_yuv_mode; - cam->nmodes = ARRAY_SIZE(cif_yuv_mode); - sd->sof_len = 4; - break; - case CIT_MODEL2: - cam->cam_mode = model2_mode + 1; /* no 160x120 */ - cam->nmodes = 3; - break; - case CIT_MODEL3: - cam->cam_mode = vga_yuv_mode; - cam->nmodes = ARRAY_SIZE(vga_yuv_mode); - sd->stop_on_control_change = 1; - sd->sof_len = 4; - break; - case CIT_MODEL4: - cam->cam_mode = model2_mode; - cam->nmodes = ARRAY_SIZE(model2_mode); - break; - case CIT_IBM_NETCAM_PRO: - cam->cam_mode = vga_yuv_mode; - cam->nmodes = 2; /* no 640 x 480 */ - cam->input_flags = V4L2_IN_ST_VFLIP; - sd->stop_on_control_change = 1; - sd->sof_len = 4; - break; - } - - return 0; -} - -static int cit_init_model0(struct gspca_dev *gspca_dev) -{ - cit_write_reg(gspca_dev, 0x0000, 0x0100); /* turn on led */ - cit_write_reg(gspca_dev, 0x0001, 0x0112); /* turn on autogain ? */ - cit_write_reg(gspca_dev, 0x0000, 0x0400); - cit_write_reg(gspca_dev, 0x0001, 0x0400); - cit_write_reg(gspca_dev, 0x0000, 0x0420); - cit_write_reg(gspca_dev, 0x0001, 0x0420); - cit_write_reg(gspca_dev, 0x000d, 0x0409); - cit_write_reg(gspca_dev, 0x0002, 0x040a); - cit_write_reg(gspca_dev, 0x0018, 0x0405); - cit_write_reg(gspca_dev, 0x0008, 0x0435); - cit_write_reg(gspca_dev, 0x0026, 0x040b); - cit_write_reg(gspca_dev, 0x0007, 0x0437); - cit_write_reg(gspca_dev, 0x0015, 0x042f); - cit_write_reg(gspca_dev, 0x002b, 0x0439); - cit_write_reg(gspca_dev, 0x0026, 0x043a); - cit_write_reg(gspca_dev, 0x0008, 0x0438); - cit_write_reg(gspca_dev, 0x001e, 0x042b); - cit_write_reg(gspca_dev, 0x0041, 0x042c); - - return 0; -} - -static int cit_init_ibm_netcam_pro(struct gspca_dev *gspca_dev) -{ - cit_read_reg(gspca_dev, 0x128, 1); - cit_write_reg(gspca_dev, 0x0003, 0x0133); - cit_write_reg(gspca_dev, 0x0000, 0x0117); - cit_write_reg(gspca_dev, 0x0008, 0x0123); - cit_write_reg(gspca_dev, 0x0000, 0x0100); - cit_read_reg(gspca_dev, 0x0116, 0); - cit_write_reg(gspca_dev, 0x0060, 0x0116); - cit_write_reg(gspca_dev, 0x0002, 0x0112); - cit_write_reg(gspca_dev, 0x0000, 0x0133); - cit_write_reg(gspca_dev, 0x0000, 0x0123); - cit_write_reg(gspca_dev, 0x0001, 0x0117); - cit_write_reg(gspca_dev, 0x0040, 0x0108); - cit_write_reg(gspca_dev, 0x0019, 0x012c); - cit_write_reg(gspca_dev, 0x0060, 0x0116); - cit_write_reg(gspca_dev, 0x0002, 0x0115); - cit_write_reg(gspca_dev, 0x000b, 0x0115); - - cit_write_reg(gspca_dev, 0x0078, 0x012d); - cit_write_reg(gspca_dev, 0x0001, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x0079, 0x012d); - cit_write_reg(gspca_dev, 0x00ff, 0x0130); - cit_write_reg(gspca_dev, 0xcd41, 0x0124); - cit_write_reg(gspca_dev, 0xfffa, 0x0124); - cit_read_reg(gspca_dev, 0x0126, 1); - - cit_model3_Packet1(gspca_dev, 0x0000, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0000, 0x0001); - cit_model3_Packet1(gspca_dev, 0x000b, 0x0000); - cit_model3_Packet1(gspca_dev, 0x000c, 0x0008); - cit_model3_Packet1(gspca_dev, 0x000d, 0x003a); - cit_model3_Packet1(gspca_dev, 0x000e, 0x0060); - cit_model3_Packet1(gspca_dev, 0x000f, 0x0060); - cit_model3_Packet1(gspca_dev, 0x0010, 0x0008); - cit_model3_Packet1(gspca_dev, 0x0011, 0x0004); - cit_model3_Packet1(gspca_dev, 0x0012, 0x0028); - cit_model3_Packet1(gspca_dev, 0x0013, 0x0002); - cit_model3_Packet1(gspca_dev, 0x0014, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0015, 0x00fb); - cit_model3_Packet1(gspca_dev, 0x0016, 0x0002); - cit_model3_Packet1(gspca_dev, 0x0017, 0x0037); - cit_model3_Packet1(gspca_dev, 0x0018, 0x0036); - cit_model3_Packet1(gspca_dev, 0x001e, 0x0000); - cit_model3_Packet1(gspca_dev, 0x001f, 0x0008); - cit_model3_Packet1(gspca_dev, 0x0020, 0x00c1); - cit_model3_Packet1(gspca_dev, 0x0021, 0x0034); - cit_model3_Packet1(gspca_dev, 0x0022, 0x0034); - cit_model3_Packet1(gspca_dev, 0x0025, 0x0002); - cit_model3_Packet1(gspca_dev, 0x0028, 0x0022); - cit_model3_Packet1(gspca_dev, 0x0029, 0x000a); - cit_model3_Packet1(gspca_dev, 0x002b, 0x0000); - cit_model3_Packet1(gspca_dev, 0x002c, 0x0000); - cit_model3_Packet1(gspca_dev, 0x002d, 0x00ff); - cit_model3_Packet1(gspca_dev, 0x002e, 0x00ff); - cit_model3_Packet1(gspca_dev, 0x002f, 0x00ff); - cit_model3_Packet1(gspca_dev, 0x0030, 0x00ff); - cit_model3_Packet1(gspca_dev, 0x0031, 0x00ff); - cit_model3_Packet1(gspca_dev, 0x0032, 0x0007); - cit_model3_Packet1(gspca_dev, 0x0033, 0x0005); - cit_model3_Packet1(gspca_dev, 0x0037, 0x0040); - cit_model3_Packet1(gspca_dev, 0x0039, 0x0000); - cit_model3_Packet1(gspca_dev, 0x003a, 0x0000); - cit_model3_Packet1(gspca_dev, 0x003b, 0x0001); - cit_model3_Packet1(gspca_dev, 0x003c, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0040, 0x000c); - cit_model3_Packet1(gspca_dev, 0x0041, 0x00fb); - cit_model3_Packet1(gspca_dev, 0x0042, 0x0002); - cit_model3_Packet1(gspca_dev, 0x0043, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0045, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0046, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0047, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0048, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0049, 0x0000); - cit_model3_Packet1(gspca_dev, 0x004a, 0x00ff); - cit_model3_Packet1(gspca_dev, 0x004b, 0x00ff); - cit_model3_Packet1(gspca_dev, 0x004c, 0x00ff); - cit_model3_Packet1(gspca_dev, 0x004f, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0050, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0051, 0x0002); - cit_model3_Packet1(gspca_dev, 0x0055, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0056, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0057, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0058, 0x0002); - cit_model3_Packet1(gspca_dev, 0x0059, 0x0000); - cit_model3_Packet1(gspca_dev, 0x005c, 0x0016); - cit_model3_Packet1(gspca_dev, 0x005d, 0x0022); - cit_model3_Packet1(gspca_dev, 0x005e, 0x003c); - cit_model3_Packet1(gspca_dev, 0x005f, 0x0050); - cit_model3_Packet1(gspca_dev, 0x0060, 0x0044); - cit_model3_Packet1(gspca_dev, 0x0061, 0x0005); - cit_model3_Packet1(gspca_dev, 0x006a, 0x007e); - cit_model3_Packet1(gspca_dev, 0x006f, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0072, 0x001b); - cit_model3_Packet1(gspca_dev, 0x0073, 0x0005); - cit_model3_Packet1(gspca_dev, 0x0074, 0x000a); - cit_model3_Packet1(gspca_dev, 0x0075, 0x001b); - cit_model3_Packet1(gspca_dev, 0x0076, 0x002a); - cit_model3_Packet1(gspca_dev, 0x0077, 0x003c); - cit_model3_Packet1(gspca_dev, 0x0078, 0x0050); - cit_model3_Packet1(gspca_dev, 0x007b, 0x0000); - cit_model3_Packet1(gspca_dev, 0x007c, 0x0011); - cit_model3_Packet1(gspca_dev, 0x007d, 0x0024); - cit_model3_Packet1(gspca_dev, 0x007e, 0x0043); - cit_model3_Packet1(gspca_dev, 0x007f, 0x005a); - cit_model3_Packet1(gspca_dev, 0x0084, 0x0020); - cit_model3_Packet1(gspca_dev, 0x0085, 0x0033); - cit_model3_Packet1(gspca_dev, 0x0086, 0x000a); - cit_model3_Packet1(gspca_dev, 0x0087, 0x0030); - cit_model3_Packet1(gspca_dev, 0x0088, 0x0070); - cit_model3_Packet1(gspca_dev, 0x008b, 0x0008); - cit_model3_Packet1(gspca_dev, 0x008f, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0090, 0x0006); - cit_model3_Packet1(gspca_dev, 0x0091, 0x0028); - cit_model3_Packet1(gspca_dev, 0x0092, 0x005a); - cit_model3_Packet1(gspca_dev, 0x0093, 0x0082); - cit_model3_Packet1(gspca_dev, 0x0096, 0x0014); - cit_model3_Packet1(gspca_dev, 0x0097, 0x0020); - cit_model3_Packet1(gspca_dev, 0x0098, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00b0, 0x0046); - cit_model3_Packet1(gspca_dev, 0x00b1, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00b2, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00b3, 0x0004); - cit_model3_Packet1(gspca_dev, 0x00b4, 0x0007); - cit_model3_Packet1(gspca_dev, 0x00b6, 0x0002); - cit_model3_Packet1(gspca_dev, 0x00b7, 0x0004); - cit_model3_Packet1(gspca_dev, 0x00bb, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00bc, 0x0001); - cit_model3_Packet1(gspca_dev, 0x00bd, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00bf, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00c0, 0x00c8); - cit_model3_Packet1(gspca_dev, 0x00c1, 0x0014); - cit_model3_Packet1(gspca_dev, 0x00c2, 0x0001); - cit_model3_Packet1(gspca_dev, 0x00c3, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00c4, 0x0004); - cit_model3_Packet1(gspca_dev, 0x00cb, 0x00bf); - cit_model3_Packet1(gspca_dev, 0x00cc, 0x00bf); - cit_model3_Packet1(gspca_dev, 0x00cd, 0x00bf); - cit_model3_Packet1(gspca_dev, 0x00ce, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00cf, 0x0020); - cit_model3_Packet1(gspca_dev, 0x00d0, 0x0040); - cit_model3_Packet1(gspca_dev, 0x00d1, 0x00bf); - cit_model3_Packet1(gspca_dev, 0x00d1, 0x00bf); - cit_model3_Packet1(gspca_dev, 0x00d2, 0x00bf); - cit_model3_Packet1(gspca_dev, 0x00d3, 0x00bf); - cit_model3_Packet1(gspca_dev, 0x00ea, 0x0008); - cit_model3_Packet1(gspca_dev, 0x00eb, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00ec, 0x00e8); - cit_model3_Packet1(gspca_dev, 0x00ed, 0x0001); - cit_model3_Packet1(gspca_dev, 0x00ef, 0x0022); - cit_model3_Packet1(gspca_dev, 0x00f0, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00f2, 0x0028); - cit_model3_Packet1(gspca_dev, 0x00f4, 0x0002); - cit_model3_Packet1(gspca_dev, 0x00f5, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00fa, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00fb, 0x0001); - cit_model3_Packet1(gspca_dev, 0x00fc, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00fd, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00fe, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00ff, 0x0000); - - cit_model3_Packet1(gspca_dev, 0x00be, 0x0003); - cit_model3_Packet1(gspca_dev, 0x00c8, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00c9, 0x0020); - cit_model3_Packet1(gspca_dev, 0x00ca, 0x0040); - cit_model3_Packet1(gspca_dev, 0x0053, 0x0001); - cit_model3_Packet1(gspca_dev, 0x0082, 0x000e); - cit_model3_Packet1(gspca_dev, 0x0083, 0x0020); - cit_model3_Packet1(gspca_dev, 0x0034, 0x003c); - cit_model3_Packet1(gspca_dev, 0x006e, 0x0055); - cit_model3_Packet1(gspca_dev, 0x0062, 0x0005); - cit_model3_Packet1(gspca_dev, 0x0063, 0x0008); - cit_model3_Packet1(gspca_dev, 0x0066, 0x000a); - cit_model3_Packet1(gspca_dev, 0x0067, 0x0006); - cit_model3_Packet1(gspca_dev, 0x006b, 0x0010); - cit_model3_Packet1(gspca_dev, 0x005a, 0x0001); - cit_model3_Packet1(gspca_dev, 0x005b, 0x000a); - cit_model3_Packet1(gspca_dev, 0x0023, 0x0006); - cit_model3_Packet1(gspca_dev, 0x0026, 0x0004); - cit_model3_Packet1(gspca_dev, 0x0036, 0x0069); - cit_model3_Packet1(gspca_dev, 0x0038, 0x0064); - cit_model3_Packet1(gspca_dev, 0x003d, 0x0003); - cit_model3_Packet1(gspca_dev, 0x003e, 0x0001); - cit_model3_Packet1(gspca_dev, 0x00b8, 0x0014); - cit_model3_Packet1(gspca_dev, 0x00b9, 0x0014); - cit_model3_Packet1(gspca_dev, 0x00e6, 0x0004); - cit_model3_Packet1(gspca_dev, 0x00e8, 0x0001); - - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->model) { - case CIT_MODEL0: - cit_init_model0(gspca_dev); - sd_stop0(gspca_dev); - break; - case CIT_MODEL1: - case CIT_MODEL2: - case CIT_MODEL3: - case CIT_MODEL4: - break; /* All is done in sd_start */ - case CIT_IBM_NETCAM_PRO: - cit_init_ibm_netcam_pro(gspca_dev); - sd_stop0(gspca_dev); - break; - } - return 0; -} - -static int cit_set_brightness(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i; - - switch (sd->model) { - case CIT_MODEL0: - case CIT_IBM_NETCAM_PRO: - /* No (known) brightness control for these */ - break; - case CIT_MODEL1: - /* Model 1: Brightness range 0 - 63 */ - cit_Packet_Format1(gspca_dev, 0x0031, val); - cit_Packet_Format1(gspca_dev, 0x0032, val); - cit_Packet_Format1(gspca_dev, 0x0033, val); - break; - case CIT_MODEL2: - /* Model 2: Brightness range 0x60 - 0xee */ - /* Scale 0 - 63 to 0x60 - 0xee */ - i = 0x60 + val * 2254 / 1000; - cit_model2_Packet1(gspca_dev, 0x001a, i); - break; - case CIT_MODEL3: - /* Model 3: Brightness range 'i' in [0x0C..0x3F] */ - i = val; - if (i < 0x0c) - i = 0x0c; - cit_model3_Packet1(gspca_dev, 0x0036, i); - break; - case CIT_MODEL4: - /* Model 4: Brightness range 'i' in [0x04..0xb4] */ - /* Scale 0 - 63 to 0x04 - 0xb4 */ - i = 0x04 + val * 2794 / 1000; - cit_model4_BrightnessPacket(gspca_dev, i); - break; - } - - return 0; -} - -static int cit_set_contrast(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->model) { - case CIT_MODEL0: { - int i; - /* gain 0-15, 0-20 -> 0-15 */ - i = val * 1000 / 1333; - cit_write_reg(gspca_dev, i, 0x0422); - /* gain 0-31, may not be lower then 0x0422, 0-20 -> 0-31 */ - i = val * 2000 / 1333; - cit_write_reg(gspca_dev, i, 0x0423); - /* gain 0-127, may not be lower then 0x0423, 0-20 -> 0-63 */ - i = val * 4000 / 1333; - cit_write_reg(gspca_dev, i, 0x0424); - /* gain 0-127, may not be lower then 0x0424, , 0-20 -> 0-127 */ - i = val * 8000 / 1333; - cit_write_reg(gspca_dev, i, 0x0425); - break; - } - case CIT_MODEL2: - case CIT_MODEL4: - /* These models do not have this control. */ - break; - case CIT_MODEL1: - { - /* Scale 0 - 20 to 15 - 0 */ - int i, new_contrast = (20 - val) * 1000 / 1333; - for (i = 0; i < cit_model1_ntries; i++) { - cit_Packet_Format1(gspca_dev, 0x0014, new_contrast); - cit_send_FF_04_02(gspca_dev); - } - break; - } - case CIT_MODEL3: - { /* Preset hardware values */ - static const struct { - unsigned short cv1; - unsigned short cv2; - unsigned short cv3; - } cv[7] = { - { 0x05, 0x05, 0x0f }, /* Minimum */ - { 0x04, 0x04, 0x16 }, - { 0x02, 0x03, 0x16 }, - { 0x02, 0x08, 0x16 }, - { 0x01, 0x0c, 0x16 }, - { 0x01, 0x0e, 0x16 }, - { 0x01, 0x10, 0x16 } /* Maximum */ - }; - int i = val / 3; - cit_model3_Packet1(gspca_dev, 0x0067, cv[i].cv1); - cit_model3_Packet1(gspca_dev, 0x005b, cv[i].cv2); - cit_model3_Packet1(gspca_dev, 0x005c, cv[i].cv3); - break; - } - case CIT_IBM_NETCAM_PRO: - cit_model3_Packet1(gspca_dev, 0x005b, val + 1); - break; - } - return 0; -} - -static int cit_set_hue(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->model) { - case CIT_MODEL0: - case CIT_MODEL1: - case CIT_IBM_NETCAM_PRO: - /* No hue control for these models */ - break; - case CIT_MODEL2: - cit_model2_Packet1(gspca_dev, 0x0024, val); - /* cit_model2_Packet1(gspca_dev, 0x0020, sat); */ - break; - case CIT_MODEL3: { - /* Model 3: Brightness range 'i' in [0x05..0x37] */ - /* TESTME according to the ibmcam driver this does not work */ - if (0) { - /* Scale 0 - 127 to 0x05 - 0x37 */ - int i = 0x05 + val * 1000 / 2540; - cit_model3_Packet1(gspca_dev, 0x007e, i); - } - break; - } - case CIT_MODEL4: - /* HDG: taken from ibmcam, setting the color gains does not - * really belong here. - * - * I am not sure r/g/b_gain variables exactly control gain - * of those channels. Most likely they subtly change some - * very internal image processing settings in the camera. - * In any case, here is what they do, and feel free to tweak: - * - * r_gain: seriously affects red gain - * g_gain: seriously affects green gain - * b_gain: seriously affects blue gain - * hue: changes average color from violet (0) to red (0xFF) - */ - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x001e, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 160, 0x0127); /* Green gain */ - cit_write_reg(gspca_dev, 160, 0x012e); /* Red gain */ - cit_write_reg(gspca_dev, 160, 0x0130); /* Blue gain */ - cit_write_reg(gspca_dev, 0x8a28, 0x0124); - cit_write_reg(gspca_dev, val, 0x012d); /* Hue */ - cit_write_reg(gspca_dev, 0xf545, 0x0124); - break; - } - return 0; -} - -static int cit_set_sharpness(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->model) { - case CIT_MODEL0: - case CIT_MODEL2: - case CIT_MODEL4: - case CIT_IBM_NETCAM_PRO: - /* These models do not have this control */ - break; - case CIT_MODEL1: { - int i; - const unsigned short sa[] = { - 0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a }; - - for (i = 0; i < cit_model1_ntries; i++) - cit_PacketFormat2(gspca_dev, 0x0013, sa[val]); - break; - } - case CIT_MODEL3: - { /* - * "Use a table of magic numbers. - * This setting doesn't really change much. - * But that's how Windows does it." - */ - static const struct { - unsigned short sv1; - unsigned short sv2; - unsigned short sv3; - unsigned short sv4; - } sv[7] = { - { 0x00, 0x00, 0x05, 0x14 }, /* Smoothest */ - { 0x01, 0x04, 0x05, 0x14 }, - { 0x02, 0x04, 0x05, 0x14 }, - { 0x03, 0x04, 0x05, 0x14 }, - { 0x03, 0x05, 0x05, 0x14 }, - { 0x03, 0x06, 0x05, 0x14 }, - { 0x03, 0x07, 0x05, 0x14 } /* Sharpest */ - }; - cit_model3_Packet1(gspca_dev, 0x0060, sv[val].sv1); - cit_model3_Packet1(gspca_dev, 0x0061, sv[val].sv2); - cit_model3_Packet1(gspca_dev, 0x0062, sv[val].sv3); - cit_model3_Packet1(gspca_dev, 0x0063, sv[val].sv4); - break; - } - } - return 0; -} - -/* - * cit_set_lighting() - * - * Camera model 1: - * We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low. - * - * Camera model 2: - * We have 16 levels of lighting, 0 for bright light and up to 15 for - * low light. But values above 5 or so are useless because camera is - * not really capable to produce anything worth viewing at such light. - * This setting may be altered only in certain camera state. - * - * Low lighting forces slower FPS. - * - * History: - * 1/5/00 Created. - * 2/20/00 Added support for Model 2 cameras. - */ -static void cit_set_lighting(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->model) { - case CIT_MODEL0: - case CIT_MODEL2: - case CIT_MODEL3: - case CIT_MODEL4: - case CIT_IBM_NETCAM_PRO: - break; - case CIT_MODEL1: { - int i; - for (i = 0; i < cit_model1_ntries; i++) - cit_Packet_Format1(gspca_dev, 0x0027, val); - break; - } - } -} - -static void cit_set_hflip(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->model) { - case CIT_MODEL0: - if (val) - cit_write_reg(gspca_dev, 0x0020, 0x0115); - else - cit_write_reg(gspca_dev, 0x0040, 0x0115); - break; - case CIT_MODEL1: - case CIT_MODEL2: - case CIT_MODEL3: - case CIT_MODEL4: - case CIT_IBM_NETCAM_PRO: - break; - } -} - -static int cit_restart_stream(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->model) { - case CIT_MODEL0: - case CIT_MODEL1: - cit_write_reg(gspca_dev, 0x0001, 0x0114); - /* Fall through */ - case CIT_MODEL2: - case CIT_MODEL4: - cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */ - usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe); - break; - case CIT_MODEL3: - case CIT_IBM_NETCAM_PRO: - cit_write_reg(gspca_dev, 0x0001, 0x0114); - cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */ - usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe); - /* Clear button events from while we were not streaming */ - cit_write_reg(gspca_dev, 0x0001, 0x0113); - break; - } - - sd->sof_read = 0; - - return 0; -} - -static int cit_get_packet_size(struct gspca_dev *gspca_dev) -{ - struct usb_host_interface *alt; - struct usb_interface *intf; - - intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); - alt = usb_altnum_to_altsetting(intf, gspca_dev->alt); - if (!alt) { - pr_err("Couldn't get altsetting\n"); - return -EIO; - } - - return le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); -} - -/* Calculate the clockdiv giving us max fps given the available bandwidth */ -static int cit_get_clock_div(struct gspca_dev *gspca_dev) -{ - int clock_div = 7; /* 0=30 1=25 2=20 3=15 4=12 5=7.5 6=6 7=3fps ?? */ - int fps[8] = { 30, 25, 20, 15, 12, 8, 6, 3 }; - int packet_size; - - packet_size = cit_get_packet_size(gspca_dev); - if (packet_size < 0) - return packet_size; - - while (clock_div > 3 && - 1000 * packet_size > - gspca_dev->width * gspca_dev->height * - fps[clock_div - 1] * 3 / 2) - clock_div--; - - PDEBUG(D_PROBE, - "PacketSize: %d, res: %dx%d -> using clockdiv: %d (%d fps)", - packet_size, gspca_dev->width, gspca_dev->height, clock_div, - fps[clock_div]); - - return clock_div; -} - -static int cit_start_model0(struct gspca_dev *gspca_dev) -{ - const unsigned short compression = 0; /* 0=none, 7=best frame rate */ - int clock_div; - - clock_div = cit_get_clock_div(gspca_dev); - if (clock_div < 0) - return clock_div; - - cit_write_reg(gspca_dev, 0x0000, 0x0100); /* turn on led */ - cit_write_reg(gspca_dev, 0x0003, 0x0438); - cit_write_reg(gspca_dev, 0x001e, 0x042b); - cit_write_reg(gspca_dev, 0x0041, 0x042c); - cit_write_reg(gspca_dev, 0x0008, 0x0436); - cit_write_reg(gspca_dev, 0x0024, 0x0403); - cit_write_reg(gspca_dev, 0x002c, 0x0404); - cit_write_reg(gspca_dev, 0x0002, 0x0426); - cit_write_reg(gspca_dev, 0x0014, 0x0427); - - switch (gspca_dev->width) { - case 160: /* 160x120 */ - cit_write_reg(gspca_dev, 0x0004, 0x010b); - cit_write_reg(gspca_dev, 0x0001, 0x010a); - cit_write_reg(gspca_dev, 0x0010, 0x0102); - cit_write_reg(gspca_dev, 0x00a0, 0x0103); - cit_write_reg(gspca_dev, 0x0000, 0x0104); - cit_write_reg(gspca_dev, 0x0078, 0x0105); - break; - - case 176: /* 176x144 */ - cit_write_reg(gspca_dev, 0x0006, 0x010b); - cit_write_reg(gspca_dev, 0x0000, 0x010a); - cit_write_reg(gspca_dev, 0x0005, 0x0102); - cit_write_reg(gspca_dev, 0x00b0, 0x0103); - cit_write_reg(gspca_dev, 0x0000, 0x0104); - cit_write_reg(gspca_dev, 0x0090, 0x0105); - break; - - case 320: /* 320x240 */ - cit_write_reg(gspca_dev, 0x0008, 0x010b); - cit_write_reg(gspca_dev, 0x0004, 0x010a); - cit_write_reg(gspca_dev, 0x0005, 0x0102); - cit_write_reg(gspca_dev, 0x00a0, 0x0103); - cit_write_reg(gspca_dev, 0x0010, 0x0104); - cit_write_reg(gspca_dev, 0x0078, 0x0105); - break; - } - - cit_write_reg(gspca_dev, compression, 0x0109); - cit_write_reg(gspca_dev, clock_div, 0x0111); - - return 0; -} - -static int cit_start_model1(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i, clock_div; - - clock_div = cit_get_clock_div(gspca_dev); - if (clock_div < 0) - return clock_div; - - cit_read_reg(gspca_dev, 0x0128, 1); - cit_read_reg(gspca_dev, 0x0100, 0); - cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */ - cit_read_reg(gspca_dev, 0x0100, 0); - cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */ - cit_read_reg(gspca_dev, 0x0100, 0); - cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */ - cit_write_reg(gspca_dev, 0x01, 0x0108); - - cit_write_reg(gspca_dev, 0x03, 0x0112); - cit_read_reg(gspca_dev, 0x0115, 0); - cit_write_reg(gspca_dev, 0x06, 0x0115); - cit_read_reg(gspca_dev, 0x0116, 0); - cit_write_reg(gspca_dev, 0x44, 0x0116); - cit_read_reg(gspca_dev, 0x0116, 0); - cit_write_reg(gspca_dev, 0x40, 0x0116); - cit_read_reg(gspca_dev, 0x0115, 0); - cit_write_reg(gspca_dev, 0x0e, 0x0115); - cit_write_reg(gspca_dev, 0x19, 0x012c); - - cit_Packet_Format1(gspca_dev, 0x00, 0x1e); - cit_Packet_Format1(gspca_dev, 0x39, 0x0d); - cit_Packet_Format1(gspca_dev, 0x39, 0x09); - cit_Packet_Format1(gspca_dev, 0x3b, 0x00); - cit_Packet_Format1(gspca_dev, 0x28, 0x22); - cit_Packet_Format1(gspca_dev, 0x27, 0x00); - cit_Packet_Format1(gspca_dev, 0x2b, 0x1f); - cit_Packet_Format1(gspca_dev, 0x39, 0x08); - - for (i = 0; i < cit_model1_ntries; i++) - cit_Packet_Format1(gspca_dev, 0x2c, 0x00); - - for (i = 0; i < cit_model1_ntries; i++) - cit_Packet_Format1(gspca_dev, 0x30, 0x14); - - cit_PacketFormat2(gspca_dev, 0x39, 0x02); - cit_PacketFormat2(gspca_dev, 0x01, 0xe1); - cit_PacketFormat2(gspca_dev, 0x02, 0xcd); - cit_PacketFormat2(gspca_dev, 0x03, 0xcd); - cit_PacketFormat2(gspca_dev, 0x04, 0xfa); - cit_PacketFormat2(gspca_dev, 0x3f, 0xff); - cit_PacketFormat2(gspca_dev, 0x39, 0x00); - - cit_PacketFormat2(gspca_dev, 0x39, 0x02); - cit_PacketFormat2(gspca_dev, 0x0a, 0x37); - cit_PacketFormat2(gspca_dev, 0x0b, 0xb8); - cit_PacketFormat2(gspca_dev, 0x0c, 0xf3); - cit_PacketFormat2(gspca_dev, 0x0d, 0xe3); - cit_PacketFormat2(gspca_dev, 0x0e, 0x0d); - cit_PacketFormat2(gspca_dev, 0x0f, 0xf2); - cit_PacketFormat2(gspca_dev, 0x10, 0xd5); - cit_PacketFormat2(gspca_dev, 0x11, 0xba); - cit_PacketFormat2(gspca_dev, 0x12, 0x53); - cit_PacketFormat2(gspca_dev, 0x3f, 0xff); - cit_PacketFormat2(gspca_dev, 0x39, 0x00); - - cit_PacketFormat2(gspca_dev, 0x39, 0x02); - cit_PacketFormat2(gspca_dev, 0x16, 0x00); - cit_PacketFormat2(gspca_dev, 0x17, 0x28); - cit_PacketFormat2(gspca_dev, 0x18, 0x7d); - cit_PacketFormat2(gspca_dev, 0x19, 0xbe); - cit_PacketFormat2(gspca_dev, 0x3f, 0xff); - cit_PacketFormat2(gspca_dev, 0x39, 0x00); - - for (i = 0; i < cit_model1_ntries; i++) - cit_Packet_Format1(gspca_dev, 0x00, 0x18); - for (i = 0; i < cit_model1_ntries; i++) - cit_Packet_Format1(gspca_dev, 0x13, 0x18); - for (i = 0; i < cit_model1_ntries; i++) - cit_Packet_Format1(gspca_dev, 0x14, 0x06); - - /* TESTME These are handled through controls - KEEP until someone can test leaving this out is ok */ - if (0) { - /* This is default brightness */ - for (i = 0; i < cit_model1_ntries; i++) - cit_Packet_Format1(gspca_dev, 0x31, 0x37); - for (i = 0; i < cit_model1_ntries; i++) - cit_Packet_Format1(gspca_dev, 0x32, 0x46); - for (i = 0; i < cit_model1_ntries; i++) - cit_Packet_Format1(gspca_dev, 0x33, 0x55); - } - - cit_Packet_Format1(gspca_dev, 0x2e, 0x04); - for (i = 0; i < cit_model1_ntries; i++) - cit_Packet_Format1(gspca_dev, 0x2d, 0x04); - for (i = 0; i < cit_model1_ntries; i++) - cit_Packet_Format1(gspca_dev, 0x29, 0x80); - cit_Packet_Format1(gspca_dev, 0x2c, 0x01); - cit_Packet_Format1(gspca_dev, 0x30, 0x17); - cit_Packet_Format1(gspca_dev, 0x39, 0x08); - for (i = 0; i < cit_model1_ntries; i++) - cit_Packet_Format1(gspca_dev, 0x34, 0x00); - - cit_write_reg(gspca_dev, 0x00, 0x0101); - cit_write_reg(gspca_dev, 0x00, 0x010a); - - switch (gspca_dev->width) { - case 128: /* 128x96 */ - cit_write_reg(gspca_dev, 0x80, 0x0103); - cit_write_reg(gspca_dev, 0x60, 0x0105); - cit_write_reg(gspca_dev, 0x0c, 0x010b); - cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */ - cit_write_reg(gspca_dev, 0x0b, 0x011d); - cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */ - cit_write_reg(gspca_dev, 0x00, 0x0129); - break; - case 176: /* 176x144 */ - cit_write_reg(gspca_dev, 0xb0, 0x0103); - cit_write_reg(gspca_dev, 0x8f, 0x0105); - cit_write_reg(gspca_dev, 0x06, 0x010b); - cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */ - cit_write_reg(gspca_dev, 0x0d, 0x011d); - cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */ - cit_write_reg(gspca_dev, 0x03, 0x0129); - break; - case 352: /* 352x288 */ - cit_write_reg(gspca_dev, 0xb0, 0x0103); - cit_write_reg(gspca_dev, 0x90, 0x0105); - cit_write_reg(gspca_dev, 0x02, 0x010b); - cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */ - cit_write_reg(gspca_dev, 0x05, 0x011d); - cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */ - cit_write_reg(gspca_dev, 0x00, 0x0129); - break; - } - - cit_write_reg(gspca_dev, 0xff, 0x012b); - - /* TESTME These are handled through controls - KEEP until someone can test leaving this out is ok */ - if (0) { - /* This is another brightness - don't know why */ - for (i = 0; i < cit_model1_ntries; i++) - cit_Packet_Format1(gspca_dev, 0x31, 0xc3); - for (i = 0; i < cit_model1_ntries; i++) - cit_Packet_Format1(gspca_dev, 0x32, 0xd2); - for (i = 0; i < cit_model1_ntries; i++) - cit_Packet_Format1(gspca_dev, 0x33, 0xe1); - - /* Default contrast */ - for (i = 0; i < cit_model1_ntries; i++) - cit_Packet_Format1(gspca_dev, 0x14, 0x0a); - - /* Default sharpness */ - for (i = 0; i < cit_model1_ntries2; i++) - cit_PacketFormat2(gspca_dev, 0x13, 0x1a); - - /* Default lighting conditions */ - cit_Packet_Format1(gspca_dev, 0x0027, - v4l2_ctrl_g_ctrl(sd->lighting)); - } - - /* Assorted init */ - switch (gspca_dev->width) { - case 128: /* 128x96 */ - cit_Packet_Format1(gspca_dev, 0x2b, 0x1e); - cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */ - cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */ - cit_write_reg(gspca_dev, 0x36, 0x0102); - cit_write_reg(gspca_dev, 0x1a, 0x0104); - cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */ - cit_write_reg(gspca_dev, 0x2b, 0x011c); - cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */ - break; - case 176: /* 176x144 */ - cit_Packet_Format1(gspca_dev, 0x2b, 0x1e); - cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */ - cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */ - cit_write_reg(gspca_dev, 0x04, 0x0102); - cit_write_reg(gspca_dev, 0x02, 0x0104); - cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */ - cit_write_reg(gspca_dev, 0x2b, 0x011c); - cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */ - break; - case 352: /* 352x288 */ - cit_Packet_Format1(gspca_dev, 0x2b, 0x1f); - cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */ - cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */ - cit_write_reg(gspca_dev, 0x08, 0x0102); - cit_write_reg(gspca_dev, 0x01, 0x0104); - cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */ - cit_write_reg(gspca_dev, 0x2f, 0x011c); - cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */ - break; - } - - cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */ - cit_write_reg(gspca_dev, clock_div, 0x0111); - - return 0; -} - -static int cit_start_model2(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int clock_div = 0; - - cit_write_reg(gspca_dev, 0x0000, 0x0100); /* LED on */ - cit_read_reg(gspca_dev, 0x0116, 0); - cit_write_reg(gspca_dev, 0x0060, 0x0116); - cit_write_reg(gspca_dev, 0x0002, 0x0112); - cit_write_reg(gspca_dev, 0x00bc, 0x012c); - cit_write_reg(gspca_dev, 0x0008, 0x012b); - cit_write_reg(gspca_dev, 0x0000, 0x0108); - cit_write_reg(gspca_dev, 0x0001, 0x0133); - cit_write_reg(gspca_dev, 0x0001, 0x0102); - switch (gspca_dev->width) { - case 176: /* 176x144 */ - cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */ - cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */ - cit_write_reg(gspca_dev, 0x0024, 0x0105); /* 176x144, 352x288 */ - cit_write_reg(gspca_dev, 0x00b9, 0x010a); /* Unique to this mode */ - cit_write_reg(gspca_dev, 0x0038, 0x0119); /* Unique to this mode */ - /* TESTME HDG: this does not seem right - (it is 2 for all other resolutions) */ - sd->sof_len = 10; - break; - case 320: /* 320x240 */ - cit_write_reg(gspca_dev, 0x0028, 0x0103); /* Unique to this mode */ - cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */ - cit_write_reg(gspca_dev, 0x001e, 0x0105); /* 320x240, 352x240 */ - cit_write_reg(gspca_dev, 0x0039, 0x010a); /* All except 176x144 */ - cit_write_reg(gspca_dev, 0x0070, 0x0119); /* All except 176x144 */ - sd->sof_len = 2; - break; - /* case VIDEOSIZE_352x240: */ - cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */ - cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */ - cit_write_reg(gspca_dev, 0x001e, 0x0105); /* 320x240, 352x240 */ - cit_write_reg(gspca_dev, 0x0039, 0x010a); /* All except 176x144 */ - cit_write_reg(gspca_dev, 0x0070, 0x0119); /* All except 176x144 */ - sd->sof_len = 2; - break; - case 352: /* 352x288 */ - cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */ - cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */ - cit_write_reg(gspca_dev, 0x0024, 0x0105); /* 176x144, 352x288 */ - cit_write_reg(gspca_dev, 0x0039, 0x010a); /* All except 176x144 */ - cit_write_reg(gspca_dev, 0x0070, 0x0119); /* All except 176x144 */ - sd->sof_len = 2; - break; - } - - cit_write_reg(gspca_dev, 0x0000, 0x0100); /* LED on */ - - switch (gspca_dev->width) { - case 176: /* 176x144 */ - cit_write_reg(gspca_dev, 0x0050, 0x0111); - cit_write_reg(gspca_dev, 0x00d0, 0x0111); - break; - case 320: /* 320x240 */ - case 352: /* 352x288 */ - cit_write_reg(gspca_dev, 0x0040, 0x0111); - cit_write_reg(gspca_dev, 0x00c0, 0x0111); - break; - } - cit_write_reg(gspca_dev, 0x009b, 0x010f); - cit_write_reg(gspca_dev, 0x00bb, 0x010f); - - /* - * Hardware settings, may affect CMOS sensor; not user controls! - * ------------------------------------------------------------- - * 0x0004: no effect - * 0x0006: hardware effect - * 0x0008: no effect - * 0x000a: stops video stream, probably important h/w setting - * 0x000c: changes color in hardware manner (not user setting) - * 0x0012: changes number of colors (does not affect speed) - * 0x002a: no effect - * 0x002c: hardware setting (related to scan lines) - * 0x002e: stops video stream, probably important h/w setting - */ - cit_model2_Packet1(gspca_dev, 0x000a, 0x005c); - cit_model2_Packet1(gspca_dev, 0x0004, 0x0000); - cit_model2_Packet1(gspca_dev, 0x0006, 0x00fb); - cit_model2_Packet1(gspca_dev, 0x0008, 0x0000); - cit_model2_Packet1(gspca_dev, 0x000c, 0x0009); - cit_model2_Packet1(gspca_dev, 0x0012, 0x000a); - cit_model2_Packet1(gspca_dev, 0x002a, 0x0000); - cit_model2_Packet1(gspca_dev, 0x002c, 0x0000); - cit_model2_Packet1(gspca_dev, 0x002e, 0x0008); - - /* - * Function 0x0030 pops up all over the place. Apparently - * it is a hardware control register, with every bit assigned to - * do something. - */ - cit_model2_Packet1(gspca_dev, 0x0030, 0x0000); - - /* - * Magic control of CMOS sensor. Only lower values like - * 0-3 work, and picture shifts left or right. Don't change. - */ - switch (gspca_dev->width) { - case 176: /* 176x144 */ - cit_model2_Packet1(gspca_dev, 0x0014, 0x0002); - cit_model2_Packet1(gspca_dev, 0x0016, 0x0002); /* Horizontal shift */ - cit_model2_Packet1(gspca_dev, 0x0018, 0x004a); /* Another hardware setting */ - clock_div = 6; - break; - case 320: /* 320x240 */ - cit_model2_Packet1(gspca_dev, 0x0014, 0x0009); - cit_model2_Packet1(gspca_dev, 0x0016, 0x0005); /* Horizontal shift */ - cit_model2_Packet1(gspca_dev, 0x0018, 0x0044); /* Another hardware setting */ - clock_div = 8; - break; - /* case VIDEOSIZE_352x240: */ - /* This mode doesn't work as Windows programs it; changed to work */ - cit_model2_Packet1(gspca_dev, 0x0014, 0x0009); /* Windows sets this to 8 */ - cit_model2_Packet1(gspca_dev, 0x0016, 0x0003); /* Horizontal shift */ - cit_model2_Packet1(gspca_dev, 0x0018, 0x0044); /* Windows sets this to 0x0045 */ - clock_div = 10; - break; - case 352: /* 352x288 */ - cit_model2_Packet1(gspca_dev, 0x0014, 0x0003); - cit_model2_Packet1(gspca_dev, 0x0016, 0x0002); /* Horizontal shift */ - cit_model2_Packet1(gspca_dev, 0x0018, 0x004a); /* Another hardware setting */ - clock_div = 16; - break; - } - - /* TESTME These are handled through controls - KEEP until someone can test leaving this out is ok */ - if (0) - cit_model2_Packet1(gspca_dev, 0x001a, 0x005a); - - /* - * We have our own frame rate setting varying from 0 (slowest) to 6 - * (fastest). The camera model 2 allows frame rate in range [0..0x1F] - # where 0 is also the slowest setting. However for all practical - # reasons high settings make no sense because USB is not fast enough - # to support high FPS. Be aware that the picture datastream will be - # severely disrupted if you ask for frame rate faster than allowed - # for the video size - see below: - * - * Allowable ranges (obtained experimentally on OHCI, K6-3, 450 MHz): - * ----------------------------------------------------------------- - * 176x144: [6..31] - * 320x240: [8..31] - * 352x240: [10..31] - * 352x288: [16..31] I have to raise lower threshold for stability... - * - * As usual, slower FPS provides better sensitivity. - */ - cit_model2_Packet1(gspca_dev, 0x001c, clock_div); - - /* - * This setting does not visibly affect pictures; left it here - * because it was present in Windows USB data stream. This function - * does not allow arbitrary values and apparently is a bit mask, to - * be activated only at appropriate time. Don't change it randomly! - */ - switch (gspca_dev->width) { - case 176: /* 176x144 */ - cit_model2_Packet1(gspca_dev, 0x0026, 0x00c2); - break; - case 320: /* 320x240 */ - cit_model2_Packet1(gspca_dev, 0x0026, 0x0044); - break; - /* case VIDEOSIZE_352x240: */ - cit_model2_Packet1(gspca_dev, 0x0026, 0x0046); - break; - case 352: /* 352x288 */ - cit_model2_Packet1(gspca_dev, 0x0026, 0x0048); - break; - } - - cit_model2_Packet1(gspca_dev, 0x0028, v4l2_ctrl_g_ctrl(sd->lighting)); - /* model2 cannot change the backlight compensation while streaming */ - v4l2_ctrl_grab(sd->lighting, true); - - /* color balance rg2 */ - cit_model2_Packet1(gspca_dev, 0x001e, 0x002f); - /* saturation */ - cit_model2_Packet1(gspca_dev, 0x0020, 0x0034); - /* color balance yb */ - cit_model2_Packet1(gspca_dev, 0x0022, 0x00a0); - - /* Hardware control command */ - cit_model2_Packet1(gspca_dev, 0x0030, 0x0004); - - return 0; -} - -static int cit_start_model3(struct gspca_dev *gspca_dev) -{ - const unsigned short compression = 0; /* 0=none, 7=best frame rate */ - int i, clock_div = 0; - - /* HDG not in ibmcam driver, added to see if it helps with - auto-detecting between model3 and ibm netcamera pro */ - cit_read_reg(gspca_dev, 0x128, 1); - - cit_write_reg(gspca_dev, 0x0000, 0x0100); - cit_read_reg(gspca_dev, 0x0116, 0); - cit_write_reg(gspca_dev, 0x0060, 0x0116); - cit_write_reg(gspca_dev, 0x0002, 0x0112); - cit_write_reg(gspca_dev, 0x0000, 0x0123); - cit_write_reg(gspca_dev, 0x0001, 0x0117); - cit_write_reg(gspca_dev, 0x0040, 0x0108); - cit_write_reg(gspca_dev, 0x0019, 0x012c); - cit_write_reg(gspca_dev, 0x0060, 0x0116); - cit_write_reg(gspca_dev, 0x0002, 0x0115); - cit_write_reg(gspca_dev, 0x0003, 0x0115); - cit_read_reg(gspca_dev, 0x0115, 0); - cit_write_reg(gspca_dev, 0x000b, 0x0115); - - /* TESTME HDG not in ibmcam driver, added to see if it helps with - auto-detecting between model3 and ibm netcamera pro */ - if (0) { - cit_write_reg(gspca_dev, 0x0078, 0x012d); - cit_write_reg(gspca_dev, 0x0001, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x0079, 0x012d); - cit_write_reg(gspca_dev, 0x00ff, 0x0130); - cit_write_reg(gspca_dev, 0xcd41, 0x0124); - cit_write_reg(gspca_dev, 0xfffa, 0x0124); - cit_read_reg(gspca_dev, 0x0126, 1); - } - - cit_model3_Packet1(gspca_dev, 0x000a, 0x0040); - cit_model3_Packet1(gspca_dev, 0x000b, 0x00f6); - cit_model3_Packet1(gspca_dev, 0x000c, 0x0002); - cit_model3_Packet1(gspca_dev, 0x000d, 0x0020); - cit_model3_Packet1(gspca_dev, 0x000e, 0x0033); - cit_model3_Packet1(gspca_dev, 0x000f, 0x0007); - cit_model3_Packet1(gspca_dev, 0x0010, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0011, 0x0070); - cit_model3_Packet1(gspca_dev, 0x0012, 0x0030); - cit_model3_Packet1(gspca_dev, 0x0013, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0014, 0x0001); - cit_model3_Packet1(gspca_dev, 0x0015, 0x0001); - cit_model3_Packet1(gspca_dev, 0x0016, 0x0001); - cit_model3_Packet1(gspca_dev, 0x0017, 0x0001); - cit_model3_Packet1(gspca_dev, 0x0018, 0x0000); - cit_model3_Packet1(gspca_dev, 0x001e, 0x00c3); - cit_model3_Packet1(gspca_dev, 0x0020, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0028, 0x0010); - cit_model3_Packet1(gspca_dev, 0x0029, 0x0054); - cit_model3_Packet1(gspca_dev, 0x002a, 0x0013); - cit_model3_Packet1(gspca_dev, 0x002b, 0x0007); - cit_model3_Packet1(gspca_dev, 0x002d, 0x0028); - cit_model3_Packet1(gspca_dev, 0x002e, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0031, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0032, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0033, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0034, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0035, 0x0038); - cit_model3_Packet1(gspca_dev, 0x003a, 0x0001); - cit_model3_Packet1(gspca_dev, 0x003c, 0x001e); - cit_model3_Packet1(gspca_dev, 0x003f, 0x000a); - cit_model3_Packet1(gspca_dev, 0x0041, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0046, 0x003f); - cit_model3_Packet1(gspca_dev, 0x0047, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0050, 0x0005); - cit_model3_Packet1(gspca_dev, 0x0052, 0x001a); - cit_model3_Packet1(gspca_dev, 0x0053, 0x0003); - cit_model3_Packet1(gspca_dev, 0x005a, 0x006b); - cit_model3_Packet1(gspca_dev, 0x005d, 0x001e); - cit_model3_Packet1(gspca_dev, 0x005e, 0x0030); - cit_model3_Packet1(gspca_dev, 0x005f, 0x0041); - cit_model3_Packet1(gspca_dev, 0x0064, 0x0008); - cit_model3_Packet1(gspca_dev, 0x0065, 0x0015); - cit_model3_Packet1(gspca_dev, 0x0068, 0x000f); - cit_model3_Packet1(gspca_dev, 0x0079, 0x0000); - cit_model3_Packet1(gspca_dev, 0x007a, 0x0000); - cit_model3_Packet1(gspca_dev, 0x007c, 0x003f); - cit_model3_Packet1(gspca_dev, 0x0082, 0x000f); - cit_model3_Packet1(gspca_dev, 0x0085, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0099, 0x0000); - cit_model3_Packet1(gspca_dev, 0x009b, 0x0023); - cit_model3_Packet1(gspca_dev, 0x009c, 0x0022); - cit_model3_Packet1(gspca_dev, 0x009d, 0x0096); - cit_model3_Packet1(gspca_dev, 0x009e, 0x0096); - cit_model3_Packet1(gspca_dev, 0x009f, 0x000a); - - switch (gspca_dev->width) { - case 160: - cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */ - cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */ - cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */ - cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */ - cit_write_reg(gspca_dev, 0x0024, 0x010b); /* Differs everywhere */ - cit_write_reg(gspca_dev, 0x00a9, 0x0119); - cit_write_reg(gspca_dev, 0x0016, 0x011b); - cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same on 160x120, 320x240 */ - cit_write_reg(gspca_dev, 0x0003, 0x011e); /* Same on 160x120, 640x480 */ - cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */ - cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */ - cit_write_reg(gspca_dev, 0x0018, 0x0102); - cit_write_reg(gspca_dev, 0x0004, 0x0104); - cit_write_reg(gspca_dev, 0x0004, 0x011a); - cit_write_reg(gspca_dev, 0x0028, 0x011c); - cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */ - cit_write_reg(gspca_dev, 0x0000, 0x0118); - cit_write_reg(gspca_dev, 0x0000, 0x0132); - cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */ - cit_write_reg(gspca_dev, compression, 0x0109); - clock_div = 3; - break; - case 320: - cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */ - cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */ - cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */ - cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */ - cit_write_reg(gspca_dev, 0x0028, 0x010b); /* Differs everywhere */ - cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same */ - cit_write_reg(gspca_dev, 0x0000, 0x011e); - cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */ - cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */ - /* 4 commands from 160x120 skipped */ - cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */ - cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */ - cit_write_reg(gspca_dev, compression, 0x0109); - cit_write_reg(gspca_dev, 0x00d9, 0x0119); - cit_write_reg(gspca_dev, 0x0006, 0x011b); - cit_write_reg(gspca_dev, 0x0021, 0x0102); /* Same on 320x240, 640x480 */ - cit_write_reg(gspca_dev, 0x0010, 0x0104); - cit_write_reg(gspca_dev, 0x0004, 0x011a); - cit_write_reg(gspca_dev, 0x003f, 0x011c); - cit_write_reg(gspca_dev, 0x001c, 0x0118); - cit_write_reg(gspca_dev, 0x0000, 0x0132); - clock_div = 5; - break; - case 640: - cit_write_reg(gspca_dev, 0x00f0, 0x0105); - cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */ - cit_write_reg(gspca_dev, 0x0038, 0x010b); /* Differs everywhere */ - cit_write_reg(gspca_dev, 0x00d9, 0x0119); /* Same on 320x240, 640x480 */ - cit_write_reg(gspca_dev, 0x0006, 0x011b); /* Same on 320x240, 640x480 */ - cit_write_reg(gspca_dev, 0x0004, 0x011d); /* NC */ - cit_write_reg(gspca_dev, 0x0003, 0x011e); /* Same on 160x120, 640x480 */ - cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */ - cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */ - cit_write_reg(gspca_dev, 0x0021, 0x0102); /* Same on 320x240, 640x480 */ - cit_write_reg(gspca_dev, 0x0016, 0x0104); /* NC */ - cit_write_reg(gspca_dev, 0x0004, 0x011a); /* Same on 320x240, 640x480 */ - cit_write_reg(gspca_dev, 0x003f, 0x011c); /* Same on 320x240, 640x480 */ - cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */ - cit_write_reg(gspca_dev, 0x001c, 0x0118); /* Same on 320x240, 640x480 */ - cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */ - cit_write_reg(gspca_dev, compression, 0x0109); - cit_write_reg(gspca_dev, 0x0040, 0x0101); - cit_write_reg(gspca_dev, 0x0040, 0x0103); - cit_write_reg(gspca_dev, 0x0000, 0x0132); /* Same on 320x240, 640x480 */ - clock_div = 7; - break; - } - - cit_model3_Packet1(gspca_dev, 0x007e, 0x000e); /* Hue */ - cit_model3_Packet1(gspca_dev, 0x0036, 0x0011); /* Brightness */ - cit_model3_Packet1(gspca_dev, 0x0060, 0x0002); /* Sharpness */ - cit_model3_Packet1(gspca_dev, 0x0061, 0x0004); /* Sharpness */ - cit_model3_Packet1(gspca_dev, 0x0062, 0x0005); /* Sharpness */ - cit_model3_Packet1(gspca_dev, 0x0063, 0x0014); /* Sharpness */ - cit_model3_Packet1(gspca_dev, 0x0096, 0x00a0); /* Red sharpness */ - cit_model3_Packet1(gspca_dev, 0x0097, 0x0096); /* Blue sharpness */ - cit_model3_Packet1(gspca_dev, 0x0067, 0x0001); /* Contrast */ - cit_model3_Packet1(gspca_dev, 0x005b, 0x000c); /* Contrast */ - cit_model3_Packet1(gspca_dev, 0x005c, 0x0016); /* Contrast */ - cit_model3_Packet1(gspca_dev, 0x0098, 0x000b); - cit_model3_Packet1(gspca_dev, 0x002c, 0x0003); /* Was 1, broke 640x480 */ - cit_model3_Packet1(gspca_dev, 0x002f, 0x002a); - cit_model3_Packet1(gspca_dev, 0x0030, 0x0029); - cit_model3_Packet1(gspca_dev, 0x0037, 0x0002); - cit_model3_Packet1(gspca_dev, 0x0038, 0x0059); - cit_model3_Packet1(gspca_dev, 0x003d, 0x002e); - cit_model3_Packet1(gspca_dev, 0x003e, 0x0028); - cit_model3_Packet1(gspca_dev, 0x0078, 0x0005); - cit_model3_Packet1(gspca_dev, 0x007b, 0x0011); - cit_model3_Packet1(gspca_dev, 0x007d, 0x004b); - cit_model3_Packet1(gspca_dev, 0x007f, 0x0022); - cit_model3_Packet1(gspca_dev, 0x0080, 0x000c); - cit_model3_Packet1(gspca_dev, 0x0081, 0x000b); - cit_model3_Packet1(gspca_dev, 0x0083, 0x00fd); - cit_model3_Packet1(gspca_dev, 0x0086, 0x000b); - cit_model3_Packet1(gspca_dev, 0x0087, 0x000b); - cit_model3_Packet1(gspca_dev, 0x007e, 0x000e); - cit_model3_Packet1(gspca_dev, 0x0096, 0x00a0); /* Red sharpness */ - cit_model3_Packet1(gspca_dev, 0x0097, 0x0096); /* Blue sharpness */ - cit_model3_Packet1(gspca_dev, 0x0098, 0x000b); - - /* FIXME we should probably use cit_get_clock_div() here (in - combination with isoc negotiation using the programmable isoc size) - like with the IBM netcam pro). */ - cit_write_reg(gspca_dev, clock_div, 0x0111); /* Clock Divider */ - - switch (gspca_dev->width) { - case 160: - cit_model3_Packet1(gspca_dev, 0x001f, 0x0000); /* Same */ - cit_model3_Packet1(gspca_dev, 0x0039, 0x001f); /* Same */ - cit_model3_Packet1(gspca_dev, 0x003b, 0x003c); /* Same */ - cit_model3_Packet1(gspca_dev, 0x0040, 0x000a); - cit_model3_Packet1(gspca_dev, 0x0051, 0x000a); - break; - case 320: - cit_model3_Packet1(gspca_dev, 0x001f, 0x0000); /* Same */ - cit_model3_Packet1(gspca_dev, 0x0039, 0x001f); /* Same */ - cit_model3_Packet1(gspca_dev, 0x003b, 0x003c); /* Same */ - cit_model3_Packet1(gspca_dev, 0x0040, 0x0008); - cit_model3_Packet1(gspca_dev, 0x0051, 0x000b); - break; - case 640: - cit_model3_Packet1(gspca_dev, 0x001f, 0x0002); /* !Same */ - cit_model3_Packet1(gspca_dev, 0x0039, 0x003e); /* !Same */ - cit_model3_Packet1(gspca_dev, 0x0040, 0x0008); - cit_model3_Packet1(gspca_dev, 0x0051, 0x000a); - break; - } - -/* if (sd->input_index) { */ - if (rca_input) { - for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) { - if (rca_initdata[i][0]) - cit_read_reg(gspca_dev, rca_initdata[i][2], 0); - else - cit_write_reg(gspca_dev, rca_initdata[i][1], - rca_initdata[i][2]); - } - } - - return 0; -} - -static int cit_start_model4(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - cit_write_reg(gspca_dev, 0x0000, 0x0100); - cit_write_reg(gspca_dev, 0x00c0, 0x0111); - cit_write_reg(gspca_dev, 0x00bc, 0x012c); - cit_write_reg(gspca_dev, 0x0080, 0x012b); - cit_write_reg(gspca_dev, 0x0000, 0x0108); - cit_write_reg(gspca_dev, 0x0001, 0x0133); - cit_write_reg(gspca_dev, 0x009b, 0x010f); - cit_write_reg(gspca_dev, 0x00bb, 0x010f); - cit_model4_Packet1(gspca_dev, 0x0038, 0x0000); - cit_model4_Packet1(gspca_dev, 0x000a, 0x005c); - - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x0004, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x0000, 0x0127); - cit_write_reg(gspca_dev, 0x00fb, 0x012e); - cit_write_reg(gspca_dev, 0x0000, 0x0130); - cit_write_reg(gspca_dev, 0x8a28, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012f); - cit_write_reg(gspca_dev, 0xd055, 0x0124); - cit_write_reg(gspca_dev, 0x000c, 0x0127); - cit_write_reg(gspca_dev, 0x0009, 0x012e); - cit_write_reg(gspca_dev, 0xaa28, 0x0124); - - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x0012, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x0008, 0x0127); - cit_write_reg(gspca_dev, 0x00aa, 0x0130); - cit_write_reg(gspca_dev, 0x82a8, 0x0124); - cit_write_reg(gspca_dev, 0x002a, 0x012d); - cit_write_reg(gspca_dev, 0x0000, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0xfffa, 0x0124); - cit_model4_Packet1(gspca_dev, 0x0034, 0x0000); - - switch (gspca_dev->width) { - case 128: /* 128x96 */ - cit_write_reg(gspca_dev, 0x0070, 0x0119); - cit_write_reg(gspca_dev, 0x00d0, 0x0111); - cit_write_reg(gspca_dev, 0x0039, 0x010a); - cit_write_reg(gspca_dev, 0x0001, 0x0102); - cit_write_reg(gspca_dev, 0x0028, 0x0103); - cit_write_reg(gspca_dev, 0x0000, 0x0104); - cit_write_reg(gspca_dev, 0x001e, 0x0105); - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x0016, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x000a, 0x0127); - cit_write_reg(gspca_dev, 0x00aa, 0x0130); - cit_write_reg(gspca_dev, 0x82a8, 0x0124); - cit_write_reg(gspca_dev, 0x0014, 0x012d); - cit_write_reg(gspca_dev, 0x0008, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012e); - cit_write_reg(gspca_dev, 0x001a, 0x0130); - cit_write_reg(gspca_dev, 0x8a0a, 0x0124); - cit_write_reg(gspca_dev, 0x005a, 0x012d); - cit_write_reg(gspca_dev, 0x9545, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x0127); - cit_write_reg(gspca_dev, 0x0018, 0x012e); - cit_write_reg(gspca_dev, 0x0043, 0x0130); - cit_write_reg(gspca_dev, 0x8a28, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012f); - cit_write_reg(gspca_dev, 0xd055, 0x0124); - cit_write_reg(gspca_dev, 0x001c, 0x0127); - cit_write_reg(gspca_dev, 0x00eb, 0x012e); - cit_write_reg(gspca_dev, 0xaa28, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x0032, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x0000, 0x0127); - cit_write_reg(gspca_dev, 0x00aa, 0x0130); - cit_write_reg(gspca_dev, 0x82a8, 0x0124); - cit_write_reg(gspca_dev, 0x0036, 0x012d); - cit_write_reg(gspca_dev, 0x0008, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0xfffa, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x001e, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x0017, 0x0127); - cit_write_reg(gspca_dev, 0x0013, 0x012e); - cit_write_reg(gspca_dev, 0x0031, 0x0130); - cit_write_reg(gspca_dev, 0x8a28, 0x0124); - cit_write_reg(gspca_dev, 0x0017, 0x012d); - cit_write_reg(gspca_dev, 0x0078, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0x0000, 0x0127); - cit_write_reg(gspca_dev, 0xfea8, 0x0124); - sd->sof_len = 2; - break; - case 160: /* 160x120 */ - cit_write_reg(gspca_dev, 0x0038, 0x0119); - cit_write_reg(gspca_dev, 0x00d0, 0x0111); - cit_write_reg(gspca_dev, 0x00b9, 0x010a); - cit_write_reg(gspca_dev, 0x0001, 0x0102); - cit_write_reg(gspca_dev, 0x0028, 0x0103); - cit_write_reg(gspca_dev, 0x0000, 0x0104); - cit_write_reg(gspca_dev, 0x001e, 0x0105); - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x0016, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x000b, 0x0127); - cit_write_reg(gspca_dev, 0x00aa, 0x0130); - cit_write_reg(gspca_dev, 0x82a8, 0x0124); - cit_write_reg(gspca_dev, 0x0014, 0x012d); - cit_write_reg(gspca_dev, 0x0008, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012e); - cit_write_reg(gspca_dev, 0x001a, 0x0130); - cit_write_reg(gspca_dev, 0x8a0a, 0x0124); - cit_write_reg(gspca_dev, 0x005a, 0x012d); - cit_write_reg(gspca_dev, 0x9545, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x0127); - cit_write_reg(gspca_dev, 0x0018, 0x012e); - cit_write_reg(gspca_dev, 0x0043, 0x0130); - cit_write_reg(gspca_dev, 0x8a28, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012f); - cit_write_reg(gspca_dev, 0xd055, 0x0124); - cit_write_reg(gspca_dev, 0x001c, 0x0127); - cit_write_reg(gspca_dev, 0x00c7, 0x012e); - cit_write_reg(gspca_dev, 0xaa28, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x0032, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x0025, 0x0127); - cit_write_reg(gspca_dev, 0x00aa, 0x0130); - cit_write_reg(gspca_dev, 0x82a8, 0x0124); - cit_write_reg(gspca_dev, 0x0036, 0x012d); - cit_write_reg(gspca_dev, 0x0008, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0xfffa, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x001e, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x0048, 0x0127); - cit_write_reg(gspca_dev, 0x0035, 0x012e); - cit_write_reg(gspca_dev, 0x00d0, 0x0130); - cit_write_reg(gspca_dev, 0x8a28, 0x0124); - cit_write_reg(gspca_dev, 0x0048, 0x012d); - cit_write_reg(gspca_dev, 0x0090, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0x0001, 0x0127); - cit_write_reg(gspca_dev, 0xfea8, 0x0124); - sd->sof_len = 2; - break; - case 176: /* 176x144 */ - cit_write_reg(gspca_dev, 0x0038, 0x0119); - cit_write_reg(gspca_dev, 0x00d0, 0x0111); - cit_write_reg(gspca_dev, 0x00b9, 0x010a); - cit_write_reg(gspca_dev, 0x0001, 0x0102); - cit_write_reg(gspca_dev, 0x002c, 0x0103); - cit_write_reg(gspca_dev, 0x0000, 0x0104); - cit_write_reg(gspca_dev, 0x0024, 0x0105); - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x0016, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x0007, 0x0127); - cit_write_reg(gspca_dev, 0x00aa, 0x0130); - cit_write_reg(gspca_dev, 0x82a8, 0x0124); - cit_write_reg(gspca_dev, 0x0014, 0x012d); - cit_write_reg(gspca_dev, 0x0001, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012e); - cit_write_reg(gspca_dev, 0x001a, 0x0130); - cit_write_reg(gspca_dev, 0x8a0a, 0x0124); - cit_write_reg(gspca_dev, 0x005e, 0x012d); - cit_write_reg(gspca_dev, 0x9545, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x0127); - cit_write_reg(gspca_dev, 0x0018, 0x012e); - cit_write_reg(gspca_dev, 0x0049, 0x0130); - cit_write_reg(gspca_dev, 0x8a28, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012f); - cit_write_reg(gspca_dev, 0xd055, 0x0124); - cit_write_reg(gspca_dev, 0x001c, 0x0127); - cit_write_reg(gspca_dev, 0x00c7, 0x012e); - cit_write_reg(gspca_dev, 0xaa28, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x0032, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x0028, 0x0127); - cit_write_reg(gspca_dev, 0x00aa, 0x0130); - cit_write_reg(gspca_dev, 0x82a8, 0x0124); - cit_write_reg(gspca_dev, 0x0036, 0x012d); - cit_write_reg(gspca_dev, 0x0008, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0xfffa, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x001e, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x0010, 0x0127); - cit_write_reg(gspca_dev, 0x0013, 0x012e); - cit_write_reg(gspca_dev, 0x002a, 0x0130); - cit_write_reg(gspca_dev, 0x8a28, 0x0124); - cit_write_reg(gspca_dev, 0x0010, 0x012d); - cit_write_reg(gspca_dev, 0x006d, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0x0001, 0x0127); - cit_write_reg(gspca_dev, 0xfea8, 0x0124); - /* TESTME HDG: this does not seem right - (it is 2 for all other resolutions) */ - sd->sof_len = 10; - break; - case 320: /* 320x240 */ - cit_write_reg(gspca_dev, 0x0070, 0x0119); - cit_write_reg(gspca_dev, 0x00d0, 0x0111); - cit_write_reg(gspca_dev, 0x0039, 0x010a); - cit_write_reg(gspca_dev, 0x0001, 0x0102); - cit_write_reg(gspca_dev, 0x0028, 0x0103); - cit_write_reg(gspca_dev, 0x0000, 0x0104); - cit_write_reg(gspca_dev, 0x001e, 0x0105); - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x0016, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x000a, 0x0127); - cit_write_reg(gspca_dev, 0x00aa, 0x0130); - cit_write_reg(gspca_dev, 0x82a8, 0x0124); - cit_write_reg(gspca_dev, 0x0014, 0x012d); - cit_write_reg(gspca_dev, 0x0008, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012e); - cit_write_reg(gspca_dev, 0x001a, 0x0130); - cit_write_reg(gspca_dev, 0x8a0a, 0x0124); - cit_write_reg(gspca_dev, 0x005a, 0x012d); - cit_write_reg(gspca_dev, 0x9545, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x0127); - cit_write_reg(gspca_dev, 0x0018, 0x012e); - cit_write_reg(gspca_dev, 0x0043, 0x0130); - cit_write_reg(gspca_dev, 0x8a28, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012f); - cit_write_reg(gspca_dev, 0xd055, 0x0124); - cit_write_reg(gspca_dev, 0x001c, 0x0127); - cit_write_reg(gspca_dev, 0x00eb, 0x012e); - cit_write_reg(gspca_dev, 0xaa28, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x0032, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x0000, 0x0127); - cit_write_reg(gspca_dev, 0x00aa, 0x0130); - cit_write_reg(gspca_dev, 0x82a8, 0x0124); - cit_write_reg(gspca_dev, 0x0036, 0x012d); - cit_write_reg(gspca_dev, 0x0008, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0xfffa, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x001e, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x0017, 0x0127); - cit_write_reg(gspca_dev, 0x0013, 0x012e); - cit_write_reg(gspca_dev, 0x0031, 0x0130); - cit_write_reg(gspca_dev, 0x8a28, 0x0124); - cit_write_reg(gspca_dev, 0x0017, 0x012d); - cit_write_reg(gspca_dev, 0x0078, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0x0000, 0x0127); - cit_write_reg(gspca_dev, 0xfea8, 0x0124); - sd->sof_len = 2; - break; - case 352: /* 352x288 */ - cit_write_reg(gspca_dev, 0x0070, 0x0119); - cit_write_reg(gspca_dev, 0x00c0, 0x0111); - cit_write_reg(gspca_dev, 0x0039, 0x010a); - cit_write_reg(gspca_dev, 0x0001, 0x0102); - cit_write_reg(gspca_dev, 0x002c, 0x0103); - cit_write_reg(gspca_dev, 0x0000, 0x0104); - cit_write_reg(gspca_dev, 0x0024, 0x0105); - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x0016, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x0006, 0x0127); - cit_write_reg(gspca_dev, 0x00aa, 0x0130); - cit_write_reg(gspca_dev, 0x82a8, 0x0124); - cit_write_reg(gspca_dev, 0x0014, 0x012d); - cit_write_reg(gspca_dev, 0x0002, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012e); - cit_write_reg(gspca_dev, 0x001a, 0x0130); - cit_write_reg(gspca_dev, 0x8a0a, 0x0124); - cit_write_reg(gspca_dev, 0x005e, 0x012d); - cit_write_reg(gspca_dev, 0x9545, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x0127); - cit_write_reg(gspca_dev, 0x0018, 0x012e); - cit_write_reg(gspca_dev, 0x0049, 0x0130); - cit_write_reg(gspca_dev, 0x8a28, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012f); - cit_write_reg(gspca_dev, 0xd055, 0x0124); - cit_write_reg(gspca_dev, 0x001c, 0x0127); - cit_write_reg(gspca_dev, 0x00cf, 0x012e); - cit_write_reg(gspca_dev, 0xaa28, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x0032, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x0000, 0x0127); - cit_write_reg(gspca_dev, 0x00aa, 0x0130); - cit_write_reg(gspca_dev, 0x82a8, 0x0124); - cit_write_reg(gspca_dev, 0x0036, 0x012d); - cit_write_reg(gspca_dev, 0x0008, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0xfffa, 0x0124); - cit_write_reg(gspca_dev, 0x00aa, 0x012d); - cit_write_reg(gspca_dev, 0x001e, 0x012f); - cit_write_reg(gspca_dev, 0xd141, 0x0124); - cit_write_reg(gspca_dev, 0x0010, 0x0127); - cit_write_reg(gspca_dev, 0x0013, 0x012e); - cit_write_reg(gspca_dev, 0x0025, 0x0130); - cit_write_reg(gspca_dev, 0x8a28, 0x0124); - cit_write_reg(gspca_dev, 0x0010, 0x012d); - cit_write_reg(gspca_dev, 0x0048, 0x012f); - cit_write_reg(gspca_dev, 0xd145, 0x0124); - cit_write_reg(gspca_dev, 0x0000, 0x0127); - cit_write_reg(gspca_dev, 0xfea8, 0x0124); - sd->sof_len = 2; - break; - } - - cit_model4_Packet1(gspca_dev, 0x0038, 0x0004); - - return 0; -} - -static int cit_start_ibm_netcam_pro(struct gspca_dev *gspca_dev) -{ - const unsigned short compression = 0; /* 0=none, 7=best frame rate */ - int i, clock_div; - - clock_div = cit_get_clock_div(gspca_dev); - if (clock_div < 0) - return clock_div; - - cit_write_reg(gspca_dev, 0x0003, 0x0133); - cit_write_reg(gspca_dev, 0x0000, 0x0117); - cit_write_reg(gspca_dev, 0x0008, 0x0123); - cit_write_reg(gspca_dev, 0x0000, 0x0100); - cit_write_reg(gspca_dev, 0x0060, 0x0116); - /* cit_write_reg(gspca_dev, 0x0002, 0x0112); see sd_stop0 */ - cit_write_reg(gspca_dev, 0x0000, 0x0133); - cit_write_reg(gspca_dev, 0x0000, 0x0123); - cit_write_reg(gspca_dev, 0x0001, 0x0117); - cit_write_reg(gspca_dev, 0x0040, 0x0108); - cit_write_reg(gspca_dev, 0x0019, 0x012c); - cit_write_reg(gspca_dev, 0x0060, 0x0116); - /* cit_write_reg(gspca_dev, 0x000b, 0x0115); see sd_stop0 */ - - cit_model3_Packet1(gspca_dev, 0x0049, 0x0000); - - cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */ - cit_write_reg(gspca_dev, 0x003a, 0x0102); /* Hstart */ - cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */ - cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */ - cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */ - cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same on 160x120, 320x240 */ - cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */ - cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */ - cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */ - - switch (gspca_dev->width) { - case 160: /* 160x120 */ - cit_write_reg(gspca_dev, 0x0024, 0x010b); - cit_write_reg(gspca_dev, 0x0089, 0x0119); - cit_write_reg(gspca_dev, 0x000a, 0x011b); - cit_write_reg(gspca_dev, 0x0003, 0x011e); - cit_write_reg(gspca_dev, 0x0007, 0x0104); - cit_write_reg(gspca_dev, 0x0009, 0x011a); - cit_write_reg(gspca_dev, 0x008b, 0x011c); - cit_write_reg(gspca_dev, 0x0008, 0x0118); - cit_write_reg(gspca_dev, 0x0000, 0x0132); - break; - case 320: /* 320x240 */ - cit_write_reg(gspca_dev, 0x0028, 0x010b); - cit_write_reg(gspca_dev, 0x00d9, 0x0119); - cit_write_reg(gspca_dev, 0x0006, 0x011b); - cit_write_reg(gspca_dev, 0x0000, 0x011e); - cit_write_reg(gspca_dev, 0x000e, 0x0104); - cit_write_reg(gspca_dev, 0x0004, 0x011a); - cit_write_reg(gspca_dev, 0x003f, 0x011c); - cit_write_reg(gspca_dev, 0x000c, 0x0118); - cit_write_reg(gspca_dev, 0x0000, 0x0132); - break; - } - - cit_model3_Packet1(gspca_dev, 0x0019, 0x0031); - cit_model3_Packet1(gspca_dev, 0x001a, 0x0003); - cit_model3_Packet1(gspca_dev, 0x001b, 0x0038); - cit_model3_Packet1(gspca_dev, 0x001c, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0024, 0x0001); - cit_model3_Packet1(gspca_dev, 0x0027, 0x0001); - cit_model3_Packet1(gspca_dev, 0x002a, 0x0004); - cit_model3_Packet1(gspca_dev, 0x0035, 0x000b); - cit_model3_Packet1(gspca_dev, 0x003f, 0x0001); - cit_model3_Packet1(gspca_dev, 0x0044, 0x0000); - cit_model3_Packet1(gspca_dev, 0x0054, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00c4, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00e7, 0x0001); - cit_model3_Packet1(gspca_dev, 0x00e9, 0x0001); - cit_model3_Packet1(gspca_dev, 0x00ee, 0x0000); - cit_model3_Packet1(gspca_dev, 0x00f3, 0x00c0); - - cit_write_reg(gspca_dev, compression, 0x0109); - cit_write_reg(gspca_dev, clock_div, 0x0111); - -/* if (sd->input_index) { */ - if (rca_input) { - for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) { - if (rca_initdata[i][0]) - cit_read_reg(gspca_dev, rca_initdata[i][2], 0); - else - cit_write_reg(gspca_dev, rca_initdata[i][1], - rca_initdata[i][2]); - } - } - - return 0; -} - -/* -- start the camera -- */ -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int packet_size; - - packet_size = cit_get_packet_size(gspca_dev); - if (packet_size < 0) - return packet_size; - - switch (sd->model) { - case CIT_MODEL0: - cit_start_model0(gspca_dev); - break; - case CIT_MODEL1: - cit_start_model1(gspca_dev); - break; - case CIT_MODEL2: - cit_start_model2(gspca_dev); - break; - case CIT_MODEL3: - cit_start_model3(gspca_dev); - break; - case CIT_MODEL4: - cit_start_model4(gspca_dev); - break; - case CIT_IBM_NETCAM_PRO: - cit_start_ibm_netcam_pro(gspca_dev); - break; - } - - /* Program max isoc packet size */ - cit_write_reg(gspca_dev, packet_size >> 8, 0x0106); - cit_write_reg(gspca_dev, packet_size & 0xff, 0x0107); - - cit_restart_stream(gspca_dev); - - return 0; -} - -static int sd_isoc_init(struct gspca_dev *gspca_dev) -{ - struct usb_host_interface *alt; - int max_packet_size; - - switch (gspca_dev->width) { - case 160: - max_packet_size = 450; - break; - case 176: - max_packet_size = 600; - break; - default: - max_packet_size = 1022; - break; - } - - /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ - alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; - alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size); - - return 0; -} - -static int sd_isoc_nego(struct gspca_dev *gspca_dev) -{ - int ret, packet_size, min_packet_size; - struct usb_host_interface *alt; - - switch (gspca_dev->width) { - case 160: - min_packet_size = 200; - break; - case 176: - min_packet_size = 266; - break; - default: - min_packet_size = 400; - break; - } - - alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; - packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); - if (packet_size <= min_packet_size) - return -EIO; - - packet_size -= 100; - if (packet_size < min_packet_size) - packet_size = min_packet_size; - alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size); - - ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); - if (ret < 0) - pr_err("set alt 1 err %d\n", ret); - - return ret; -} - -static void sd_stopN(struct gspca_dev *gspca_dev) -{ - cit_write_reg(gspca_dev, 0x0000, 0x010c); -} - -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* We cannot use gspca_dev->present here as that is not set when - sd_init gets called and we get called from sd_init */ - if (!gspca_dev->dev) - return; - - switch (sd->model) { - case CIT_MODEL0: - /* HDG windows does this, but it causes the cams autogain to - restart from a gain of 0, which does not look good when - changing resolutions. */ - /* cit_write_reg(gspca_dev, 0x0000, 0x0112); */ - cit_write_reg(gspca_dev, 0x00c0, 0x0100); /* LED Off */ - break; - case CIT_MODEL1: - cit_send_FF_04_02(gspca_dev); - cit_read_reg(gspca_dev, 0x0100, 0); - cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */ - break; - case CIT_MODEL2: - v4l2_ctrl_grab(sd->lighting, false); - /* Fall through! */ - case CIT_MODEL4: - cit_model2_Packet1(gspca_dev, 0x0030, 0x0004); - - cit_write_reg(gspca_dev, 0x0080, 0x0100); /* LED Off */ - cit_write_reg(gspca_dev, 0x0020, 0x0111); - cit_write_reg(gspca_dev, 0x00a0, 0x0111); - - cit_model2_Packet1(gspca_dev, 0x0030, 0x0002); - - cit_write_reg(gspca_dev, 0x0020, 0x0111); - cit_write_reg(gspca_dev, 0x0000, 0x0112); - break; - case CIT_MODEL3: - cit_write_reg(gspca_dev, 0x0006, 0x012c); - cit_model3_Packet1(gspca_dev, 0x0046, 0x0000); - cit_read_reg(gspca_dev, 0x0116, 0); - cit_write_reg(gspca_dev, 0x0064, 0x0116); - cit_read_reg(gspca_dev, 0x0115, 0); - cit_write_reg(gspca_dev, 0x0003, 0x0115); - cit_write_reg(gspca_dev, 0x0008, 0x0123); - cit_write_reg(gspca_dev, 0x0000, 0x0117); - cit_write_reg(gspca_dev, 0x0000, 0x0112); - cit_write_reg(gspca_dev, 0x0080, 0x0100); - break; - case CIT_IBM_NETCAM_PRO: - cit_model3_Packet1(gspca_dev, 0x0049, 0x00ff); - cit_write_reg(gspca_dev, 0x0006, 0x012c); - cit_write_reg(gspca_dev, 0x0000, 0x0116); - /* HDG windows does this, but I cannot get the camera - to restart with this without redoing the entire init - sequence which makes switching modes really slow */ - /* cit_write_reg(gspca_dev, 0x0006, 0x0115); */ - cit_write_reg(gspca_dev, 0x0008, 0x0123); - cit_write_reg(gspca_dev, 0x0000, 0x0117); - cit_write_reg(gspca_dev, 0x0003, 0x0133); - cit_write_reg(gspca_dev, 0x0000, 0x0111); - /* HDG windows does this, but I get a green picture when - restarting the stream after this */ - /* cit_write_reg(gspca_dev, 0x0000, 0x0112); */ - cit_write_reg(gspca_dev, 0x00c0, 0x0100); - break; - } - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - /* If the last button state is pressed, release it now! */ - if (sd->button_state) { - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); - input_sync(gspca_dev->input_dev); - sd->button_state = 0; - } -#endif -} - -static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - u8 byte3 = 0, byte4 = 0; - int i; - - switch (sd->model) { - case CIT_MODEL0: - case CIT_MODEL1: - case CIT_MODEL3: - case CIT_IBM_NETCAM_PRO: - switch (gspca_dev->width) { - case 160: /* 160x120 */ - byte3 = 0x02; - byte4 = 0x0a; - break; - case 176: /* 176x144 */ - byte3 = 0x02; - byte4 = 0x0e; - break; - case 320: /* 320x240 */ - byte3 = 0x02; - byte4 = 0x08; - break; - case 352: /* 352x288 */ - byte3 = 0x02; - byte4 = 0x00; - break; - case 640: - byte3 = 0x03; - byte4 = 0x08; - break; - } - - /* These have a different byte3 */ - if (sd->model <= CIT_MODEL1) - byte3 = 0x00; - - for (i = 0; i < len; i++) { - /* For this model the SOF always starts at offset 0 - so no need to search the entire frame */ - if (sd->model == CIT_MODEL0 && sd->sof_read != i) - break; - - switch (sd->sof_read) { - case 0: - if (data[i] == 0x00) - sd->sof_read++; - break; - case 1: - if (data[i] == 0xff) - sd->sof_read++; - else if (data[i] == 0x00) - sd->sof_read = 1; - else - sd->sof_read = 0; - break; - case 2: - if (data[i] == byte3) - sd->sof_read++; - else if (data[i] == 0x00) - sd->sof_read = 1; - else - sd->sof_read = 0; - break; - case 3: - if (data[i] == byte4) { - sd->sof_read = 0; - return data + i + (sd->sof_len - 3); - } - if (byte3 == 0x00 && data[i] == 0xff) - sd->sof_read = 2; - else if (data[i] == 0x00) - sd->sof_read = 1; - else - sd->sof_read = 0; - break; - } - } - break; - case CIT_MODEL2: - case CIT_MODEL4: - /* TESTME we need to find a longer sof signature to avoid - false positives */ - for (i = 0; i < len; i++) { - switch (sd->sof_read) { - case 0: - if (data[i] == 0x00) - sd->sof_read++; - break; - case 1: - sd->sof_read = 0; - if (data[i] == 0xff) { - if (i >= 4) - PDEBUG(D_FRAM, - "header found at offset: %d: %02x %02x 00 %02x %02x %02x\n", - i - 1, - data[i - 4], - data[i - 3], - data[i], - data[i + 1], - data[i + 2]); - else - PDEBUG(D_FRAM, - "header found at offset: %d: 00 %02x %02x %02x\n", - i - 1, - data[i], - data[i + 1], - data[i + 2]); - return data + i + (sd->sof_len - 1); - } - break; - } - } - break; - } - return NULL; -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - unsigned char *sof; - - sof = cit_find_sof(gspca_dev, data, len); - if (sof) { - int n; - - /* finish decoding current frame */ - n = sof - data; - if (n > sd->sof_len) - n -= sd->sof_len; - else - n = 0; - gspca_frame_add(gspca_dev, LAST_PACKET, - data, n); - gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); - len -= sof - data; - data = sof; - } - - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) -static void cit_check_button(struct gspca_dev *gspca_dev) -{ - int new_button_state; - struct sd *sd = (struct sd *)gspca_dev; - - switch (sd->model) { - case CIT_MODEL3: - case CIT_IBM_NETCAM_PRO: - break; - default: /* TEST ME unknown if this works on other models too */ - return; - } - - /* Read the button state */ - cit_read_reg(gspca_dev, 0x0113, 0); - new_button_state = !gspca_dev->usb_buf[0]; - - /* Tell the cam we've seen the button press, notice that this - is a nop (iow the cam keeps reporting pressed) until the - button is actually released. */ - if (new_button_state) - cit_write_reg(gspca_dev, 0x01, 0x0113); - - if (sd->button_state != new_button_state) { - input_report_key(gspca_dev->input_dev, KEY_CAMERA, - new_button_state); - input_sync(gspca_dev->input_dev); - sd->button_state = new_button_state; - } -} -#endif - -static int sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - gspca_dev->usb_err = 0; - - if (!gspca_dev->streaming) - return 0; - - if (sd->stop_on_control_change) - sd_stopN(gspca_dev); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - cit_set_brightness(gspca_dev, ctrl->val); - break; - case V4L2_CID_CONTRAST: - cit_set_contrast(gspca_dev, ctrl->val); - break; - case V4L2_CID_HUE: - cit_set_hue(gspca_dev, ctrl->val); - break; - case V4L2_CID_HFLIP: - cit_set_hflip(gspca_dev, ctrl->val); - break; - case V4L2_CID_SHARPNESS: - cit_set_sharpness(gspca_dev, ctrl->val); - break; - case V4L2_CID_BACKLIGHT_COMPENSATION: - cit_set_lighting(gspca_dev, ctrl->val); - break; - } - if (sd->stop_on_control_change) - cit_restart_stream(gspca_dev); - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops sd_ctrl_ops = { - .s_ctrl = sd_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - bool has_brightness; - bool has_contrast; - bool has_hue; - bool has_sharpness; - bool has_lighting; - bool has_hflip; - - has_brightness = has_contrast = has_hue = - has_sharpness = has_hflip = has_lighting = false; - switch (sd->model) { - case CIT_MODEL0: - has_contrast = has_hflip = true; - break; - case CIT_MODEL1: - has_brightness = has_contrast = - has_sharpness = has_lighting = true; - break; - case CIT_MODEL2: - has_brightness = has_hue = has_lighting = true; - break; - case CIT_MODEL3: - has_brightness = has_contrast = has_sharpness = true; - break; - case CIT_MODEL4: - has_brightness = has_hue = true; - break; - case CIT_IBM_NETCAM_PRO: - has_brightness = has_hue = - has_sharpness = has_hflip = has_lighting = true; - break; - } - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 5); - if (has_brightness) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 63, 1, 32); - if (has_contrast) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_CONTRAST, 0, 20, 1, 10); - if (has_hue) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_HUE, 0, 127, 1, 63); - if (has_sharpness) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_SHARPNESS, 0, 6, 1, 3); - if (has_lighting) - sd->lighting = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BACKLIGHT_COMPENSATION, 0, 2, 1, 1); - if (has_hflip) - v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_HFLIP, 0, 1, 1, 0); - - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - return 0; -} - -/* sub-driver description */ -static const struct sd_desc sd_desc = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .stopN = sd_stopN, - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .dq_callback = cit_check_button, - .other_input = 1, -#endif -}; - -static const struct sd_desc sd_desc_isoc_nego = { - .name = MODULE_NAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .start = sd_start, - .isoc_init = sd_isoc_init, - .isoc_nego = sd_isoc_nego, - .stopN = sd_stopN, - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .dq_callback = cit_check_button, - .other_input = 1, -#endif -}; - -/* -- module initialisation -- */ -static const struct usb_device_id device_table[] = { - { USB_DEVICE_VER(0x0545, 0x8080, 0x0001, 0x0001), .driver_info = CIT_MODEL0 }, - { USB_DEVICE_VER(0x0545, 0x8080, 0x0002, 0x0002), .driver_info = CIT_MODEL1 }, - { USB_DEVICE_VER(0x0545, 0x8080, 0x030a, 0x030a), .driver_info = CIT_MODEL2 }, - { USB_DEVICE_VER(0x0545, 0x8080, 0x0301, 0x0301), .driver_info = CIT_MODEL3 }, - { USB_DEVICE_VER(0x0545, 0x8002, 0x030a, 0x030a), .driver_info = CIT_MODEL4 }, - { USB_DEVICE_VER(0x0545, 0x800c, 0x030a, 0x030a), .driver_info = CIT_MODEL2 }, - { USB_DEVICE_VER(0x0545, 0x800d, 0x030a, 0x030a), .driver_info = CIT_MODEL4 }, - {} -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - const struct sd_desc *desc = &sd_desc; - - switch (id->driver_info) { - case CIT_MODEL0: - case CIT_MODEL1: - if (intf->cur_altsetting->desc.bInterfaceNumber != 2) - return -ENODEV; - break; - case CIT_MODEL2: - case CIT_MODEL4: - if (intf->cur_altsetting->desc.bInterfaceNumber != 0) - return -ENODEV; - break; - case CIT_MODEL3: - if (intf->cur_altsetting->desc.bInterfaceNumber != 0) - return -ENODEV; - /* FIXME this likely applies to all model3 cams and probably - to other models too. */ - if (ibm_netcam_pro) - desc = &sd_desc_isoc_nego; - break; - } - - return gspca_dev_probe2(intf, id, desc, sizeof(struct sd), THIS_MODULE); -} - -static struct usb_driver sd_driver = { - .name = MODULE_NAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); diff --git a/drivers/media/video/gspca/zc3xx-reg.h b/drivers/media/video/gspca/zc3xx-reg.h deleted file mode 100644 index a1bd94e8ce52..000000000000 --- a/drivers/media/video/gspca/zc3xx-reg.h +++ /dev/null @@ -1,251 +0,0 @@ -/* - * zc030x registers - * - * Copyright (c) 2008 Mauro Carvalho Chehab <mchehab@infradead.org> - * - * The register aliases used here came from this driver: - * http://zc0302.sourceforge.net/zc0302.php - * - * This code is placed under the terms of the GNU General Public License v2 - */ - -/* Define the register map */ -#define ZC3XX_R000_SYSTEMCONTROL 0x0000 -#define ZC3XX_R001_SYSTEMOPERATING 0x0001 - -/* Picture size */ -#define ZC3XX_R002_CLOCKSELECT 0x0002 -#define ZC3XX_R003_FRAMEWIDTHHIGH 0x0003 -#define ZC3XX_R004_FRAMEWIDTHLOW 0x0004 -#define ZC3XX_R005_FRAMEHEIGHTHIGH 0x0005 -#define ZC3XX_R006_FRAMEHEIGHTLOW 0x0006 - -/* JPEG control */ -#define ZC3XX_R008_CLOCKSETTING 0x0008 - -/* Test mode */ -#define ZC3XX_R00B_TESTMODECONTROL 0x000b - -/* Frame retreiving */ -#define ZC3XX_R00C_LASTACQTIME 0x000c -#define ZC3XX_R00D_MONITORRES 0x000d -#define ZC3XX_R00E_TIMESTAMPHIGH 0x000e -#define ZC3XX_R00F_TIMESTAMPLOW 0x000f -#define ZC3XX_R018_FRAMELOST 0x0018 -#define ZC3XX_R019_AUTOADJUSTFPS 0x0019 -#define ZC3XX_R01A_LASTFRAMESTATE 0x001a -#define ZC3XX_R025_DATACOUNTER 0x0025 - -/* Stream and sensor specific */ -#define ZC3XX_R010_CMOSSENSORSELECT 0x0010 -#define ZC3XX_R011_VIDEOSTATUS 0x0011 -#define ZC3XX_R012_VIDEOCONTROLFUNC 0x0012 - -/* Horizontal and vertical synchros */ -#define ZC3XX_R01D_HSYNC_0 0x001d -#define ZC3XX_R01E_HSYNC_1 0x001e -#define ZC3XX_R01F_HSYNC_2 0x001f -#define ZC3XX_R020_HSYNC_3 0x0020 - -/* Target picture size in byte */ -#define ZC3XX_R022_TARGETPICTSIZE_0 0x0022 -#define ZC3XX_R023_TARGETPICTSIZE_1 0x0023 -#define ZC3XX_R024_TARGETPICTSIZE_2 0x0024 - -/* Audio registers */ -#define ZC3XX_R030_AUDIOADC 0x0030 -#define ZC3XX_R031_AUDIOSTREAMSTATUS 0x0031 -#define ZC3XX_R032_AUDIOSTATUS 0x0032 - -/* Sensor interface */ -#define ZC3XX_R080_HBLANKHIGH 0x0080 -#define ZC3XX_R081_HBLANKLOW 0x0081 -#define ZC3XX_R082_RESETLEVELADDR 0x0082 -#define ZC3XX_R083_RGAINADDR 0x0083 -#define ZC3XX_R084_GGAINADDR 0x0084 -#define ZC3XX_R085_BGAINADDR 0x0085 -#define ZC3XX_R086_EXPTIMEHIGH 0x0086 -#define ZC3XX_R087_EXPTIMEMID 0x0087 -#define ZC3XX_R088_EXPTIMELOW 0x0088 -#define ZC3XX_R089_RESETBLACKHIGH 0x0089 -#define ZC3XX_R08A_RESETWHITEHIGH 0x008a -#define ZC3XX_R08B_I2CDEVICEADDR 0x008b -#define ZC3XX_R08C_I2CIDLEANDNACK 0x008c -#define ZC3XX_R08D_COMPABILITYMODE 0x008d -#define ZC3XX_R08E_COMPABILITYMODE2 0x008e - -/* I2C control */ -#define ZC3XX_R090_I2CCOMMAND 0x0090 -#define ZC3XX_R091_I2CSTATUS 0x0091 -#define ZC3XX_R092_I2CADDRESSSELECT 0x0092 -#define ZC3XX_R093_I2CSETVALUE 0x0093 -#define ZC3XX_R094_I2CWRITEACK 0x0094 -#define ZC3XX_R095_I2CREAD 0x0095 -#define ZC3XX_R096_I2CREADACK 0x0096 - -/* Window inside the sensor array */ -#define ZC3XX_R097_WINYSTARTHIGH 0x0097 -#define ZC3XX_R098_WINYSTARTLOW 0x0098 -#define ZC3XX_R099_WINXSTARTHIGH 0x0099 -#define ZC3XX_R09A_WINXSTARTLOW 0x009a -#define ZC3XX_R09B_WINHEIGHTHIGH 0x009b -#define ZC3XX_R09C_WINHEIGHTLOW 0x009c -#define ZC3XX_R09D_WINWIDTHHIGH 0x009d -#define ZC3XX_R09E_WINWIDTHLOW 0x009e -#define ZC3XX_R119_FIRSTYHIGH 0x0119 -#define ZC3XX_R11A_FIRSTYLOW 0x011a -#define ZC3XX_R11B_FIRSTXHIGH 0x011b -#define ZC3XX_R11C_FIRSTXLOW 0x011c - -/* Max sensor array size */ -#define ZC3XX_R09F_MAXXHIGH 0x009f -#define ZC3XX_R0A0_MAXXLOW 0x00a0 -#define ZC3XX_R0A1_MAXYHIGH 0x00a1 -#define ZC3XX_R0A2_MAXYLOW 0x00a2 -#define ZC3XX_R0A3_EXPOSURETIMEHIGH 0x00a3 -#define ZC3XX_R0A4_EXPOSURETIMELOW 0x00a4 -#define ZC3XX_R0A5_EXPOSUREGAIN 0x00a5 -#define ZC3XX_R0A6_EXPOSUREBLACKLVL 0x00a6 - -/* Other registers */ -#define ZC3XX_R100_OPERATIONMODE 0x0100 -#define ZC3XX_R101_SENSORCORRECTION 0x0101 - -/* Gains */ -#define ZC3XX_R116_RGAIN 0x0116 -#define ZC3XX_R117_GGAIN 0x0117 -#define ZC3XX_R118_BGAIN 0x0118 -#define ZC3XX_R11D_GLOBALGAIN 0x011d -#define ZC3XX_R1A8_DIGITALGAIN 0x01a8 -#define ZC3XX_R1A9_DIGITALLIMITDIFF 0x01a9 -#define ZC3XX_R1AA_DIGITALGAINSTEP 0x01aa - -/* Auto correction */ -#define ZC3XX_R180_AUTOCORRECTENABLE 0x0180 -#define ZC3XX_R181_WINXSTART 0x0181 -#define ZC3XX_R182_WINXWIDTH 0x0182 -#define ZC3XX_R183_WINXCENTER 0x0183 -#define ZC3XX_R184_WINYSTART 0x0184 -#define ZC3XX_R185_WINYWIDTH 0x0185 -#define ZC3XX_R186_WINYCENTER 0x0186 - -/* Gain range */ -#define ZC3XX_R187_MAXGAIN 0x0187 -#define ZC3XX_R188_MINGAIN 0x0188 - -/* Auto exposure and white balance */ -#define ZC3XX_R189_AWBSTATUS 0x0189 -#define ZC3XX_R18A_AWBFREEZE 0x018a -#define ZC3XX_R18B_AESTATUS 0x018b -#define ZC3XX_R18C_AEFREEZE 0x018c -#define ZC3XX_R18F_AEUNFREEZE 0x018f -#define ZC3XX_R190_EXPOSURELIMITHIGH 0x0190 -#define ZC3XX_R191_EXPOSURELIMITMID 0x0191 -#define ZC3XX_R192_EXPOSURELIMITLOW 0x0192 -#define ZC3XX_R195_ANTIFLICKERHIGH 0x0195 -#define ZC3XX_R196_ANTIFLICKERMID 0x0196 -#define ZC3XX_R197_ANTIFLICKERLOW 0x0197 - -/* What is this ? */ -#define ZC3XX_R18D_YTARGET 0x018d -#define ZC3XX_R18E_RESETLVL 0x018e - -/* Color */ -#define ZC3XX_R1A0_REDMEANAFTERAGC 0x01a0 -#define ZC3XX_R1A1_GREENMEANAFTERAGC 0x01a1 -#define ZC3XX_R1A2_BLUEMEANAFTERAGC 0x01a2 -#define ZC3XX_R1A3_REDMEANAFTERAWB 0x01a3 -#define ZC3XX_R1A4_GREENMEANAFTERAWB 0x01a4 -#define ZC3XX_R1A5_BLUEMEANAFTERAWB 0x01a5 -#define ZC3XX_R1A6_YMEANAFTERAE 0x01a6 -#define ZC3XX_R1A7_CALCGLOBALMEAN 0x01a7 - -/* Matrixes */ - -/* Color matrix is like : - R' = R * RGB00 + G * RGB01 + B * RGB02 + RGB03 - G' = R * RGB10 + G * RGB11 + B * RGB22 + RGB13 - B' = R * RGB20 + G * RGB21 + B * RGB12 + RGB23 - */ -#define ZC3XX_R10A_RGB00 0x010a -#define ZC3XX_R10B_RGB01 0x010b -#define ZC3XX_R10C_RGB02 0x010c -#define ZC3XX_R113_RGB03 0x0113 -#define ZC3XX_R10D_RGB10 0x010d -#define ZC3XX_R10E_RGB11 0x010e -#define ZC3XX_R10F_RGB12 0x010f -#define ZC3XX_R114_RGB13 0x0114 -#define ZC3XX_R110_RGB20 0x0110 -#define ZC3XX_R111_RGB21 0x0111 -#define ZC3XX_R112_RGB22 0x0112 -#define ZC3XX_R115_RGB23 0x0115 - -/* Gamma matrix */ -#define ZC3XX_R120_GAMMA00 0x0120 -#define ZC3XX_R121_GAMMA01 0x0121 -#define ZC3XX_R122_GAMMA02 0x0122 -#define ZC3XX_R123_GAMMA03 0x0123 -#define ZC3XX_R124_GAMMA04 0x0124 -#define ZC3XX_R125_GAMMA05 0x0125 -#define ZC3XX_R126_GAMMA06 0x0126 -#define ZC3XX_R127_GAMMA07 0x0127 -#define ZC3XX_R128_GAMMA08 0x0128 -#define ZC3XX_R129_GAMMA09 0x0129 -#define ZC3XX_R12A_GAMMA0A 0x012a -#define ZC3XX_R12B_GAMMA0B 0x012b -#define ZC3XX_R12C_GAMMA0C 0x012c -#define ZC3XX_R12D_GAMMA0D 0x012d -#define ZC3XX_R12E_GAMMA0E 0x012e -#define ZC3XX_R12F_GAMMA0F 0x012f -#define ZC3XX_R130_GAMMA10 0x0130 -#define ZC3XX_R131_GAMMA11 0x0131 -#define ZC3XX_R132_GAMMA12 0x0132 -#define ZC3XX_R133_GAMMA13 0x0133 -#define ZC3XX_R134_GAMMA14 0x0134 -#define ZC3XX_R135_GAMMA15 0x0135 -#define ZC3XX_R136_GAMMA16 0x0136 -#define ZC3XX_R137_GAMMA17 0x0137 -#define ZC3XX_R138_GAMMA18 0x0138 -#define ZC3XX_R139_GAMMA19 0x0139 -#define ZC3XX_R13A_GAMMA1A 0x013a -#define ZC3XX_R13B_GAMMA1B 0x013b -#define ZC3XX_R13C_GAMMA1C 0x013c -#define ZC3XX_R13D_GAMMA1D 0x013d -#define ZC3XX_R13E_GAMMA1E 0x013e -#define ZC3XX_R13F_GAMMA1F 0x013f - -/* Luminance gamma */ -#define ZC3XX_R140_YGAMMA00 0x0140 -#define ZC3XX_R141_YGAMMA01 0x0141 -#define ZC3XX_R142_YGAMMA02 0x0142 -#define ZC3XX_R143_YGAMMA03 0x0143 -#define ZC3XX_R144_YGAMMA04 0x0144 -#define ZC3XX_R145_YGAMMA05 0x0145 -#define ZC3XX_R146_YGAMMA06 0x0146 -#define ZC3XX_R147_YGAMMA07 0x0147 -#define ZC3XX_R148_YGAMMA08 0x0148 -#define ZC3XX_R149_YGAMMA09 0x0149 -#define ZC3XX_R14A_YGAMMA0A 0x014a -#define ZC3XX_R14B_YGAMMA0B 0x014b -#define ZC3XX_R14C_YGAMMA0C 0x014c -#define ZC3XX_R14D_YGAMMA0D 0x014d -#define ZC3XX_R14E_YGAMMA0E 0x014e -#define ZC3XX_R14F_YGAMMA0F 0x014f -#define ZC3XX_R150_YGAMMA10 0x0150 -#define ZC3XX_R151_YGAMMA11 0x0151 - -#define ZC3XX_R1C5_SHARPNESSMODE 0x01c5 -#define ZC3XX_R1C6_SHARPNESS00 0x01c6 -#define ZC3XX_R1C7_SHARPNESS01 0x01c7 -#define ZC3XX_R1C8_SHARPNESS02 0x01c8 -#define ZC3XX_R1C9_SHARPNESS03 0x01c9 -#define ZC3XX_R1CA_SHARPNESS04 0x01ca -#define ZC3XX_R1CB_SHARPNESS05 0x01cb - -/* Dead pixels */ -#define ZC3XX_R250_DEADPIXELSMODE 0x0250 - -/* EEPROM */ -#define ZC3XX_R300_EEPROMCONFIG 0x0300 -#define ZC3XX_R301_EEPROMACCESS 0x0301 -#define ZC3XX_R302_EEPROMSTATUS 0x0302 diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c deleted file mode 100644 index f0bacee33ef9..000000000000 --- a/drivers/media/video/gspca/zc3xx.c +++ /dev/null @@ -1,7024 +0,0 @@ -/* - * Z-Star/Vimicro zc301/zc302p/vc30x driver - * - * Copyright (C) 2009-2012 Jean-Francois Moine <http://moinejf.free.fr> - * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.fr - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/input.h> -#include "gspca.h" -#include "jpeg.h" - -MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, " - "Serge A. Suchkov <Serge.A.S@tochka.ru>"); -MODULE_DESCRIPTION("GSPCA ZC03xx/VC3xx USB Camera Driver"); -MODULE_LICENSE("GPL"); - -static int force_sensor = -1; - -#define REG08_DEF 3 /* default JPEG compression (75%) */ -#include "zc3xx-reg.h" - -/* specific webcam descriptor */ -struct sd { - struct gspca_dev gspca_dev; /* !! must be the first item */ - - struct { /* gamma/brightness/contrast control cluster */ - struct v4l2_ctrl *gamma; - struct v4l2_ctrl *brightness; - struct v4l2_ctrl *contrast; - }; - struct { /* autogain/exposure control cluster */ - struct v4l2_ctrl *autogain; - struct v4l2_ctrl *exposure; - }; - struct v4l2_ctrl *plfreq; - struct v4l2_ctrl *sharpness; - struct v4l2_ctrl *jpegqual; - - struct work_struct work; - struct workqueue_struct *work_thread; - - u8 reg08; /* webcam compression quality */ - - u8 bridge; - u8 sensor; /* Type of image sensor chip */ - u16 chip_revision; - - u8 jpeg_hdr[JPEG_HDR_SZ]; -}; -enum bridges { - BRIDGE_ZC301, - BRIDGE_ZC303, -}; -enum sensors { - SENSOR_ADCM2700, - SENSOR_CS2102, - SENSOR_CS2102K, - SENSOR_GC0303, - SENSOR_GC0305, - SENSOR_HDCS2020, - SENSOR_HV7131B, - SENSOR_HV7131R, - SENSOR_ICM105A, - SENSOR_MC501CB, - SENSOR_MT9V111_1, /* (mi360soc) zc301 */ - SENSOR_MT9V111_3, /* (mi360soc) zc303 */ - SENSOR_OV7620, /* OV7648 - same values */ - SENSOR_OV7630C, - SENSOR_PAS106, - SENSOR_PAS202B, - SENSOR_PB0330, - SENSOR_PO2030, - SENSOR_TAS5130C, - SENSOR_MAX -}; - -static const struct v4l2_pix_format vga_mode[] = { - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 240 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 480 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; - -static const struct v4l2_pix_format broken_vga_mode[] = { - {320, 232, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 320, - .sizeimage = 320 * 232 * 4 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, - {640, 472, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 640, - .sizeimage = 640 * 472 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; - -static const struct v4l2_pix_format sif_mode[] = { - {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 176, - .sizeimage = 176 * 144 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 1}, - {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, - .bytesperline = 352, - .sizeimage = 352 * 288 * 3 / 8 + 590, - .colorspace = V4L2_COLORSPACE_JPEG, - .priv = 0}, -}; - -/* - * Bridge reg08 bits 1-2 -> JPEG quality conversion table. Note the highest - * quality setting is not usable as USB 1 does not have enough bandwidth. - */ -static u8 jpeg_qual[] = {50, 75, 87, /* 94 */}; - -/* usb exchanges */ -struct usb_action { - u8 req; - u8 val; - u16 idx; -}; - -static const struct usb_action adcm2700_Initial[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ - {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */ - {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */ - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ - {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */ - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */ - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */ - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */ - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */ - {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */ - {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */ - {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */ - {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ - {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */ - {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ - {0xa0, 0x58, ZC3XX_R116_RGAIN}, /* 01,16,58,cc */ - {0xa0, 0x5a, ZC3XX_R118_BGAIN}, /* 01,18,5a,cc */ - {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */ - {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */ - {0xbb, 0x00, 0x0408}, /* 04,00,08,bb */ - {0xdd, 0x00, 0x0200}, /* 00,02,00,dd */ - {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */ - {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ - {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */ - {0xbb, 0xe0, 0x0c2e}, /* 0c,e0,2e,bb */ - {0xbb, 0x01, 0x2000}, /* 20,01,00,bb */ - {0xbb, 0x96, 0x2400}, /* 24,96,00,bb */ - {0xbb, 0x06, 0x1006}, /* 10,06,06,bb */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ - {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ - {0xbb, 0x5f, 0x2090}, /* 20,5f,90,bb */ - {0xbb, 0x01, 0x8000}, /* 80,01,00,bb */ - {0xbb, 0x09, 0x8400}, /* 84,09,00,bb */ - {0xbb, 0x86, 0x0002}, /* 00,86,02,bb */ - {0xbb, 0xe6, 0x0401}, /* 04,e6,01,bb */ - {0xbb, 0x86, 0x0802}, /* 08,86,02,bb */ - {0xbb, 0xe6, 0x0c01}, /* 0c,e6,01,bb */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ - {0xaa, 0xfe, 0x0000}, /* 00,fe,00,aa */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0020}, /* 00,fe,20,aa */ -/*mswin+*/ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, - {0xaa, 0xfe, 0x0002}, - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, - {0xaa, 0xb4, 0xcd37}, - {0xaa, 0xa4, 0x0004}, - {0xaa, 0xa8, 0x0007}, - {0xaa, 0xac, 0x0004}, -/*mswin-*/ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ - {0xaa, 0xfe, 0x0000}, /* 00,fe,00,aa */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ - {0xbb, 0x04, 0x0400}, /* 04,04,00,bb */ - {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ - {0xbb, 0x01, 0x0400}, /* 04,01,00,bb */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xbb, 0x41, 0x2803}, /* 28,41,03,bb */ - {0xbb, 0x40, 0x2c03}, /* 2c,40,03,bb */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ - {} -}; -static const struct usb_action adcm2700_InitialScale[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ - {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */ - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ - {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */ - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */ - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */ - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */ - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */ - {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d8,cc */ - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */ - {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */ - {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ - {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */ - {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ - {0xa0, 0x58, ZC3XX_R116_RGAIN}, /* 01,16,58,cc */ - {0xa0, 0x5a, ZC3XX_R118_BGAIN}, /* 01,18,5a,cc */ - {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */ - {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,d3,cc */ - {0xbb, 0x00, 0x0408}, /* 04,00,08,bb */ - {0xdd, 0x00, 0x0200}, /* 00,02,00,dd */ - {0xbb, 0x00, 0x0400}, /* 04,00,00,bb */ - {0xdd, 0x00, 0x0050}, /* 00,00,50,dd */ - {0xbb, 0x0f, 0x140f}, /* 14,0f,0f,bb */ - {0xbb, 0xe0, 0x0c2e}, /* 0c,e0,2e,bb */ - {0xbb, 0x01, 0x2000}, /* 20,01,00,bb */ - {0xbb, 0x96, 0x2400}, /* 24,96,00,bb */ - {0xbb, 0x06, 0x1006}, /* 10,06,06,bb */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ - {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ - {0xbb, 0x5f, 0x2090}, /* 20,5f,90,bb */ - {0xbb, 0x01, 0x8000}, /* 80,01,00,bb */ - {0xbb, 0x09, 0x8400}, /* 84,09,00,bb */ - {0xbb, 0x86, 0x0002}, /* 00,88,02,bb */ - {0xbb, 0xe6, 0x0401}, /* 04,e6,01,bb */ - {0xbb, 0x86, 0x0802}, /* 08,88,02,bb */ - {0xbb, 0xe6, 0x0c01}, /* 0c,e6,01,bb */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ - {0xaa, 0xfe, 0x0000}, /* 00,fe,00,aa */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0020}, /* 00,fe,20,aa */ - /*******/ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ - {0xaa, 0xfe, 0x0000}, /* 00,fe,00,aa */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xdd, 0x00, 0x0010}, /* 00,00,10,dd */ - {0xbb, 0x04, 0x0400}, /* 04,04,00,bb */ - {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ - {0xbb, 0x01, 0x0400}, /* 04,01,00,bb */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xbb, 0x41, 0x2803}, /* 28,41,03,bb */ - {0xbb, 0x40, 0x2c03}, /* 2c,40,03,bb */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ - {} -}; -static const struct usb_action adcm2700_50HZ[] = { - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xbb, 0x05, 0x8400}, /* 84,05,00,bb */ - {0xbb, 0xd0, 0xb007}, /* b0,d0,07,bb */ - {0xbb, 0xa0, 0xb80f}, /* b8,a0,0f,bb */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ - {0xaa, 0x26, 0x00d0}, /* 00,26,d0,aa */ - {0xaa, 0x28, 0x0002}, /* 00,28,02,aa */ - {} -}; -static const struct usb_action adcm2700_60HZ[] = { - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xbb, 0x07, 0x8400}, /* 84,07,00,bb */ - {0xbb, 0x82, 0xb006}, /* b0,82,06,bb */ - {0xbb, 0x04, 0xb80d}, /* b8,04,0d,bb */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ - {0xaa, 0x26, 0x0057}, /* 00,26,57,aa */ - {0xaa, 0x28, 0x0002}, /* 00,28,02,aa */ - {} -}; -static const struct usb_action adcm2700_NoFliker[] = { - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */ - {0xbb, 0x07, 0x8400}, /* 84,07,00,bb */ - {0xbb, 0x05, 0xb000}, /* b0,05,00,bb */ - {0xbb, 0xa0, 0xb801}, /* b8,a0,01,bb */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ - {} -}; -static const struct usb_action cs2102_InitialScale[] = { /* 320x240 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x20, ZC3XX_R080_HBLANKHIGH}, - {0xa0, 0x21, ZC3XX_R081_HBLANKLOW}, - {0xa0, 0x30, ZC3XX_R083_RGAINADDR}, - {0xa0, 0x31, ZC3XX_R084_GGAINADDR}, - {0xa0, 0x32, ZC3XX_R085_BGAINADDR}, - {0xa0, 0x23, ZC3XX_R086_EXPTIMEHIGH}, - {0xa0, 0x24, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x25, ZC3XX_R088_EXPTIMELOW}, - {0xa0, 0xb3, ZC3XX_R08B_I2CDEVICEADDR}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xaa, 0x02, 0x0008}, - {0xaa, 0x03, 0x0000}, - {0xaa, 0x11, 0x0000}, - {0xaa, 0x12, 0x0089}, - {0xaa, 0x13, 0x0000}, - {0xaa, 0x14, 0x00e9}, - {0xaa, 0x20, 0x0000}, - {0xaa, 0x22, 0x0000}, - {0xaa, 0x0b, 0x0004}, - {0xaa, 0x30, 0x0030}, - {0xaa, 0x31, 0x0030}, - {0xaa, 0x32, 0x0030}, - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x10, 0x01ae}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x68, ZC3XX_R18D_YTARGET}, - {0xa0, 0x00, 0x01ad}, - {} -}; - -static const struct usb_action cs2102_Initial[] = { /* 640x480 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x20, ZC3XX_R080_HBLANKHIGH}, - {0xa0, 0x21, ZC3XX_R081_HBLANKLOW}, - {0xa0, 0x30, ZC3XX_R083_RGAINADDR}, - {0xa0, 0x31, ZC3XX_R084_GGAINADDR}, - {0xa0, 0x32, ZC3XX_R085_BGAINADDR}, - {0xa0, 0x23, ZC3XX_R086_EXPTIMEHIGH}, - {0xa0, 0x24, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x25, ZC3XX_R088_EXPTIMELOW}, - {0xa0, 0xb3, ZC3XX_R08B_I2CDEVICEADDR}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xaa, 0x02, 0x0008}, - {0xaa, 0x03, 0x0000}, - {0xaa, 0x11, 0x0001}, - {0xaa, 0x12, 0x0087}, - {0xaa, 0x13, 0x0001}, - {0xaa, 0x14, 0x00e7}, - {0xaa, 0x20, 0x0000}, - {0xaa, 0x22, 0x0000}, - {0xaa, 0x0b, 0x0004}, - {0xaa, 0x30, 0x0030}, - {0xaa, 0x31, 0x0030}, - {0xaa, 0x32, 0x0030}, - {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x15, 0x01ae}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x68, ZC3XX_R18D_YTARGET}, - {0xa0, 0x00, 0x01ad}, - {} -}; -static const struct usb_action cs2102_50HZScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x23, 0x0001}, - {0xaa, 0x24, 0x005f}, - {0xaa, 0x25, 0x0090}, - {0xaa, 0x21, 0x00dd}, - {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0xbf, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x3a, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x98, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xdd, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xe4, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {} -}; -static const struct usb_action cs2102_50HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x23, 0x0000}, - {0xaa, 0x24, 0x00af}, - {0xaa, 0x25, 0x00c8}, - {0xaa, 0x21, 0x0068}, - {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x5f, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x90, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x1d, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x4c, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x68, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xe3, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {} -}; -static const struct usb_action cs2102_60HZScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x23, 0x0001}, - {0xaa, 0x24, 0x0055}, - {0xaa, 0x25, 0x00cc}, - {0xaa, 0x21, 0x003f}, - {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0xab, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x98, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x30, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0xd4, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x39, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x70, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xb0, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {} -}; -static const struct usb_action cs2102_60HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x23, 0x0000}, - {0xaa, 0x24, 0x00aa}, - {0xaa, 0x25, 0x00e6}, - {0xaa, 0x21, 0x003f}, - {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x55, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xcc, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x18, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x6a, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x3f, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xa5, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {} -}; -static const struct usb_action cs2102_NoFlikerScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x23, 0x0001}, - {0xaa, 0x24, 0x005f}, - {0xaa, 0x25, 0x0000}, - {0xaa, 0x21, 0x0001}, - {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0xbf, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x80, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x01, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xa0, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {} -}; -static const struct usb_action cs2102_NoFliker[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x23, 0x0000}, - {0xaa, 0x24, 0x00af}, - {0xaa, 0x25, 0x0080}, - {0xaa, 0x21, 0x0001}, - {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x5f, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x80, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x01, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xa0, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {} -}; - -/* CS2102_KOCOM */ -static const struct usb_action cs2102K_InitialScale[] = { - {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, - {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0a, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0b, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0c, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x7c, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0d, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0xa3, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0e, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x78, ZC3XX_R18D_YTARGET}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x00, 0x01ad}, - {0xa0, 0x01, 0x01b1}, - {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x60, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x4c, ZC3XX_R118_BGAIN}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */ - {0xa0, 0x38, ZC3XX_R121_GAMMA01}, - {0xa0, 0x59, ZC3XX_R122_GAMMA02}, - {0xa0, 0x79, ZC3XX_R123_GAMMA03}, - {0xa0, 0x92, ZC3XX_R124_GAMMA04}, - {0xa0, 0xa7, ZC3XX_R125_GAMMA05}, - {0xa0, 0xb9, ZC3XX_R126_GAMMA06}, - {0xa0, 0xc8, ZC3XX_R127_GAMMA07}, - {0xa0, 0xd4, ZC3XX_R128_GAMMA08}, - {0xa0, 0xdf, ZC3XX_R129_GAMMA09}, - {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A}, - {0xa0, 0xee, ZC3XX_R12B_GAMMA0B}, - {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C}, - {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D}, - {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E}, - {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, - {0xa0, 0x26, ZC3XX_R130_GAMMA10}, - {0xa0, 0x22, ZC3XX_R131_GAMMA11}, - {0xa0, 0x20, ZC3XX_R132_GAMMA12}, - {0xa0, 0x1c, ZC3XX_R133_GAMMA13}, - {0xa0, 0x16, ZC3XX_R134_GAMMA14}, - {0xa0, 0x13, ZC3XX_R135_GAMMA15}, - {0xa0, 0x10, ZC3XX_R136_GAMMA16}, - {0xa0, 0x0d, ZC3XX_R137_GAMMA17}, - {0xa0, 0x0b, ZC3XX_R138_GAMMA18}, - {0xa0, 0x09, ZC3XX_R139_GAMMA19}, - {0xa0, 0x07, ZC3XX_R13A_GAMMA1A}, - {0xa0, 0x06, ZC3XX_R13B_GAMMA1B}, - {0xa0, 0x05, ZC3XX_R13C_GAMMA1C}, - {0xa0, 0x04, ZC3XX_R13D_GAMMA1D}, - {0xa0, 0x03, ZC3XX_R13E_GAMMA1E}, - {0xa0, 0x02, ZC3XX_R13F_GAMMA1F}, - {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf4, ZC3XX_R10B_RGB01}, - {0xa0, 0xf4, ZC3XX_R10C_RGB02}, - {0xa0, 0xf4, ZC3XX_R10D_RGB10}, - {0xa0, 0x58, ZC3XX_R10E_RGB11}, - {0xa0, 0xf4, ZC3XX_R10F_RGB12}, - {0xa0, 0xf4, ZC3XX_R110_RGB20}, - {0xa0, 0xf4, ZC3XX_R111_RGB21}, - {0xa0, 0x58, ZC3XX_R112_RGB22}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, - {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x19, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0x1f, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x60, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x4c, ZC3XX_R118_BGAIN}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {} -}; - -static const struct usb_action cs2102K_Initial[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, -/*fixme: next sequence = i2c exchanges*/ - {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0a, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0b, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0c, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x7b, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0d, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0xa3, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0e, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x78, ZC3XX_R18D_YTARGET}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x00, 0x01ad}, - {0xa0, 0x01, 0x01b1}, - {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x60, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x4c, ZC3XX_R118_BGAIN}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */ - {0xa0, 0x38, ZC3XX_R121_GAMMA01}, - {0xa0, 0x59, ZC3XX_R122_GAMMA02}, - {0xa0, 0x79, ZC3XX_R123_GAMMA03}, - {0xa0, 0x92, ZC3XX_R124_GAMMA04}, - {0xa0, 0xa7, ZC3XX_R125_GAMMA05}, - {0xa0, 0xb9, ZC3XX_R126_GAMMA06}, - {0xa0, 0xc8, ZC3XX_R127_GAMMA07}, - {0xa0, 0xd4, ZC3XX_R128_GAMMA08}, - {0xa0, 0xdf, ZC3XX_R129_GAMMA09}, - {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A}, - {0xa0, 0xee, ZC3XX_R12B_GAMMA0B}, - {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C}, - {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D}, - {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E}, - {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, - {0xa0, 0x26, ZC3XX_R130_GAMMA10}, - {0xa0, 0x22, ZC3XX_R131_GAMMA11}, - {0xa0, 0x20, ZC3XX_R132_GAMMA12}, - {0xa0, 0x1c, ZC3XX_R133_GAMMA13}, - {0xa0, 0x16, ZC3XX_R134_GAMMA14}, - {0xa0, 0x13, ZC3XX_R135_GAMMA15}, - {0xa0, 0x10, ZC3XX_R136_GAMMA16}, - {0xa0, 0x0d, ZC3XX_R137_GAMMA17}, - {0xa0, 0x0b, ZC3XX_R138_GAMMA18}, - {0xa0, 0x09, ZC3XX_R139_GAMMA19}, - {0xa0, 0x07, ZC3XX_R13A_GAMMA1A}, - {0xa0, 0x06, ZC3XX_R13B_GAMMA1B}, - {0xa0, 0x05, ZC3XX_R13C_GAMMA1C}, - {0xa0, 0x04, ZC3XX_R13D_GAMMA1D}, - {0xa0, 0x03, ZC3XX_R13E_GAMMA1E}, - {0xa0, 0x02, ZC3XX_R13F_GAMMA1F}, - {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf4, ZC3XX_R10B_RGB01}, - {0xa0, 0xf4, ZC3XX_R10C_RGB02}, - {0xa0, 0xf4, ZC3XX_R10D_RGB10}, - {0xa0, 0x58, ZC3XX_R10E_RGB11}, - {0xa0, 0xf4, ZC3XX_R10F_RGB12}, - {0xa0, 0xf4, ZC3XX_R110_RGB20}, - {0xa0, 0xf4, ZC3XX_R111_RGB21}, - {0xa0, 0x58, ZC3XX_R112_RGB22}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, - {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x19, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0x1f, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x60, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x4c, ZC3XX_R118_BGAIN}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, -/*fixme:what does the next sequence?*/ - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0xd0, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0xd0, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x0a, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x0a, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x44, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x44, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x7e, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x7e, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {} -}; - -static const struct usb_action gc0305_Initial[] = { /* 640x480 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */ - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */ - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */ - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */ - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */ - {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc */ - {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */ - {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc */ - {0xaa, 0x13, 0x0002}, /* 00,13,02,aa */ - {0xaa, 0x15, 0x0003}, /* 00,15,03,aa */ - {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */ - {0xaa, 0x02, 0x0000}, /* 00,02,00,aa */ - {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */ - {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa */ - {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */ - {0xaa, 0x1f, 0x0008}, /* 00,1f,08,aa */ - {0xaa, 0x21, 0x0012}, /* 00,21,12,aa */ - {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc */ - {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc */ - {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc */ - {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */ - {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa */ - {0xaa, 0x0b, 0x00b0}, /* 00,0b,b0,aa */ - {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa */ - {0xaa, 0x0d, 0x00b0}, /* 00,0d,b0,aa */ - {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa */ - {0xaa, 0x0f, 0x00b0}, /* 00,0f,b0,aa */ - {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ - {0xaa, 0x11, 0x00b0}, /* 00,11,b0,aa */ - {0xaa, 0x16, 0x0001}, /* 00,16,01,aa */ - {0xaa, 0x17, 0x00e6}, /* 00,17,e6,aa */ - {0xaa, 0x18, 0x0002}, /* 00,18,02,aa */ - {0xaa, 0x19, 0x0086}, /* 00,19,86,aa */ - {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */ - {0xaa, 0x1b, 0x0020}, /* 00,1b,20,aa */ - {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc */ - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ - {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc */ - {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc */ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ - {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */ - {0xa0, 0x85, ZC3XX_R18D_YTARGET}, /* 01,8d,85,cc */ - {0xa0, 0x00, 0x011e}, /* 01,1e,00,cc */ - {0xa0, 0x52, ZC3XX_R116_RGAIN}, /* 01,16,52,cc */ - {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* 01,17,40,cc */ - {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */ - {0xa0, 0x03, ZC3XX_R113_RGB03}, /* 01,13,03,cc */ - {} -}; -static const struct usb_action gc0305_InitialScale[] = { /* 320x240 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */ - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */ - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */ - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */ - {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc */ - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */ - {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc */ - {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */ - {0xaa, 0x15, 0x0001}, /* 00,15,01,aa */ - {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */ - {0xaa, 0x02, 0x0000}, /* 00,02,00,aa */ - {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */ - {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa */ - {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */ - {0xaa, 0x1f, 0x0008}, /* 00,1f,08,aa */ - {0xaa, 0x21, 0x0012}, /* 00,21,12,aa */ - {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc */ - {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc */ - {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc */ - {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */ - {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa */ - {0xaa, 0x0b, 0x00b0}, /* 00,0b,b0,aa */ - {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa */ - {0xaa, 0x0d, 0x00b0}, /* 00,0d,b0,aa */ - {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa */ - {0xaa, 0x0f, 0x00b0}, /* 00,0f,b0,aa */ - {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ - {0xaa, 0x11, 0x00b0}, /* 00,11,b0,aa */ - {0xaa, 0x16, 0x0001}, /* 00,16,01,aa */ - {0xaa, 0x17, 0x00e8}, /* 00,17,e8,aa */ - {0xaa, 0x18, 0x0002}, /* 00,18,02,aa */ - {0xaa, 0x19, 0x0088}, /* 00,19,88,aa */ - {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */ - {0xaa, 0x1b, 0x0020}, /* 00,1b,20,aa */ - {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc */ - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ - {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc */ - {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc */ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ - {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */ - {0xa0, 0x00, 0x011e}, /* 01,1e,00,cc */ - {0xa0, 0x52, ZC3XX_R116_RGAIN}, /* 01,16,52,cc */ - {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* 01,17,40,cc */ - {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */ - {0xa0, 0x03, ZC3XX_R113_RGB03}, /* 01,13,03,cc */ - {} -}; -static const struct usb_action gc0305_50HZ[] = { - {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ - {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */ - {0xaa, 0x84, 0x0038}, /* 00,84,38,aa */ /* win: 00,84,ec */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0b,cc */ - {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */ - /* win: 01,92,10 */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,8e,cc */ - /* win: 01,97,ec */ - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc */ - {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc */ - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */ - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ - {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc */ - {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */ - {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,60,cc */ - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */ -/* {0xa0, 0x85, ZC3XX_R18D_YTARGET}, * 01,8d,85,cc * - * if 640x480 */ - {} -}; -static const struct usb_action gc0305_60HZ[] = { - {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ - {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ - {0xaa, 0x84, 0x00ec}, /* 00,84,ec,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0b,cc */ - {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0xec, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,ec,cc */ - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc */ - {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc */ - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */ - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ - {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc */ - {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */ - {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,60,cc */ - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */ - {0xa0, 0x80, ZC3XX_R18D_YTARGET}, /* 01,8d,80,cc */ - {} -}; - -static const struct usb_action gc0305_NoFliker[] = { - {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc */ - {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ - {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ - {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,00,cc */ - {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,48,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */ - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc */ - {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc */ - {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc */ - {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */ - {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,60,cc */ - {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,03,cc */ - {0xa0, 0x80, ZC3XX_R18D_YTARGET}, /* 01,8d,80,cc */ - {} -}; - -static const struct usb_action hdcs2020_InitialScale[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* qtable 0x05 */ - {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, - {0xaa, 0x1c, 0x0000}, - {0xaa, 0x0a, 0x0001}, - {0xaa, 0x0b, 0x0006}, - {0xaa, 0x0c, 0x007b}, - {0xaa, 0x0d, 0x00a7}, - {0xaa, 0x03, 0x00fb}, - {0xaa, 0x05, 0x0000}, - {0xaa, 0x06, 0x0003}, - {0xaa, 0x09, 0x0008}, - - {0xaa, 0x0f, 0x0018}, /* set sensor gain */ - {0xaa, 0x10, 0x0018}, - {0xaa, 0x11, 0x0018}, - {0xaa, 0x12, 0x0018}, - - {0xaa, 0x15, 0x004e}, - {0xaa, 0x1c, 0x0004}, - {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x70, ZC3XX_R18D_YTARGET}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa1, 0x01, 0x0002}, - {0xa1, 0x01, 0x0008}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x40, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x40, ZC3XX_R118_BGAIN}, - {0xa1, 0x01, 0x0008}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa1, 0x01, 0x01c8}, - {0xa1, 0x01, 0x01c9}, - {0xa1, 0x01, 0x01ca}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */ - {0xa0, 0x38, ZC3XX_R121_GAMMA01}, - {0xa0, 0x59, ZC3XX_R122_GAMMA02}, - {0xa0, 0x79, ZC3XX_R123_GAMMA03}, - {0xa0, 0x92, ZC3XX_R124_GAMMA04}, - {0xa0, 0xa7, ZC3XX_R125_GAMMA05}, - {0xa0, 0xb9, ZC3XX_R126_GAMMA06}, - {0xa0, 0xc8, ZC3XX_R127_GAMMA07}, - {0xa0, 0xd4, ZC3XX_R128_GAMMA08}, - {0xa0, 0xdf, ZC3XX_R129_GAMMA09}, - {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A}, - {0xa0, 0xee, ZC3XX_R12B_GAMMA0B}, - {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C}, - {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D}, - {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E}, - {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, - {0xa0, 0x26, ZC3XX_R130_GAMMA10}, - {0xa0, 0x22, ZC3XX_R131_GAMMA11}, - {0xa0, 0x20, ZC3XX_R132_GAMMA12}, - {0xa0, 0x1c, ZC3XX_R133_GAMMA13}, - {0xa0, 0x16, ZC3XX_R134_GAMMA14}, - {0xa0, 0x13, ZC3XX_R135_GAMMA15}, - {0xa0, 0x10, ZC3XX_R136_GAMMA16}, - {0xa0, 0x0d, ZC3XX_R137_GAMMA17}, - {0xa0, 0x0b, ZC3XX_R138_GAMMA18}, - {0xa0, 0x09, ZC3XX_R139_GAMMA19}, - {0xa0, 0x07, ZC3XX_R13A_GAMMA1A}, - {0xa0, 0x06, ZC3XX_R13B_GAMMA1B}, - {0xa0, 0x05, ZC3XX_R13C_GAMMA1C}, - {0xa0, 0x04, ZC3XX_R13D_GAMMA1D}, - {0xa0, 0x03, ZC3XX_R13E_GAMMA1E}, - {0xa0, 0x02, ZC3XX_R13F_GAMMA1F}, - - {0xa0, 0x66, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xed, ZC3XX_R10B_RGB01}, - {0xa0, 0xed, ZC3XX_R10C_RGB02}, - {0xa0, 0xed, ZC3XX_R10D_RGB10}, - {0xa0, 0x66, ZC3XX_R10E_RGB11}, - {0xa0, 0xed, ZC3XX_R10F_RGB12}, - {0xa0, 0xed, ZC3XX_R110_RGB20}, - {0xa0, 0xed, ZC3XX_R111_RGB21}, - {0xa0, 0x66, ZC3XX_R112_RGB22}, - - {0xa1, 0x01, 0x0180}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x13, 0x0031}, - {0xaa, 0x14, 0x0001}, - {0xaa, 0x0e, 0x0004}, - {0xaa, 0x19, 0x00cd}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - - {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 0x14 */ - {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x18, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0x41, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x40, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x40, ZC3XX_R118_BGAIN}, - {} -}; -static const struct usb_action hdcs2020_Initial[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, - {0xaa, 0x1c, 0x0000}, - {0xaa, 0x0a, 0x0001}, - {0xaa, 0x0b, 0x0006}, - {0xaa, 0x0c, 0x007a}, - {0xaa, 0x0d, 0x00a7}, - {0xaa, 0x03, 0x00fb}, - {0xaa, 0x05, 0x0000}, - {0xaa, 0x06, 0x0003}, - {0xaa, 0x09, 0x0008}, - {0xaa, 0x0f, 0x0018}, /* original setting */ - {0xaa, 0x10, 0x0018}, - {0xaa, 0x11, 0x0018}, - {0xaa, 0x12, 0x0018}, - {0xaa, 0x15, 0x004e}, - {0xaa, 0x1c, 0x0004}, - {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x70, ZC3XX_R18D_YTARGET}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa1, 0x01, 0x0002}, - {0xa1, 0x01, 0x0008}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x40, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x40, ZC3XX_R118_BGAIN}, - {0xa1, 0x01, 0x0008}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa1, 0x01, 0x01c8}, - {0xa1, 0x01, 0x01c9}, - {0xa1, 0x01, 0x01ca}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */ - {0xa0, 0x38, ZC3XX_R121_GAMMA01}, - {0xa0, 0x59, ZC3XX_R122_GAMMA02}, - {0xa0, 0x79, ZC3XX_R123_GAMMA03}, - {0xa0, 0x92, ZC3XX_R124_GAMMA04}, - {0xa0, 0xa7, ZC3XX_R125_GAMMA05}, - {0xa0, 0xb9, ZC3XX_R126_GAMMA06}, - {0xa0, 0xc8, ZC3XX_R127_GAMMA07}, - {0xa0, 0xd4, ZC3XX_R128_GAMMA08}, - {0xa0, 0xdf, ZC3XX_R129_GAMMA09}, - {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A}, - {0xa0, 0xee, ZC3XX_R12B_GAMMA0B}, - {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C}, - {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D}, - {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E}, - {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, - {0xa0, 0x26, ZC3XX_R130_GAMMA10}, - {0xa0, 0x22, ZC3XX_R131_GAMMA11}, - {0xa0, 0x20, ZC3XX_R132_GAMMA12}, - {0xa0, 0x1c, ZC3XX_R133_GAMMA13}, - {0xa0, 0x16, ZC3XX_R134_GAMMA14}, - {0xa0, 0x13, ZC3XX_R135_GAMMA15}, - {0xa0, 0x10, ZC3XX_R136_GAMMA16}, - {0xa0, 0x0d, ZC3XX_R137_GAMMA17}, - {0xa0, 0x0b, ZC3XX_R138_GAMMA18}, - {0xa0, 0x09, ZC3XX_R139_GAMMA19}, - {0xa0, 0x07, ZC3XX_R13A_GAMMA1A}, - {0xa0, 0x06, ZC3XX_R13B_GAMMA1B}, - {0xa0, 0x05, ZC3XX_R13C_GAMMA1C}, - {0xa0, 0x04, ZC3XX_R13D_GAMMA1D}, - {0xa0, 0x03, ZC3XX_R13E_GAMMA1E}, - {0xa0, 0x02, ZC3XX_R13F_GAMMA1F}, - {0xa0, 0x66, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xed, ZC3XX_R10B_RGB01}, - {0xa0, 0xed, ZC3XX_R10C_RGB02}, - {0xa0, 0xed, ZC3XX_R10D_RGB10}, - {0xa0, 0x66, ZC3XX_R10E_RGB11}, - {0xa0, 0xed, ZC3XX_R10F_RGB12}, - {0xa0, 0xed, ZC3XX_R110_RGB20}, - {0xa0, 0xed, ZC3XX_R111_RGB21}, - {0xa0, 0x66, ZC3XX_R112_RGB22}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - /**** set exposure ***/ - {0xaa, 0x13, 0x0031}, - {0xaa, 0x14, 0x0001}, - {0xaa, 0x0e, 0x0004}, - {0xaa, 0x19, 0x00cd}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x18, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0x41, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x40, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x40, ZC3XX_R118_BGAIN}, - {} -}; -static const struct usb_action hdcs2020_50HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x13, 0x0018}, /* 00,13,18,aa */ - {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */ - {0xaa, 0x0e, 0x0005}, /* 00,0e,05,aa */ - {0xaa, 0x19, 0x001f}, /* 00,19,1f,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */ - {0xa0, 0x76, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,76,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x46, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,46,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ - {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,28,cc */ - {0xa0, 0x05, ZC3XX_R01D_HSYNC_0}, /* 00,1d,05,cc */ - {0xa0, 0x1a, ZC3XX_R01E_HSYNC_1}, /* 00,1e,1a,cc */ - {0xa0, 0x2f, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2f,cc */ - {} -}; -static const struct usb_action hdcs2020_60HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x13, 0x0031}, /* 00,13,31,aa */ - {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */ - {0xaa, 0x0e, 0x0004}, /* 00,0e,04,aa */ - {0xaa, 0x19, 0x00cd}, /* 00,19,cd,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */ - {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,62,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3d,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */ - {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,28,cc */ - {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, /* 00,1d,04,cc */ - {0xa0, 0x18, ZC3XX_R01E_HSYNC_1}, /* 00,1e,18,cc */ - {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2c,cc */ - {} -}; -static const struct usb_action hdcs2020_NoFliker[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x13, 0x0010}, /* 00,13,10,aa */ - {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */ - {0xaa, 0x0e, 0x0004}, /* 00,0e,04,aa */ - {0xaa, 0x19, 0x0000}, /* 00,19,00,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */ - {0xa0, 0x70, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,70,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ - {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, /* 00,1d,04,cc */ - {0xa0, 0x17, ZC3XX_R01E_HSYNC_1}, /* 00,1e,17,cc */ - {0xa0, 0x2a, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2a,cc */ - {} -}; - -static const struct usb_action hv7131b_InitialScale[] = { /* 320x240 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xaa, 0x30, 0x002d}, - {0xaa, 0x01, 0x0005}, - {0xaa, 0x11, 0x0000}, - {0xaa, 0x13, 0x0001}, /* {0xaa, 0x13, 0x0000}, */ - {0xaa, 0x14, 0x0001}, - {0xaa, 0x15, 0x00e8}, - {0xaa, 0x16, 0x0002}, - {0xaa, 0x17, 0x0086}, /* 00,17,88,aa */ - {0xaa, 0x31, 0x0038}, - {0xaa, 0x32, 0x0038}, - {0xaa, 0x33, 0x0038}, - {0xaa, 0x5b, 0x0001}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x68, ZC3XX_R18D_YTARGET}, - {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x00, 0x01ad}, - {0xa0, 0xc0, 0x019b}, - {0xa0, 0xa0, 0x019c}, - {0xa0, 0x02, ZC3XX_R188_MINGAIN}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xaa, 0x02, 0x0090}, /* 00,02,80,aa */ - {} -}; - -static const struct usb_action hv7131b_Initial[] = { /* 640x480*/ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xaa, 0x30, 0x002d}, - {0xaa, 0x01, 0x0005}, - {0xaa, 0x11, 0x0001}, - {0xaa, 0x13, 0x0000}, /* {0xaa, 0x13, 0x0001}; */ - {0xaa, 0x14, 0x0001}, - {0xaa, 0x15, 0x00e6}, - {0xaa, 0x16, 0x0002}, - {0xaa, 0x17, 0x0086}, - {0xaa, 0x31, 0x0038}, - {0xaa, 0x32, 0x0038}, - {0xaa, 0x33, 0x0038}, - {0xaa, 0x5b, 0x0001}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x70, ZC3XX_R18D_YTARGET}, - {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x00, 0x01ad}, - {0xa0, 0xc0, 0x019b}, - {0xa0, 0xa0, 0x019c}, - {0xa0, 0x02, ZC3XX_R188_MINGAIN}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xaa, 0x02, 0x0090}, /* {0xaa, 0x02, 0x0080}, */ - {} -}; -static const struct usb_action hv7131b_50HZ[] = { /* 640x480*/ - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x25, 0x0007}, /* 00,25,07,aa */ - {0xaa, 0x26, 0x0053}, /* 00,26,53,aa */ - {0xaa, 0x27, 0x0000}, /* 00,27,00,aa */ - {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */ - {0xaa, 0x21, 0x0050}, /* 00,21,50,aa */ - {0xaa, 0x22, 0x001b}, /* 00,22,1b,aa */ - {0xaa, 0x23, 0x00fc}, /* 00,23,fc,aa */ - {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */ - {0xa0, 0x9b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,9b,cc */ - {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,80,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0xea, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,ea,cc */ - {0xa0, 0x60, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,60,cc */ - {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */ - {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */ - {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */ - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ - {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */ - {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, /* 00,1e,50,cc */ - {0xa0, 0x1b, ZC3XX_R01F_HSYNC_2}, /* 00,1f,1b,cc */ - {0xa0, 0xfc, ZC3XX_R020_HSYNC_3}, /* 00,20,fc,cc */ - {} -}; -static const struct usb_action hv7131b_50HZScale[] = { /* 320x240 */ - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x25, 0x0007}, /* 00,25,07,aa */ - {0xaa, 0x26, 0x0053}, /* 00,26,53,aa */ - {0xaa, 0x27, 0x0000}, /* 00,27,00,aa */ - {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */ - {0xaa, 0x21, 0x0050}, /* 00,21,50,aa */ - {0xaa, 0x22, 0x0012}, /* 00,22,12,aa */ - {0xaa, 0x23, 0x0080}, /* 00,23,80,aa */ - {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */ - {0xa0, 0x9b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,9b,cc */ - {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,80,cc */ - {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,01,cc */ - {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,d4,cc */ - {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,c0,cc */ - {0xa0, 0x07, ZC3XX_R18C_AEFREEZE}, /* 01,8c,07,cc */ - {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,0f,cc */ - {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */ - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ - {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */ - {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, /* 00,1e,50,cc */ - {0xa0, 0x12, ZC3XX_R01F_HSYNC_2}, /* 00,1f,12,cc */ - {0xa0, 0x80, ZC3XX_R020_HSYNC_3}, /* 00,20,80,cc */ - {} -}; -static const struct usb_action hv7131b_60HZ[] = { /* 640x480*/ - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x25, 0x0007}, /* 00,25,07,aa */ - {0xaa, 0x26, 0x00a1}, /* 00,26,a1,aa */ - {0xaa, 0x27, 0x0020}, /* 00,27,20,aa */ - {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */ - {0xaa, 0x21, 0x0040}, /* 00,21,40,aa */ - {0xaa, 0x22, 0x0013}, /* 00,22,13,aa */ - {0xaa, 0x23, 0x004c}, /* 00,23,4c,aa */ - {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */ - {0xa0, 0x4d, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,4d,cc */ - {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,60,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0xc3, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,c3,cc */ - {0xa0, 0x50, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,50,cc */ - {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */ - {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */ - {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */ - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ - {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */ - {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, /* 00,1e,40,cc */ - {0xa0, 0x13, ZC3XX_R01F_HSYNC_2}, /* 00,1f,13,cc */ - {0xa0, 0x4c, ZC3XX_R020_HSYNC_3}, /* 00,20,4c,cc */ - {} -}; -static const struct usb_action hv7131b_60HZScale[] = { /* 320x240 */ - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x25, 0x0007}, /* 00,25,07,aa */ - {0xaa, 0x26, 0x00a1}, /* 00,26,a1,aa */ - {0xaa, 0x27, 0x0020}, /* 00,27,20,aa */ - {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */ - {0xaa, 0x21, 0x00a0}, /* 00,21,a0,aa */ - {0xaa, 0x22, 0x0016}, /* 00,22,16,aa */ - {0xaa, 0x23, 0x0040}, /* 00,23,40,aa */ - {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */ - {0xa0, 0x4d, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,4d,cc */ - {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,60,cc */ - {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,01,cc */ - {0xa0, 0x86, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,86,cc */ - {0xa0, 0xa0, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,a0,cc */ - {0xa0, 0x07, ZC3XX_R18C_AEFREEZE}, /* 01,8c,07,cc */ - {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,0f,cc */ - {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,18,cc */ - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ - {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */ - {0xa0, 0xa0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,a0,cc */ - {0xa0, 0x16, ZC3XX_R01F_HSYNC_2}, /* 00,1f,16,cc */ - {0xa0, 0x40, ZC3XX_R020_HSYNC_3}, /* 00,20,40,cc */ - {} -}; -static const struct usb_action hv7131b_NoFliker[] = { /* 640x480*/ - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x25, 0x0003}, /* 00,25,03,aa */ - {0xaa, 0x26, 0x0000}, /* 00,26,00,aa */ - {0xaa, 0x27, 0x0000}, /* 00,27,00,aa */ - {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */ - {0xaa, 0x21, 0x0010}, /* 00,21,10,aa */ - {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */ - {0xaa, 0x23, 0x0003}, /* 00,23,03,aa */ - {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */ - {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,f8,cc */ - {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,00,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,02,cc */ - {0xa0, 0x00, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,00,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ - {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */ - {0xa0, 0x10, ZC3XX_R01E_HSYNC_1}, /* 00,1e,10,cc */ - {0xa0, 0x00, ZC3XX_R01F_HSYNC_2}, /* 00,1f,00,cc */ - {0xa0, 0x03, ZC3XX_R020_HSYNC_3}, /* 00,20,03,cc */ - {} -}; -static const struct usb_action hv7131b_NoFlikerScale[] = { /* 320x240 */ - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x25, 0x0003}, /* 00,25,03,aa */ - {0xaa, 0x26, 0x0000}, /* 00,26,00,aa */ - {0xaa, 0x27, 0x0000}, /* 00,27,00,aa */ - {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */ - {0xaa, 0x21, 0x00a0}, /* 00,21,a0,aa */ - {0xaa, 0x22, 0x0016}, /* 00,22,16,aa */ - {0xaa, 0x23, 0x0040}, /* 00,23,40,aa */ - {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,2f,cc */ - {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,f8,cc */ - {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,00,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,02,cc */ - {0xa0, 0x00, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,00,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ - {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, /* 00,1d,00,cc */ - {0xa0, 0xa0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,a0,cc */ - {0xa0, 0x16, ZC3XX_R01F_HSYNC_2}, /* 00,1f,16,cc */ - {0xa0, 0x40, ZC3XX_R020_HSYNC_3}, /* 00,20,40,cc */ - {} -}; - -/* from lPEPI264v.inf (hv7131b!) */ -static const struct usb_action hv7131r_InitialScale[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, - {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xdd, 0x00, 0x0200}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xaa, 0x01, 0x000c}, - {0xaa, 0x11, 0x0000}, - {0xaa, 0x13, 0x0000}, - {0xaa, 0x14, 0x0001}, - {0xaa, 0x15, 0x00e8}, - {0xaa, 0x16, 0x0002}, - {0xaa, 0x17, 0x0088}, - {0xaa, 0x30, 0x000b}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x78, ZC3XX_R18D_YTARGET}, - {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x00, 0x01ad}, - {0xa0, 0xc0, 0x019b}, - {0xa0, 0xa0, 0x019c}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {} -}; -static const struct usb_action hv7131r_Initial[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, - {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, - {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xdd, 0x00, 0x0200}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xaa, 0x01, 0x000c}, - {0xaa, 0x11, 0x0000}, - {0xaa, 0x13, 0x0000}, - {0xaa, 0x14, 0x0001}, - {0xaa, 0x15, 0x00e6}, - {0xaa, 0x16, 0x0002}, - {0xaa, 0x17, 0x0086}, - {0xaa, 0x30, 0x000b}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x78, ZC3XX_R18D_YTARGET}, - {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x00, 0x01ad}, - {0xa0, 0xc0, 0x019b}, - {0xa0, 0xa0, 0x019c}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {} -}; -static const struct usb_action hv7131r_50HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x06, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x68, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0xea, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x60, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x18, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x00, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0x08, ZC3XX_R020_HSYNC_3}, - {} -}; -static const struct usb_action hv7131r_50HZScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x0c, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0xd1, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x40, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x18, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x00, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0x08, ZC3XX_R020_HSYNC_3}, - {} -}; -static const struct usb_action hv7131r_60HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x06, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x1a, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0xc3, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x50, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x18, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x00, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0x08, ZC3XX_R020_HSYNC_3}, - {} -}; -static const struct usb_action hv7131r_60HZScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x0c, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x35, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x86, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0xa0, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x18, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x00, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0x08, ZC3XX_R020_HSYNC_3}, - {} -}; -static const struct usb_action hv7131r_NoFliker[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x58, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x00, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0x08, ZC3XX_R020_HSYNC_3}, - {} -}; -static const struct usb_action hv7131r_NoFlikerScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x04, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0xb0, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x00, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x00, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0x08, ZC3XX_R020_HSYNC_3}, - {} -}; - -static const struct usb_action icm105a_InitialScale[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x0c, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, - {0xa0, 0x00, ZC3XX_R097_WINYSTARTHIGH}, - {0xa0, 0x01, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R099_WINXSTARTHIGH}, - {0xa0, 0x01, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x01, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x01, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, - {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xaa, 0x01, 0x0010}, - {0xaa, 0x03, 0x0000}, - {0xaa, 0x04, 0x0001}, - {0xaa, 0x05, 0x0020}, - {0xaa, 0x06, 0x0001}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0001}, - {0xaa, 0x04, 0x0011}, - {0xaa, 0x05, 0x00a0}, - {0xaa, 0x06, 0x0001}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0002}, - {0xaa, 0x04, 0x0013}, - {0xaa, 0x05, 0x0020}, - {0xaa, 0x06, 0x0001}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0003}, - {0xaa, 0x04, 0x0015}, - {0xaa, 0x05, 0x0020}, - {0xaa, 0x06, 0x0005}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0004}, - {0xaa, 0x04, 0x0017}, - {0xaa, 0x05, 0x0020}, - {0xaa, 0x06, 0x000d}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0005}, - {0xaa, 0x04, 0x0019}, - {0xaa, 0x05, 0x0020}, - {0xaa, 0x06, 0x0005}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0006}, - {0xaa, 0x04, 0x0017}, - {0xaa, 0x05, 0x0026}, - {0xaa, 0x06, 0x0005}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0007}, - {0xaa, 0x04, 0x0019}, - {0xaa, 0x05, 0x0022}, - {0xaa, 0x06, 0x0005}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0008}, - {0xaa, 0x04, 0x0021}, - {0xaa, 0x05, 0x00aa}, - {0xaa, 0x06, 0x0005}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0009}, - {0xaa, 0x04, 0x0023}, - {0xaa, 0x05, 0x00aa}, - {0xaa, 0x06, 0x000d}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x000a}, - {0xaa, 0x04, 0x0025}, - {0xaa, 0x05, 0x00aa}, - {0xaa, 0x06, 0x0005}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x000b}, - {0xaa, 0x04, 0x00ec}, - {0xaa, 0x05, 0x002e}, - {0xaa, 0x06, 0x0005}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x000c}, - {0xaa, 0x04, 0x00fa}, - {0xaa, 0x05, 0x002a}, - {0xaa, 0x06, 0x0005}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x07, 0x000d}, - {0xaa, 0x01, 0x0005}, - {0xaa, 0x94, 0x0002}, - {0xaa, 0x90, 0x0000}, - {0xaa, 0x91, 0x001f}, - {0xaa, 0x10, 0x0064}, - {0xaa, 0x9b, 0x00f0}, - {0xaa, 0x9c, 0x0002}, - {0xaa, 0x14, 0x001a}, - {0xaa, 0x20, 0x0080}, - {0xaa, 0x22, 0x0080}, - {0xaa, 0x24, 0x0080}, - {0xaa, 0x26, 0x0080}, - {0xaa, 0x00, 0x0084}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xaa, 0xa8, 0x00c0}, - {0xa1, 0x01, 0x0002}, - {0xa1, 0x01, 0x0008}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x40, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x40, ZC3XX_R118_BGAIN}, - {0xa1, 0x01, 0x0008}, - - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa1, 0x01, 0x01c8}, - {0xa1, 0x01, 0x01c9}, - {0xa1, 0x01, 0x01ca}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - {0xa0, 0x52, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf7, ZC3XX_R10B_RGB01}, - {0xa0, 0xf7, ZC3XX_R10C_RGB02}, - {0xa0, 0xf7, ZC3XX_R10D_RGB10}, - {0xa0, 0x52, ZC3XX_R10E_RGB11}, - {0xa0, 0xf7, ZC3XX_R10F_RGB12}, - {0xa0, 0xf7, ZC3XX_R110_RGB20}, - {0xa0, 0xf7, ZC3XX_R111_RGB21}, - {0xa0, 0x52, ZC3XX_R112_RGB22}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x0d, 0x0003}, - {0xaa, 0x0c, 0x008c}, - {0xaa, 0x0e, 0x0095}, - {0xaa, 0x0f, 0x0002}, - {0xaa, 0x1c, 0x0094}, - {0xaa, 0x1d, 0x0002}, - {0xaa, 0x20, 0x0080}, - {0xaa, 0x22, 0x0080}, - {0xaa, 0x24, 0x0080}, - {0xaa, 0x26, 0x0080}, - {0xaa, 0x00, 0x0084}, - {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, - {0xa0, 0x94, ZC3XX_R0A4_EXPOSURETIMELOW}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x84, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xe3, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xec, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xf5, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0xc0, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x40, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x40, ZC3XX_R118_BGAIN}, - {} -}; - -static const struct usb_action icm105a_Initial[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x0c, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, - {0xa0, 0x00, ZC3XX_R097_WINYSTARTHIGH}, - {0xa0, 0x02, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R099_WINXSTARTHIGH}, - {0xa0, 0x02, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x02, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, - {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, - {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, - {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xaa, 0x01, 0x0010}, - {0xaa, 0x03, 0x0000}, - {0xaa, 0x04, 0x0001}, - {0xaa, 0x05, 0x0020}, - {0xaa, 0x06, 0x0001}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0001}, - {0xaa, 0x04, 0x0011}, - {0xaa, 0x05, 0x00a0}, - {0xaa, 0x06, 0x0001}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0002}, - {0xaa, 0x04, 0x0013}, - {0xaa, 0x05, 0x0020}, - {0xaa, 0x06, 0x0001}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0003}, - {0xaa, 0x04, 0x0015}, - {0xaa, 0x05, 0x0020}, - {0xaa, 0x06, 0x0005}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0004}, - {0xaa, 0x04, 0x0017}, - {0xaa, 0x05, 0x0020}, - {0xaa, 0x06, 0x000d}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0005}, - {0xa0, 0x04, ZC3XX_R092_I2CADDRESSSELECT}, - {0xa0, 0x19, ZC3XX_R093_I2CSETVALUE}, - {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND}, - {0xa1, 0x01, 0x0091}, - {0xaa, 0x05, 0x0020}, - {0xaa, 0x06, 0x0005}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0006}, - {0xaa, 0x04, 0x0017}, - {0xaa, 0x05, 0x0026}, - {0xaa, 0x06, 0x0005}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0007}, - {0xaa, 0x04, 0x0019}, - {0xaa, 0x05, 0x0022}, - {0xaa, 0x06, 0x0005}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0008}, - {0xaa, 0x04, 0x0021}, - {0xaa, 0x05, 0x00aa}, - {0xaa, 0x06, 0x0005}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x0009}, - {0xaa, 0x04, 0x0023}, - {0xaa, 0x05, 0x00aa}, - {0xaa, 0x06, 0x000d}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x000a}, - {0xaa, 0x04, 0x0025}, - {0xaa, 0x05, 0x00aa}, - {0xaa, 0x06, 0x0005}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x000b}, - {0xaa, 0x04, 0x00ec}, - {0xaa, 0x05, 0x002e}, - {0xaa, 0x06, 0x0005}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x03, 0x000c}, - {0xaa, 0x04, 0x00fa}, - {0xaa, 0x05, 0x002a}, - {0xaa, 0x06, 0x0005}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x07, 0x000d}, - {0xaa, 0x01, 0x0005}, - {0xaa, 0x94, 0x0002}, - {0xaa, 0x90, 0x0000}, - {0xaa, 0x91, 0x0010}, - {0xaa, 0x10, 0x0064}, - {0xaa, 0x9b, 0x00f0}, - {0xaa, 0x9c, 0x0002}, - {0xaa, 0x14, 0x001a}, - {0xaa, 0x20, 0x0080}, - {0xaa, 0x22, 0x0080}, - {0xaa, 0x24, 0x0080}, - {0xaa, 0x26, 0x0080}, - {0xaa, 0x00, 0x0084}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xaa, 0xa8, 0x0080}, - {0xa0, 0x78, ZC3XX_R18D_YTARGET}, - {0xa1, 0x01, 0x0002}, - {0xa1, 0x01, 0x0008}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x40, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x40, ZC3XX_R118_BGAIN}, - {0xa1, 0x01, 0x0008}, - - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa1, 0x01, 0x01c8}, - {0xa1, 0x01, 0x01c9}, - {0xa1, 0x01, 0x01ca}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - - {0xa0, 0x52, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf7, ZC3XX_R10B_RGB01}, - {0xa0, 0xf7, ZC3XX_R10C_RGB02}, - {0xa0, 0xf7, ZC3XX_R10D_RGB10}, - {0xa0, 0x52, ZC3XX_R10E_RGB11}, - {0xa0, 0xf7, ZC3XX_R10F_RGB12}, - {0xa0, 0xf7, ZC3XX_R110_RGB20}, - {0xa0, 0xf7, ZC3XX_R111_RGB21}, - {0xa0, 0x52, ZC3XX_R112_RGB22}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x0d, 0x0003}, - {0xaa, 0x0c, 0x0020}, - {0xaa, 0x0e, 0x000e}, - {0xaa, 0x0f, 0x0002}, - {0xaa, 0x1c, 0x000d}, - {0xaa, 0x1d, 0x0002}, - {0xaa, 0x20, 0x0080}, - {0xaa, 0x22, 0x0080}, - {0xaa, 0x24, 0x0080}, - {0xaa, 0x26, 0x0080}, - {0xaa, 0x00, 0x0084}, - {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, - {0xa0, 0x0d, ZC3XX_R0A4_EXPOSURETIMELOW}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x1a, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x4b, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xd8, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0180}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x40, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x40, ZC3XX_R118_BGAIN}, - {} -}; -static const struct usb_action icm105a_50HZScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ - {0xaa, 0x0c, 0x0020}, /* 00,0c,20,aa */ - {0xaa, 0x0e, 0x000e}, /* 00,0e,0e,aa */ - {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */ - {0xaa, 0x1c, 0x000d}, /* 00,1c,0d,aa */ - {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */ - {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */ - {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */ - {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */ - {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */ - {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */ - {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */ - {0xa0, 0x0d, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,0d,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */ - {0xa0, 0x1a, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,1a,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x4b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,4b,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */ - {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */ - {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */ - {0xa0, 0xd8, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d8,cc */ - {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {} -}; -static const struct usb_action icm105a_50HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ - {0xaa, 0x0c, 0x008c}, /* 00,0c,8c,aa */ - {0xaa, 0x0e, 0x0095}, /* 00,0e,95,aa */ - {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */ - {0xaa, 0x1c, 0x0094}, /* 00,1c,94,aa */ - {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */ - {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */ - {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */ - {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */ - {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */ - {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */ - {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */ - {0xa0, 0x94, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,94,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */ - {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x84, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,84,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */ - {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */ - {0xa0, 0xe3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,e3,cc */ - {0xa0, 0xec, ZC3XX_R01E_HSYNC_1}, /* 00,1e,ec,cc */ - {0xa0, 0xf5, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f5,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */ - {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */ - {} -}; -static const struct usb_action icm105a_60HZScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ - {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */ - {0xaa, 0x0e, 0x000d}, /* 00,0e,0d,aa */ - {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */ - {0xaa, 0x1c, 0x0008}, /* 00,1c,08,aa */ - {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */ - {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */ - {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */ - {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */ - {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */ - {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */ - {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */ - {0xa0, 0x08, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,08,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */ - {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x41, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,41,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */ - {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */ - {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */ - {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */ - {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {} -}; -static const struct usb_action icm105a_60HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ - {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */ - {0xaa, 0x0e, 0x0086}, /* 00,0e,86,aa */ - {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */ - {0xaa, 0x1c, 0x0085}, /* 00,1c,85,aa */ - {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */ - {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */ - {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */ - {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */ - {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */ - {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */ - {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */ - {0xa0, 0x85, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,85,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */ - {0xa0, 0x08, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,08,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,81,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */ - {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */ - {0xa0, 0xc2, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c2,cc */ - {0xa0, 0xd6, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d6,cc */ - {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */ - {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */ - {} -}; -static const struct usb_action icm105a_NoFlikerScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ - {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */ - {0xaa, 0x0e, 0x000d}, /* 00,0e,0d,aa */ - {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */ - {0xaa, 0x1c, 0x0000}, /* 00,1c,00,aa */ - {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */ - {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */ - {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */ - {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */ - {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */ - {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */ - {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */ - {0xa0, 0x00, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,00,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */ - {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ - {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */ - {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */ - {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {} -}; -static const struct usb_action icm105a_NoFliker[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ - {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */ - {0xaa, 0x0e, 0x0081}, /* 00,0e,81,aa */ - {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */ - {0xaa, 0x1c, 0x0080}, /* 00,1c,80,aa */ - {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */ - {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */ - {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */ - {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */ - {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */ - {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */ - {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */ - {0xa0, 0x80, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,80,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */ - {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ - {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */ - {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */ - {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */ - {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */ - {} -}; - -static const struct usb_action mc501cb_Initial[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */ - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */ - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ - {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */ - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */ - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */ - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */ - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */ - {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */ - {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */ - {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */ - {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */ - {0xa0, 0x33, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,33,cc */ - {0xa0, 0x34, ZC3XX_R087_EXPTIMEMID}, /* 00,87,34,cc */ - {0xa0, 0x35, ZC3XX_R088_EXPTIMELOW}, /* 00,88,35,cc */ - {0xa0, 0xb0, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,b0,cc */ - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */ - {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */ - {0xaa, 0x01, 0x0003}, /* 00,01,03,aa */ - {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */ - {0xaa, 0x03, 0x0000}, /* 00,03,00,aa */ - {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ - {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */ - {0xaa, 0x12, 0x0000}, /* 00,12,00,aa */ - {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */ - {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */ - {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */ - {0xaa, 0x16, 0x0000}, /* 00,16,00,aa */ - {0xaa, 0x17, 0x0001}, /* 00,17,01,aa */ - {0xaa, 0x18, 0x00de}, /* 00,18,de,aa */ - {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */ - {0xaa, 0x1a, 0x0086}, /* 00,1a,86,aa */ - {0xaa, 0x20, 0x00a8}, /* 00,20,a8,aa */ - {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */ - {0xaa, 0x23, 0x0000}, /* 00,23,00,aa */ - {0xaa, 0x24, 0x0000}, /* 00,24,00,aa */ - {0xaa, 0x40, 0x0033}, /* 00,40,33,aa */ - {0xaa, 0x41, 0x0077}, /* 00,41,77,aa */ - {0xaa, 0x42, 0x0053}, /* 00,42,53,aa */ - {0xaa, 0x43, 0x00b0}, /* 00,43,b0,aa */ - {0xaa, 0x4b, 0x0001}, /* 00,4b,01,aa */ - {0xaa, 0x72, 0x0020}, /* 00,72,20,aa */ - {0xaa, 0x73, 0x0000}, /* 00,73,00,aa */ - {0xaa, 0x80, 0x0000}, /* 00,80,00,aa */ - {0xaa, 0x85, 0x0050}, /* 00,85,50,aa */ - {0xaa, 0x91, 0x0070}, /* 00,91,70,aa */ - {0xaa, 0x92, 0x0072}, /* 00,92,72,aa */ - {0xaa, 0x03, 0x0001}, /* 00,03,01,aa */ - {0xaa, 0x10, 0x00a0}, /* 00,10,a0,aa */ - {0xaa, 0x11, 0x0001}, /* 00,11,01,aa */ - {0xaa, 0x30, 0x0000}, /* 00,30,00,aa */ - {0xaa, 0x60, 0x0000}, /* 00,60,00,aa */ - {0xaa, 0xa0, 0x001a}, /* 00,a0,1a,aa */ - {0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */ - {0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */ - {0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */ - {0xaa, 0xa4, 0x0010}, /* 00,a4,10,aa */ - {0xaa, 0xa5, 0x0020}, /* 00,a5,20,aa */ - {0xaa, 0xb1, 0x0044}, /* 00,b1,44,aa */ - {0xaa, 0xd0, 0x0001}, /* 00,d0,01,aa */ - {0xaa, 0xd1, 0x0085}, /* 00,d1,85,aa */ - {0xaa, 0xd2, 0x0080}, /* 00,d2,80,aa */ - {0xaa, 0xd3, 0x0080}, /* 00,d3,80,aa */ - {0xaa, 0xd4, 0x0080}, /* 00,d4,80,aa */ - {0xaa, 0xd5, 0x0080}, /* 00,d5,80,aa */ - {0xaa, 0xc0, 0x00c3}, /* 00,c0,c3,aa */ - {0xaa, 0xc2, 0x0044}, /* 00,c2,44,aa */ - {0xaa, 0xc4, 0x0040}, /* 00,c4,40,aa */ - {0xaa, 0xc5, 0x0020}, /* 00,c5,20,aa */ - {0xaa, 0xc6, 0x0008}, /* 00,c6,08,aa */ - {0xaa, 0x03, 0x0004}, /* 00,03,04,aa */ - {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ - {0xaa, 0x40, 0x0030}, /* 00,40,30,aa */ - {0xaa, 0x41, 0x0020}, /* 00,41,20,aa */ - {0xaa, 0x42, 0x002d}, /* 00,42,2d,aa */ - {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ - {0xaa, 0x1c, 0x0050}, /* 00,1C,50,aa */ - {0xaa, 0x11, 0x0081}, /* 00,11,81,aa */ - {0xaa, 0x3b, 0x001d}, /* 00,3b,1D,aa */ - {0xaa, 0x3c, 0x004c}, /* 00,3c,4C,aa */ - {0xaa, 0x3d, 0x0018}, /* 00,3d,18,aa */ - {0xaa, 0x3e, 0x006a}, /* 00,3e,6A,aa */ - {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */ - {0xaa, 0x52, 0x00ff}, /* 00,52,FF,aa */ - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */ - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ - {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */ - {0xaa, 0x03, 0x0002}, /* 00,03,02,aa */ - {0xaa, 0x51, 0x0027}, /* 00,51,27,aa */ - {0xaa, 0x52, 0x0020}, /* 00,52,20,aa */ - {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ - {0xaa, 0x50, 0x0010}, /* 00,50,10,aa */ - {0xaa, 0x51, 0x0010}, /* 00,51,10,aa */ - {0xaa, 0x54, 0x0010}, /* 00,54,10,aa */ - {0xaa, 0x55, 0x0010}, /* 00,55,10,aa */ - {0xa0, 0xf0, 0x0199}, /* 01,99,F0,cc */ - {0xa0, 0x80, 0x019a}, /* 01,9A,80,cc */ - - {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ - {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ - {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */ - {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */ - {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */ - {} -}; - -static const struct usb_action mc501cb_InitialScale[] = { /* 320x240 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */ - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */ - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ - {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */ - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */ - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */ - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */ - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */ - {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */ - {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d8,cc */ - {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */ - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */ - {0xa0, 0x33, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,33,cc */ - {0xa0, 0x34, ZC3XX_R087_EXPTIMEMID}, /* 00,87,34,cc */ - {0xa0, 0x35, ZC3XX_R088_EXPTIMELOW}, /* 00,88,35,cc */ - {0xa0, 0xb0, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,b0,cc */ - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */ - {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */ - {0xaa, 0x01, 0x0003}, /* 00,01,03,aa */ - {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */ - {0xaa, 0x03, 0x0000}, /* 00,03,00,aa */ - {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ - {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */ - {0xaa, 0x12, 0x0000}, /* 00,12,00,aa */ - {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */ - {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */ - {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */ - {0xaa, 0x16, 0x0000}, /* 00,16,00,aa */ - {0xaa, 0x17, 0x0001}, /* 00,17,01,aa */ - {0xaa, 0x18, 0x00d8}, /* 00,18,d8,aa */ - {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */ - {0xaa, 0x1a, 0x0088}, /* 00,1a,88,aa */ - {0xaa, 0x20, 0x00a8}, /* 00,20,a8,aa */ - {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */ - {0xaa, 0x23, 0x0000}, /* 00,23,00,aa */ - {0xaa, 0x24, 0x0000}, /* 00,24,00,aa */ - {0xaa, 0x40, 0x0033}, /* 00,40,33,aa */ - {0xaa, 0x41, 0x0077}, /* 00,41,77,aa */ - {0xaa, 0x42, 0x0053}, /* 00,42,53,aa */ - {0xaa, 0x43, 0x00b0}, /* 00,43,b0,aa */ - {0xaa, 0x4b, 0x0001}, /* 00,4b,01,aa */ - {0xaa, 0x72, 0x0020}, /* 00,72,20,aa */ - {0xaa, 0x73, 0x0000}, /* 00,73,00,aa */ - {0xaa, 0x80, 0x0000}, /* 00,80,00,aa */ - {0xaa, 0x85, 0x0050}, /* 00,85,50,aa */ - {0xaa, 0x91, 0x0070}, /* 00,91,70,aa */ - {0xaa, 0x92, 0x0072}, /* 00,92,72,aa */ - {0xaa, 0x03, 0x0001}, /* 00,03,01,aa */ - {0xaa, 0x10, 0x00a0}, /* 00,10,a0,aa */ - {0xaa, 0x11, 0x0001}, /* 00,11,01,aa */ - {0xaa, 0x30, 0x0000}, /* 00,30,00,aa */ - {0xaa, 0x60, 0x0000}, /* 00,60,00,aa */ - {0xaa, 0xa0, 0x001a}, /* 00,a0,1a,aa */ - {0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */ - {0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */ - {0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */ - {0xaa, 0xa4, 0x0010}, /* 00,a4,10,aa */ - {0xaa, 0xa5, 0x0020}, /* 00,a5,20,aa */ - {0xaa, 0xb1, 0x0044}, /* 00,b1,44,aa */ - {0xaa, 0xd0, 0x0001}, /* 00,d0,01,aa */ - {0xaa, 0xd1, 0x0085}, /* 00,d1,85,aa */ - {0xaa, 0xd2, 0x0080}, /* 00,d2,80,aa */ - {0xaa, 0xd3, 0x0080}, /* 00,d3,80,aa */ - {0xaa, 0xd4, 0x0080}, /* 00,d4,80,aa */ - {0xaa, 0xd5, 0x0080}, /* 00,d5,80,aa */ - {0xaa, 0xc0, 0x00c3}, /* 00,c0,c3,aa */ - {0xaa, 0xc2, 0x0044}, /* 00,c2,44,aa */ - {0xaa, 0xc4, 0x0040}, /* 00,c4,40,aa */ - {0xaa, 0xc5, 0x0020}, /* 00,c5,20,aa */ - {0xaa, 0xc6, 0x0008}, /* 00,c6,08,aa */ - {0xaa, 0x03, 0x0004}, /* 00,03,04,aa */ - {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ - {0xaa, 0x40, 0x0030}, /* 00,40,30,aa */ - {0xaa, 0x41, 0x0020}, /* 00,41,20,aa */ - {0xaa, 0x42, 0x002d}, /* 00,42,2d,aa */ - {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ - {0xaa, 0x1c, 0x0050}, /* 00,1c,50,aa */ - {0xaa, 0x11, 0x0081}, /* 00,11,81,aa */ - {0xaa, 0x3b, 0x003a}, /* 00,3b,3A,aa */ - {0xaa, 0x3c, 0x0098}, /* 00,3c,98,aa */ - {0xaa, 0x3d, 0x0030}, /* 00,3d,30,aa */ - {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */ - {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */ - {0xaa, 0x52, 0x00ff}, /* 00,52,FF,aa */ - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */ - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ - {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */ - {0xaa, 0x03, 0x0002}, /* 00,03,02,aa */ - {0xaa, 0x51, 0x004e}, /* 00,51,4E,aa */ - {0xaa, 0x52, 0x0041}, /* 00,52,41,aa */ - {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ - {0xaa, 0x50, 0x0010}, /* 00,50,10,aa */ - {0xaa, 0x51, 0x0010}, /* 00,51,10,aa */ - {0xaa, 0x54, 0x0010}, /* 00,54,10,aa */ - {0xaa, 0x55, 0x0010}, /* 00,55,10,aa */ - {0xa0, 0xf0, 0x0199}, /* 01,99,F0,cc */ - {0xa0, 0x80, 0x019a}, /* 01,9A,80,cc */ - {} -}; - -static const struct usb_action mc501cb_50HZ[] = { - {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ - {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ - {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */ - {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */ - {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */ - {0xaa, 0x3c, 0x004c}, /* 00,3C,4C,aa */ - {0xaa, 0x3d, 0x001d}, /* 00,3D,1D,aa */ - {0xaa, 0x3e, 0x004c}, /* 00,3E,4C,aa */ - {} -}; - -static const struct usb_action mc501cb_50HZScale[] = { - {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ - {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ - {0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */ - {0xaa, 0x37, 0x0098}, /* 00,37,98,aa */ - {0xaa, 0x3b, 0x003a}, /* 00,3B,3A,aa */ - {0xaa, 0x3c, 0x0098}, /* 00,3C,98,aa */ - {0xaa, 0x3d, 0x003a}, /* 00,3D,3A,aa */ - {0xaa, 0x3e, 0x0098}, /* 00,3E,98,aa */ - {} -}; - -static const struct usb_action mc501cb_60HZ[] = { - {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ - {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ - {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */ - {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */ - {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */ - {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */ - {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */ - {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */ - {} -}; - -static const struct usb_action mc501cb_60HZScale[] = { - {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ - {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ - {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */ - {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */ - {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */ - {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */ - {0xaa, 0x3b, 0x0030}, /* 00,3B,30,aa */ - {0xaa, 0x3c, 0x00d4}, /* 00,3C,D4,aa */ - {} -}; - -static const struct usb_action mc501cb_NoFliker[] = { - {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ - {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ - {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */ - {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */ - {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */ - {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */ - {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */ - {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */ - {} -}; - -static const struct usb_action mc501cb_NoFlikerScale[] = { - {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ - {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ - {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */ - {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */ - {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */ - {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */ - {0xaa, 0x3b, 0x0030}, /* 00,3B,30,aa */ - {0xaa, 0x3c, 0x00d4}, /* 00,3C,D4,aa */ - {} -}; - -/* from zs211.inf */ -static const struct usb_action ov7620_Initial[] = { /* 640x480 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ - {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, /* 00,02,40,cc */ - {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ - {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,06,cc */ - {0xa0, 0x02, ZC3XX_R083_RGAINADDR}, /* 00,83,02,cc */ - {0xa0, 0x01, ZC3XX_R085_BGAINADDR}, /* 00,85,01,cc */ - {0xa0, 0x80, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,80,cc */ - {0xa0, 0x81, ZC3XX_R087_EXPTIMEMID}, /* 00,87,81,cc */ - {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW}, /* 00,88,10,cc */ - {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,a1,cc */ - {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */ - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ - {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */ - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */ - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */ - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */ - {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */ - {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */ - {0xaa, 0x12, 0x0088}, /* 00,12,88,aa */ - {0xaa, 0x12, 0x0048}, /* 00,12,48,aa */ - {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */ - {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ - {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */ - {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */ - {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */ - {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */ - {0xaa, 0x17, 0x0018}, /* 00,17,18,aa */ - {0xaa, 0x18, 0x00ba}, /* 00,18,ba,aa */ - {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */ - {0xaa, 0x1a, 0x00f1}, /* 00,1a,f1,aa */ - {0xaa, 0x20, 0x0040}, /* 00,20,40,aa */ - {0xaa, 0x24, 0x0088}, /* 00,24,88,aa */ - {0xaa, 0x25, 0x0078}, /* 00,25,78,aa */ - {0xaa, 0x27, 0x00f6}, /* 00,27,f6,aa */ - {0xaa, 0x28, 0x00a0}, /* 00,28,a0,aa */ - {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */ - {0xaa, 0x2a, 0x0083}, /* 00,2a,83,aa */ - {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */ - {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */ - {0xaa, 0x74, 0x0020}, /* 00,74,20,aa */ - {0xaa, 0x61, 0x0068}, /* 00,61,68,aa */ - {0xaa, 0x64, 0x0088}, /* 00,64,88,aa */ - {0xaa, 0x00, 0x0000}, /* 00,00,00,aa */ - {0xaa, 0x06, 0x0080}, /* 00,06,80,aa */ - {0xaa, 0x01, 0x0090}, /* 00,01,90,aa */ - {0xaa, 0x02, 0x0030}, /* 00,02,30,aa */ - {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,77,cc */ - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */ - {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ - {0xa0, 0x68, ZC3XX_R116_RGAIN}, /* 01,16,68,cc */ - {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */ - {0xa0, 0x40, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,40,cc */ - {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */ - {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */ - {} -}; -static const struct usb_action ov7620_InitialScale[] = { /* 320x240 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ - {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT}, /* 00,02,50,cc */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */ - /* mx change? */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ - {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,06,cc */ - {0xa0, 0x02, ZC3XX_R083_RGAINADDR}, /* 00,83,02,cc */ - {0xa0, 0x01, ZC3XX_R085_BGAINADDR}, /* 00,85,01,cc */ - {0xa0, 0x80, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,80,cc */ - {0xa0, 0x81, ZC3XX_R087_EXPTIMEMID}, /* 00,87,81,cc */ - {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW}, /* 00,88,10,cc */ - {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,a1,cc */ - {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */ - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ - {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */ - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */ - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */ - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */ - {0xa0, 0xd6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d6,cc */ - /* OV7648 00,9c,d8,cc */ - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */ - {0xaa, 0x12, 0x0088}, /* 00,12,88,aa */ - {0xaa, 0x12, 0x0048}, /* 00,12,48,aa */ - {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */ - {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ - {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */ - {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */ - {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */ - {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */ - {0xaa, 0x24, 0x0088}, /* 00,24,88,aa */ - {0xaa, 0x25, 0x0078}, /* 00,25,78,aa */ - {0xaa, 0x17, 0x0018}, /* 00,17,18,aa */ - {0xaa, 0x18, 0x00ba}, /* 00,18,ba,aa */ - {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */ - {0xaa, 0x1a, 0x00f2}, /* 00,1a,f2,aa */ - {0xaa, 0x20, 0x0040}, /* 00,20,40,aa */ - {0xaa, 0x27, 0x00f6}, /* 00,27,f6,aa */ - {0xaa, 0x28, 0x00a0}, /* 00,28,a0,aa */ - {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */ - {0xaa, 0x2a, 0x0083}, /* 00,2a,83,aa */ - {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */ - {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */ - {0xaa, 0x74, 0x0020}, /* 00,74,20,aa */ - {0xaa, 0x61, 0x0068}, /* 00,61,68,aa */ - {0xaa, 0x64, 0x0088}, /* 00,64,88,aa */ - {0xaa, 0x00, 0x0000}, /* 00,00,00,aa */ - {0xaa, 0x06, 0x0080}, /* 00,06,80,aa */ - {0xaa, 0x01, 0x0090}, /* 00,01,90,aa */ - {0xaa, 0x02, 0x0030}, /* 00,02,30,aa */ - {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,77,cc */ - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */ - {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ - {0xa0, 0x68, ZC3XX_R116_RGAIN}, /* 01,16,68,cc */ - {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */ - {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,50,cc */ - {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */ - {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */ - {} -}; -static const struct usb_action ov7620_50HZ[] = { - {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ - {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ - {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */ - {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */ - {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */ - {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */ - {0xaa, 0x10, 0x0082}, /* 00,10,82,aa */ - {0xaa, 0x76, 0x0003}, /* 00,76,03,aa */ -/* {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, * 00,02,40,cc - * if mode0 (640x480) */ - {} -}; -static const struct usb_action ov7620_60HZ[] = { - {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ - /* (bug in zs211.inf) */ - {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ - {0xaa, 0x2b, 0x0000}, /* 00,2b,00,aa */ - {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */ - {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */ - {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */ - {0xaa, 0x10, 0x0020}, /* 00,10,20,aa */ - {0xaa, 0x76, 0x0003}, /* 00,76,03,aa */ -/* {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, * 00,02,40,cc - * if mode0 (640x480) */ -/* ?? in gspca v1, it was - {0xa0, 0x00, 0x0039}, * 00,00,00,dd * - {0xa1, 0x01, 0x0037}, */ - {} -}; -static const struct usb_action ov7620_NoFliker[] = { - {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ - /* (bug in zs211.inf) */ - {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ - {0xaa, 0x2b, 0x0000}, /* 00,2b,00,aa */ - {0xaa, 0x75, 0x008e}, /* 00,75,8e,aa */ - {0xaa, 0x2d, 0x0001}, /* 00,2d,01,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */ - {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,01,cc */ -/* {0xa0, 0x44, ZC3XX_R002_CLOCKSELECT}, * 00,02,44,cc - * if mode1 (320x240) */ -/* ?? was - {0xa0, 0x00, 0x0039}, * 00,00,00,dd * - {0xa1, 0x01, 0x0037}, */ - {} -}; - -static const struct usb_action ov7630c_InitialScale[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, - {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xaa, 0x12, 0x0080}, - {0xa0, 0x02, ZC3XX_R083_RGAINADDR}, - {0xa0, 0x01, ZC3XX_R085_BGAINADDR}, - {0xa0, 0x90, ZC3XX_R086_EXPTIMEHIGH}, - {0xa0, 0x91, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, - {0xaa, 0x12, 0x0069}, - {0xaa, 0x04, 0x0020}, - {0xaa, 0x06, 0x0050}, - {0xaa, 0x13, 0x0083}, - {0xaa, 0x14, 0x0000}, - {0xaa, 0x15, 0x0024}, - {0xaa, 0x17, 0x0018}, - {0xaa, 0x18, 0x00ba}, - {0xaa, 0x19, 0x0002}, - {0xaa, 0x1a, 0x00f6}, - {0xaa, 0x1b, 0x0002}, - {0xaa, 0x20, 0x00c2}, - {0xaa, 0x24, 0x0060}, - {0xaa, 0x25, 0x0040}, - {0xaa, 0x26, 0x0030}, - {0xaa, 0x27, 0x00ea}, - {0xaa, 0x28, 0x00a0}, - {0xaa, 0x21, 0x0000}, - {0xaa, 0x2a, 0x0081}, - {0xaa, 0x2b, 0x0096}, - {0xaa, 0x2d, 0x0094}, - {0xaa, 0x2f, 0x003d}, - {0xaa, 0x30, 0x0024}, - {0xaa, 0x60, 0x0000}, - {0xaa, 0x61, 0x0040}, - {0xaa, 0x68, 0x007c}, - {0xaa, 0x6f, 0x0015}, - {0xaa, 0x75, 0x0088}, - {0xaa, 0x77, 0x00b5}, - {0xaa, 0x01, 0x0060}, - {0xaa, 0x02, 0x0060}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x00, 0x01ad}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x60, ZC3XX_R116_RGAIN}, - {0xa0, 0x46, ZC3XX_R118_BGAIN}, - {0xa0, 0x04, ZC3XX_R113_RGB03}, -/* 0x10, */ - {0xa1, 0x01, 0x0002}, - {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf8, ZC3XX_R10B_RGB01}, - {0xa0, 0xf8, ZC3XX_R10C_RGB02}, - {0xa0, 0xf8, ZC3XX_R10D_RGB10}, - {0xa0, 0x50, ZC3XX_R10E_RGB11}, - {0xa0, 0xf8, ZC3XX_R10F_RGB12}, - {0xa0, 0xf8, ZC3XX_R110_RGB20}, - {0xa0, 0xf8, ZC3XX_R111_RGB21}, - {0xa0, 0x50, ZC3XX_R112_RGB22}, - {0xa1, 0x01, 0x0008}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa1, 0x01, 0x01c8}, - {0xa1, 0x01, 0x01c9}, - {0xa1, 0x01, 0x01ca}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - {0xa0, 0x01, ZC3XX_R120_GAMMA00}, /* gamma 2 ?*/ - {0xa0, 0x0c, ZC3XX_R121_GAMMA01}, - {0xa0, 0x1f, ZC3XX_R122_GAMMA02}, - {0xa0, 0x3a, ZC3XX_R123_GAMMA03}, - {0xa0, 0x53, ZC3XX_R124_GAMMA04}, - {0xa0, 0x6d, ZC3XX_R125_GAMMA05}, - {0xa0, 0x85, ZC3XX_R126_GAMMA06}, - {0xa0, 0x9c, ZC3XX_R127_GAMMA07}, - {0xa0, 0xb0, ZC3XX_R128_GAMMA08}, - {0xa0, 0xc2, ZC3XX_R129_GAMMA09}, - {0xa0, 0xd1, ZC3XX_R12A_GAMMA0A}, - {0xa0, 0xde, ZC3XX_R12B_GAMMA0B}, - {0xa0, 0xe9, ZC3XX_R12C_GAMMA0C}, - {0xa0, 0xf2, ZC3XX_R12D_GAMMA0D}, - {0xa0, 0xf9, ZC3XX_R12E_GAMMA0E}, - {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, - {0xa0, 0x05, ZC3XX_R130_GAMMA10}, - {0xa0, 0x0f, ZC3XX_R131_GAMMA11}, - {0xa0, 0x16, ZC3XX_R132_GAMMA12}, - {0xa0, 0x1a, ZC3XX_R133_GAMMA13}, - {0xa0, 0x19, ZC3XX_R134_GAMMA14}, - {0xa0, 0x19, ZC3XX_R135_GAMMA15}, - {0xa0, 0x17, ZC3XX_R136_GAMMA16}, - {0xa0, 0x15, ZC3XX_R137_GAMMA17}, - {0xa0, 0x12, ZC3XX_R138_GAMMA18}, - {0xa0, 0x10, ZC3XX_R139_GAMMA19}, - {0xa0, 0x0e, ZC3XX_R13A_GAMMA1A}, - {0xa0, 0x0b, ZC3XX_R13B_GAMMA1B}, - {0xa0, 0x09, ZC3XX_R13C_GAMMA1C}, - {0xa0, 0x08, ZC3XX_R13D_GAMMA1D}, - {0xa0, 0x06, ZC3XX_R13E_GAMMA1E}, - {0xa0, 0x03, ZC3XX_R13F_GAMMA1F}, - {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf8, ZC3XX_R10B_RGB01}, - {0xa0, 0xf8, ZC3XX_R10C_RGB02}, - {0xa0, 0xf8, ZC3XX_R10D_RGB10}, - {0xa0, 0x50, ZC3XX_R10E_RGB11}, - {0xa0, 0xf8, ZC3XX_R10F_RGB12}, - {0xa0, 0xf8, ZC3XX_R110_RGB20}, - {0xa0, 0xf8, ZC3XX_R111_RGB21}, - {0xa0, 0x50, ZC3XX_R112_RGB22}, - - {0xa1, 0x01, 0x0180}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xaa, 0x10, 0x001b}, - {0xaa, 0x76, 0x0002}, - {0xaa, 0x2a, 0x0081}, - {0xaa, 0x2b, 0x0000}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x01, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xb8, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x37, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xaa, 0x13, 0x0083}, /* 40 */ - {0xa1, 0x01, 0x0180}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {} -}; - -static const struct usb_action ov7630c_Initial[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, - {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - - {0xaa, 0x12, 0x0080}, - {0xa0, 0x02, ZC3XX_R083_RGAINADDR}, - {0xa0, 0x01, ZC3XX_R085_BGAINADDR}, - {0xa0, 0x90, ZC3XX_R086_EXPTIMEHIGH}, - {0xa0, 0x91, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, - {0xaa, 0x12, 0x0069}, /* i2c */ - {0xaa, 0x04, 0x0020}, - {0xaa, 0x06, 0x0050}, - {0xaa, 0x13, 0x00c3}, - {0xaa, 0x14, 0x0000}, - {0xaa, 0x15, 0x0024}, - {0xaa, 0x19, 0x0003}, - {0xaa, 0x1a, 0x00f6}, - {0xaa, 0x1b, 0x0002}, - {0xaa, 0x20, 0x00c2}, - {0xaa, 0x24, 0x0060}, - {0xaa, 0x25, 0x0040}, - {0xaa, 0x26, 0x0030}, - {0xaa, 0x27, 0x00ea}, - {0xaa, 0x28, 0x00a0}, - {0xaa, 0x21, 0x0000}, - {0xaa, 0x2a, 0x0081}, - {0xaa, 0x2b, 0x0096}, - {0xaa, 0x2d, 0x0084}, - {0xaa, 0x2f, 0x003d}, - {0xaa, 0x30, 0x0024}, - {0xaa, 0x60, 0x0000}, - {0xaa, 0x61, 0x0040}, - {0xaa, 0x68, 0x007c}, - {0xaa, 0x6f, 0x0015}, - {0xaa, 0x75, 0x0088}, - {0xaa, 0x77, 0x00b5}, - {0xaa, 0x01, 0x0060}, - {0xaa, 0x02, 0x0060}, - {0xaa, 0x17, 0x0018}, - {0xaa, 0x18, 0x00ba}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN}, - {0xa0, 0x00, 0x01ad}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x60, ZC3XX_R116_RGAIN}, - {0xa0, 0x46, ZC3XX_R118_BGAIN}, - {0xa0, 0x04, ZC3XX_R113_RGB03}, - - {0xa1, 0x01, 0x0002}, - {0xa0, 0x4e, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xfe, ZC3XX_R10B_RGB01}, - {0xa0, 0xf4, ZC3XX_R10C_RGB02}, - {0xa0, 0xf7, ZC3XX_R10D_RGB10}, - {0xa0, 0x4d, ZC3XX_R10E_RGB11}, - {0xa0, 0xfc, ZC3XX_R10F_RGB12}, - {0xa0, 0x00, ZC3XX_R110_RGB20}, - {0xa0, 0xf6, ZC3XX_R111_RGB21}, - {0xa0, 0x4a, ZC3XX_R112_RGB22}, - - {0xa1, 0x01, 0x0008}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */ - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */ - {0xa1, 0x01, 0x01c8}, - {0xa1, 0x01, 0x01c9}, - {0xa1, 0x01, 0x01ca}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */ - {0xa0, 0x16, ZC3XX_R120_GAMMA00}, /* gamma ~4 */ - {0xa0, 0x3a, ZC3XX_R121_GAMMA01}, - {0xa0, 0x5b, ZC3XX_R122_GAMMA02}, - {0xa0, 0x7c, ZC3XX_R123_GAMMA03}, - {0xa0, 0x94, ZC3XX_R124_GAMMA04}, - {0xa0, 0xa9, ZC3XX_R125_GAMMA05}, - {0xa0, 0xbb, ZC3XX_R126_GAMMA06}, - {0xa0, 0xca, ZC3XX_R127_GAMMA07}, - {0xa0, 0xd7, ZC3XX_R128_GAMMA08}, - {0xa0, 0xe1, ZC3XX_R129_GAMMA09}, - {0xa0, 0xea, ZC3XX_R12A_GAMMA0A}, - {0xa0, 0xf1, ZC3XX_R12B_GAMMA0B}, - {0xa0, 0xf7, ZC3XX_R12C_GAMMA0C}, - {0xa0, 0xfc, ZC3XX_R12D_GAMMA0D}, - {0xa0, 0xff, ZC3XX_R12E_GAMMA0E}, - {0xa0, 0xff, ZC3XX_R12F_GAMMA0F}, - {0xa0, 0x20, ZC3XX_R130_GAMMA10}, - {0xa0, 0x22, ZC3XX_R131_GAMMA11}, - {0xa0, 0x20, ZC3XX_R132_GAMMA12}, - {0xa0, 0x1c, ZC3XX_R133_GAMMA13}, - {0xa0, 0x16, ZC3XX_R134_GAMMA14}, - {0xa0, 0x13, ZC3XX_R135_GAMMA15}, - {0xa0, 0x10, ZC3XX_R136_GAMMA16}, - {0xa0, 0x0d, ZC3XX_R137_GAMMA17}, - {0xa0, 0x0b, ZC3XX_R138_GAMMA18}, - {0xa0, 0x09, ZC3XX_R139_GAMMA19}, - {0xa0, 0x07, ZC3XX_R13A_GAMMA1A}, - {0xa0, 0x06, ZC3XX_R13B_GAMMA1B}, - {0xa0, 0x05, ZC3XX_R13C_GAMMA1C}, - {0xa0, 0x04, ZC3XX_R13D_GAMMA1D}, - {0xa0, 0x00, ZC3XX_R13E_GAMMA1E}, - {0xa0, 0x01, ZC3XX_R13F_GAMMA1F}, - {0xa0, 0x4e, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xfe, ZC3XX_R10B_RGB01}, - {0xa0, 0xf4, ZC3XX_R10C_RGB02}, - {0xa0, 0xf7, ZC3XX_R10D_RGB10}, - {0xa0, 0x4d, ZC3XX_R10E_RGB11}, - {0xa0, 0xfc, ZC3XX_R10F_RGB12}, - {0xa0, 0x00, ZC3XX_R110_RGB20}, - {0xa0, 0xf6, ZC3XX_R111_RGB21}, - {0xa0, 0x4a, ZC3XX_R112_RGB22}, - - {0xa1, 0x01, 0x0180}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xaa, 0x10, 0x000d}, - {0xaa, 0x76, 0x0002}, - {0xaa, 0x2a, 0x0081}, - {0xaa, 0x2b, 0x0000}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xd8, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x1b, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xaa, 0x13, 0x00c3}, - - {0xa1, 0x01, 0x0180}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {} -}; - -static const struct usb_action pas106b_Initial_com[] = { -/* Sream and Sensor specific */ - {0xa1, 0x01, 0x0010}, /* CMOSSensorSelect */ -/* System */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* SystemControl */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* SystemControl */ -/* Picture size */ - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* ClockSelect */ - {0xa0, 0x03, 0x003a}, - {0xa0, 0x0c, 0x003b}, - {0xa0, 0x04, 0x0038}, - {} -}; - -static const struct usb_action pas106b_InitialScale[] = { /* 176x144 */ -/* JPEG control */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, -/* Sream and Sensor specific */ - {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT}, -/* Picture size */ - {0xa0, 0x00, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0xb0, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x00, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0x90, ZC3XX_R006_FRAMEHEIGHTLOW}, -/* System */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, -/* Sream and Sensor specific */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, -/* Sensor Interface */ - {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, -/* Window inside sensor array */ - {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW}, -/* Init the sensor */ - {0xaa, 0x02, 0x0004}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x09, 0x0005}, - {0xaa, 0x0a, 0x0002}, - {0xaa, 0x0b, 0x0002}, - {0xaa, 0x0c, 0x0005}, - {0xaa, 0x0d, 0x0000}, - {0xaa, 0x0e, 0x0002}, - {0xaa, 0x14, 0x0081}, -/* Other registers */ - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, -/* Frame retreiving */ - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, -/* Gains */ - {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN}, -/* Unknown */ - {0xa0, 0x00, 0x01ad}, -/* Sharpness */ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, -/* Other registers */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, -/* Auto exposure and white balance */ - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, -/*Dead pixels */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, -/* EEPROM */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, -/* JPEG control */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, -/* Other registers */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, -/* Auto exposure and white balance */ - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, -/*Dead pixels */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, -/* EEPROM */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, -/* JPEG control */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, - - {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf4, ZC3XX_R10B_RGB01}, - {0xa0, 0xf4, ZC3XX_R10C_RGB02}, - {0xa0, 0xf4, ZC3XX_R10D_RGB10}, - {0xa0, 0x58, ZC3XX_R10E_RGB11}, - {0xa0, 0xf4, ZC3XX_R10F_RGB12}, - {0xa0, 0xf4, ZC3XX_R110_RGB20}, - {0xa0, 0xf4, ZC3XX_R111_RGB21}, - {0xa0, 0x58, ZC3XX_R112_RGB22}, -/* Auto correction */ - {0xa0, 0x03, ZC3XX_R181_WINXSTART}, - {0xa0, 0x08, ZC3XX_R182_WINXWIDTH}, - {0xa0, 0x16, ZC3XX_R183_WINXCENTER}, - {0xa0, 0x03, ZC3XX_R184_WINYSTART}, - {0xa0, 0x05, ZC3XX_R185_WINYWIDTH}, - {0xa0, 0x14, ZC3XX_R186_WINYCENTER}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, -/* Auto exposure and white balance */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, -/* sensor on */ - {0xaa, 0x07, 0x00b1}, - {0xaa, 0x05, 0x0003}, - {0xaa, 0x04, 0x0001}, - {0xaa, 0x03, 0x003b}, -/* Gains */ - {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, -/* Auto correction */ - {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0180}, /* AutoCorrectEnable */ - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, -/* Gains */ - {0xa0, 0x40, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x40, ZC3XX_R118_BGAIN}, - {} -}; - -static const struct usb_action pas106b_Initial[] = { /* 352x288 */ -/* JPEG control */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, -/* Sream and Sensor specific */ - {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT}, -/* Picture size */ - {0xa0, 0x01, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x60, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0x20, ZC3XX_R006_FRAMEHEIGHTLOW}, -/* System */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, -/* Sream and Sensor specific */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, -/* Sensor Interface */ - {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, -/* Window inside sensor array */ - {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW}, -/* Init the sensor */ - {0xaa, 0x02, 0x0004}, - {0xaa, 0x08, 0x0000}, - {0xaa, 0x09, 0x0005}, - {0xaa, 0x0a, 0x0002}, - {0xaa, 0x0b, 0x0002}, - {0xaa, 0x0c, 0x0005}, - {0xaa, 0x0d, 0x0000}, - {0xaa, 0x0e, 0x0002}, - {0xaa, 0x14, 0x0081}, -/* Other registers */ - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, -/* Frame retreiving */ - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, -/* Gains */ - {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN}, -/* Unknown */ - {0xa0, 0x00, 0x01ad}, -/* Sharpness */ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, -/* Other registers */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, -/* Auto exposure and white balance */ - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x80, ZC3XX_R18D_YTARGET}, -/*Dead pixels */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, -/* EEPROM */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, -/* JPEG control */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, -/* Other registers */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, -/* Auto exposure and white balance */ - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, -/*Dead pixels */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, -/* EEPROM */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, -/* JPEG control */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, - {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, - - {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */ - {0xa0, 0xf4, ZC3XX_R10B_RGB01}, - {0xa0, 0xf4, ZC3XX_R10C_RGB02}, - {0xa0, 0xf4, ZC3XX_R10D_RGB10}, - {0xa0, 0x58, ZC3XX_R10E_RGB11}, - {0xa0, 0xf4, ZC3XX_R10F_RGB12}, - {0xa0, 0xf4, ZC3XX_R110_RGB20}, - {0xa0, 0xf4, ZC3XX_R111_RGB21}, - {0xa0, 0x58, ZC3XX_R112_RGB22}, -/* Auto correction */ - {0xa0, 0x03, ZC3XX_R181_WINXSTART}, - {0xa0, 0x08, ZC3XX_R182_WINXWIDTH}, - {0xa0, 0x16, ZC3XX_R183_WINXCENTER}, - {0xa0, 0x03, ZC3XX_R184_WINYSTART}, - {0xa0, 0x05, ZC3XX_R185_WINYWIDTH}, - {0xa0, 0x14, ZC3XX_R186_WINYCENTER}, - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - -/* Auto exposure and white balance */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW}, - - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW}, - - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, -/* sensor on */ - {0xaa, 0x07, 0x00b1}, - {0xaa, 0x05, 0x0003}, - {0xaa, 0x04, 0x0001}, - {0xaa, 0x03, 0x003b}, -/* Gains */ - {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, -/* Auto correction */ - {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa1, 0x01, 0x0180}, /* AutoCorrectEnable */ - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, -/* Gains */ - {0xa0, 0x40, ZC3XX_R116_RGAIN}, - {0xa0, 0x40, ZC3XX_R117_GGAIN}, - {0xa0, 0x40, ZC3XX_R118_BGAIN}, - - {0xa0, 0x00, 0x0007}, /* AutoCorrectEnable */ - {0xa0, 0xff, ZC3XX_R018_FRAMELOST}, /* Frame adjust */ - {} -}; -static const struct usb_action pas106b_50HZ[] = { - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */ - {0xa0, 0x54, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,54,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,87,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x30, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,30,cc */ - {0xaa, 0x03, 0x0021}, /* 00,03,21,aa */ - {0xaa, 0x04, 0x000c}, /* 00,04,0c,aa */ - {0xaa, 0x05, 0x0002}, /* 00,05,02,aa */ - {0xaa, 0x07, 0x001c}, /* 00,07,1c,aa */ - {0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */ - {} -}; -static const struct usb_action pas106b_60HZ[] = { - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */ - {0xa0, 0x2e, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,2e,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x71, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,71,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x30, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,30,cc */ - {0xaa, 0x03, 0x001c}, /* 00,03,1c,aa */ - {0xaa, 0x04, 0x0004}, /* 00,04,04,aa */ - {0xaa, 0x05, 0x0001}, /* 00,05,01,aa */ - {0xaa, 0x07, 0x00c4}, /* 00,07,c4,aa */ - {0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */ - {} -}; -static const struct usb_action pas106b_NoFliker[] = { - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */ - {0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xaa, 0x03, 0x0013}, /* 00,03,13,aa */ - {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */ - {0xaa, 0x05, 0x0001}, /* 00,05,01,aa */ - {0xaa, 0x07, 0x0030}, /* 00,07,30,aa */ - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ - {} -}; - -/* from lvWIMv.inf 046d:08a2/:08aa 2007/06/03 */ -static const struct usb_action pas202b_Initial[] = { /* 640x480 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */ - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */ - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ - {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */ - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */ - {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,03,cc */ - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */ - {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,03,cc */ - {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */ - {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc */ - {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */ - {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */ - {0xaa, 0x02, 0x0002}, /* 00,02,04,aa --> 02 */ - {0xaa, 0x07, 0x0006}, /* 00,07,06,aa */ - {0xaa, 0x08, 0x0002}, /* 00,08,02,aa */ - {0xaa, 0x09, 0x0006}, /* 00,09,06,aa */ - {0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */ - {0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */ - {0xaa, 0x0c, 0x0006}, - {0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */ - {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ - {0xaa, 0x12, 0x0005}, /* 00,12,05,aa */ - {0xaa, 0x13, 0x0063}, /* 00,13,63,aa */ - {0xaa, 0x15, 0x0070}, /* 00,15,70,aa */ - {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */ - {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ - {0xa0, 0x70, ZC3XX_R18D_YTARGET}, /* 01,8d,70,cc */ - {} -}; -static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */ - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ - {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */ - {0xa0, 0x08, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,08,cc */ - {0xa0, 0x02, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,02,cc */ - {0xa0, 0x08, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,08,cc */ - {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,02,cc */ - {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */ - {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */ - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */ - {0xaa, 0x02, 0x0002}, /* 00,02,02,aa */ - {0xaa, 0x07, 0x0006}, /* 00,07,06,aa */ - {0xaa, 0x08, 0x0002}, /* 00,08,02,aa */ - {0xaa, 0x09, 0x0006}, /* 00,09,06,aa */ - {0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */ - {0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */ - {0xaa, 0x0c, 0x0006}, - {0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */ - {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ - {0xaa, 0x12, 0x0005}, /* 00,12,05,aa */ - {0xaa, 0x13, 0x0063}, /* 00,13,63,aa */ - {0xaa, 0x15, 0x0070}, /* 00,15,70,aa */ - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */ - {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ - {0xa0, 0x70, ZC3XX_R18D_YTARGET}, /* 01,8d,70,cc */ - {0xa0, 0xff, ZC3XX_R097_WINYSTARTHIGH}, - {0xa0, 0xfe, ZC3XX_R098_WINYSTARTLOW}, - {} -}; -static const struct usb_action pas202b_50HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ - {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ - {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ - {0xaa, 0x21, 0x001b}, - {0xaa, 0x03, 0x0044}, /* 00,03,44,aa */ - {0xaa, 0x04, 0x0008}, - {0xaa, 0x05, 0x001b}, - {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ - {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ - {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x1b, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x4d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,4d,cc */ - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x44, ZC3XX_R01D_HSYNC_0}, /* 00,1d,44,cc */ - {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ - {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */ - {0xa0, 0xeb, ZC3XX_R020_HSYNC_3}, /* 00,20,eb,cc */ - {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */ - {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */ - {} -}; -static const struct usb_action pas202b_50HZScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ - {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ - {0xaa, 0x20, 0x0004}, - {0xaa, 0x21, 0x003d}, - {0xaa, 0x03, 0x0041}, /* 00,03,41,aa */ - {0xaa, 0x04, 0x0010}, - {0xaa, 0x05, 0x003d}, - {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ - {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ - {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x3d, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x9b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,9b,cc */ - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x41, ZC3XX_R01D_HSYNC_0}, /* 00,1d,41,cc */ - {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ - {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */ - {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */ - {} -}; -static const struct usb_action pas202b_60HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ - {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ - {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ - {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */ - {0xaa, 0x03, 0x0045}, /* 00,03,45,aa */ - {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */ - {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */ - {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ - {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ - {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x40, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,40,cc */ - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x45, ZC3XX_R01D_HSYNC_0}, /* 00,1d,45,cc */ - {0xa0, 0x8e, ZC3XX_R01E_HSYNC_1}, /* 00,1e,8e,cc */ - {0xa0, 0xc1, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c1,cc */ - {0xa0, 0xf5, ZC3XX_R020_HSYNC_3}, /* 00,20,f5,cc */ - {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */ - {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */ - {} -}; -static const struct usb_action pas202b_60HZScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ - {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ - {0xaa, 0x20, 0x0004}, - {0xaa, 0x21, 0x0008}, - {0xaa, 0x03, 0x0042}, /* 00,03,42,aa */ - {0xaa, 0x04, 0x0010}, - {0xaa, 0x05, 0x0008}, - {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ - {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ - {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x08, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,81,cc */ - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x42, ZC3XX_R01D_HSYNC_0}, /* 00,1d,42,cc */ - {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ - {0xa0, 0xaf, ZC3XX_R01F_HSYNC_2}, /* 00,1f,af,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */ - {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */ - {} -}; -static const struct usb_action pas202b_NoFliker[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ - {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ - {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ - {0xaa, 0x21, 0x0006}, - {0xaa, 0x03, 0x0040}, /* 00,03,40,aa */ - {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */ - {0xaa, 0x05, 0x0006}, - {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ - {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x06, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */ - {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */ - {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */ - {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */ - {} -}; -static const struct usb_action pas202b_NoFlikerScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ - {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ - {0xaa, 0x20, 0x0004}, - {0xaa, 0x21, 0x000c}, - {0xaa, 0x03, 0x0040}, /* 00,03,40,aa */ - {0xaa, 0x04, 0x0010}, - {0xaa, 0x05, 0x000c}, - {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ - {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x0c, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x02, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,02,cc */ - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */ - {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */ - {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID}, /* 00,87,0f,cc */ - {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */ - {} -}; - -/* mt9v111 (mi0360soc) and pb0330 from vm30x.inf 0ac8:301b 07/02/13 */ -static const struct usb_action mt9v111_1_Initial[] = { /* 640x480 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, - {0xdd, 0x00, 0x0200}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xaa, 0x01, 0x0001}, - {0xaa, 0x06, 0x0000}, - {0xaa, 0x08, 0x0483}, - {0xaa, 0x01, 0x0004}, - {0xaa, 0x08, 0x0006}, - {0xaa, 0x02, 0x0011}, - {0xaa, 0x03, 0x01e5}, /*jfm: was 01e7*/ - {0xaa, 0x04, 0x0285}, /*jfm: was 0287*/ - {0xaa, 0x07, 0x3002}, - {0xaa, 0x20, 0x5100}, - {0xaa, 0x35, 0x507f}, - {0xaa, 0x30, 0x0005}, - {0xaa, 0x31, 0x0000}, - {0xaa, 0x58, 0x0078}, - {0xaa, 0x62, 0x0411}, - {0xaa, 0x2b, 0x007f}, - {0xaa, 0x2c, 0x007f}, /*jfm: was 0030*/ - {0xaa, 0x2d, 0x007f}, /*jfm: was 0030*/ - {0xaa, 0x2e, 0x007f}, /*jfm: was 0030*/ - {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x09, 0x01ad}, /*jfm: was 00*/ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x6c, ZC3XX_R18D_YTARGET}, - {0xa0, 0x61, ZC3XX_R116_RGAIN}, - {0xa0, 0x65, ZC3XX_R118_BGAIN}, - {} -}; -static const struct usb_action mt9v111_1_InitialScale[] = { /* 320x240 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, - {0xdd, 0x00, 0x0200}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xaa, 0x01, 0x0001}, - {0xaa, 0x06, 0x0000}, - {0xaa, 0x08, 0x0483}, - {0xaa, 0x01, 0x0004}, - {0xaa, 0x08, 0x0006}, - {0xaa, 0x02, 0x0011}, - {0xaa, 0x03, 0x01e7}, - {0xaa, 0x04, 0x0287}, - {0xaa, 0x07, 0x3002}, - {0xaa, 0x20, 0x5100}, - {0xaa, 0x35, 0x007f}, /*jfm: was 0050*/ - {0xaa, 0x30, 0x0005}, - {0xaa, 0x31, 0x0000}, - {0xaa, 0x58, 0x0078}, - {0xaa, 0x62, 0x0411}, - {0xaa, 0x2b, 0x007f}, /*jfm: was 28*/ - {0xaa, 0x2c, 0x007f}, /*jfm: was 30*/ - {0xaa, 0x2d, 0x007f}, /*jfm: was 30*/ - {0xaa, 0x2e, 0x007f}, /*jfm: was 28*/ - {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x09, 0x01ad}, /*jfm: was 00*/ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x6c, ZC3XX_R18D_YTARGET}, - {0xa0, 0x61, ZC3XX_R116_RGAIN}, - {0xa0, 0x65, ZC3XX_R118_BGAIN}, - {} -}; -static const struct usb_action mt9v111_1_AE50HZ[] = { - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xbb, 0x00, 0x0562}, - {0xbb, 0x01, 0x09aa}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x9b, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {} -}; -static const struct usb_action mt9v111_1_AE50HZScale[] = { - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xbb, 0x00, 0x0509}, - {0xbb, 0x01, 0x0934}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {} -}; -static const struct usb_action mt9v111_1_AE60HZ[] = { - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x05, 0x003d}, - {0xaa, 0x09, 0x016e}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xdd, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {} -}; -static const struct usb_action mt9v111_1_AE60HZScale[] = { - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xbb, 0x00, 0x0509}, - {0xbb, 0x01, 0x0983}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {} -}; -static const struct usb_action mt9v111_1_AENoFliker[] = { - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xbb, 0x00, 0x0509}, - {0xbb, 0x01, 0x0960}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x09, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xe0, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {} -}; -static const struct usb_action mt9v111_1_AENoFlikerScale[] = { - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xbb, 0x00, 0x0534}, - {0xbb, 0x02, 0x0960}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x34, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xe0, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {} -}; -/* from usbvm303.inf 0ac8:303b 07/03/25 (3 - tas5130c) */ -static const struct usb_action mt9v111_3_Initial[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, - {0xdd, 0x00, 0x0200}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xaa, 0x01, 0x0001}, /* select IFP/SOC registers */ - {0xaa, 0x06, 0x0000}, /* operating mode control */ - {0xaa, 0x08, 0x0483}, /* output format control */ - /* H red first, V red or blue first, - * raw Bayer, auto flicker */ - {0xaa, 0x01, 0x0004}, /* select sensor core registers */ - {0xaa, 0x08, 0x0006}, /* row start */ - {0xaa, 0x02, 0x0011}, /* column start */ - {0xaa, 0x03, 0x01e5}, /* window height - 1 */ - {0xaa, 0x04, 0x0285}, /* window width - 1 */ - {0xaa, 0x07, 0x3002}, /* output control */ - {0xaa, 0x20, 0x1100}, /* read mode: bits 8 & 12 (?) */ - {0xaa, 0x35, 0x007f}, /* global gain */ - {0xaa, 0x30, 0x0005}, - {0xaa, 0x31, 0x0000}, - {0xaa, 0x58, 0x0078}, - {0xaa, 0x62, 0x0411}, - {0xaa, 0x2b, 0x007f}, /* green1 gain */ - {0xaa, 0x2c, 0x007f}, /* blue gain */ - {0xaa, 0x2d, 0x007f}, /* red gain */ - {0xaa, 0x2e, 0x007f}, /* green2 gain */ - {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x00, 0x01ad}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x80, ZC3XX_R18D_YTARGET}, - {0xa0, 0x61, ZC3XX_R116_RGAIN}, - {0xa0, 0x65, ZC3XX_R118_BGAIN}, - {} -}; -static const struct usb_action mt9v111_3_InitialScale[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, - {0xdd, 0x00, 0x0200}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xaa, 0x01, 0x0001}, - {0xaa, 0x06, 0x0000}, - {0xaa, 0x08, 0x0483}, - {0xaa, 0x01, 0x0004}, - {0xaa, 0x08, 0x0006}, - {0xaa, 0x02, 0x0011}, - {0xaa, 0x03, 0x01e7}, - {0xaa, 0x04, 0x0287}, - {0xaa, 0x07, 0x3002}, - {0xaa, 0x20, 0x1100}, - {0xaa, 0x35, 0x007f}, - {0xaa, 0x30, 0x0005}, - {0xaa, 0x31, 0x0000}, - {0xaa, 0x58, 0x0078}, - {0xaa, 0x62, 0x0411}, - {0xaa, 0x2b, 0x007f}, - {0xaa, 0x2c, 0x007f}, - {0xaa, 0x2d, 0x007f}, - {0xaa, 0x2e, 0x007f}, - {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x00, 0x01ad}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x80, ZC3XX_R18D_YTARGET}, - {0xa0, 0x61, ZC3XX_R116_RGAIN}, - {0xa0, 0x65, ZC3XX_R118_BGAIN}, - {} -}; -static const struct usb_action mt9v111_3_AE50HZ[] = { - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x05, 0x0009}, /* horizontal blanking */ - {0xaa, 0x09, 0x01ce}, /* shutter width */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {} -}; -static const struct usb_action mt9v111_3_AE50HZScale[] = { - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x05, 0x0009}, - {0xaa, 0x09, 0x01ce}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {} -}; -static const struct usb_action mt9v111_3_AE60HZ[] = { - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x05, 0x0009}, - {0xaa, 0x09, 0x0083}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {} -}; -static const struct usb_action mt9v111_3_AE60HZScale[] = { - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x05, 0x0009}, - {0xaa, 0x09, 0x0083}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {} -}; -static const struct usb_action mt9v111_3_AENoFliker[] = { - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x05, 0x0034}, - {0xaa, 0x09, 0x0260}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x34, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xe0, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {} -}; -static const struct usb_action mt9v111_3_AENoFlikerScale[] = { - {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xaa, 0x05, 0x0034}, - {0xaa, 0x09, 0x0260}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x34, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xe0, ZC3XX_R020_HSYNC_3}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, - {} -}; - -static const struct usb_action pb0330_Initial[] = { /* 640x480 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xdd, 0x00, 0x0200}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xaa, 0x01, 0x0006}, - {0xaa, 0x02, 0x0011}, - {0xaa, 0x03, 0x01e5}, /*jfm: was 1e7*/ - {0xaa, 0x04, 0x0285}, /*jfm: was 0287*/ - {0xaa, 0x06, 0x0003}, - {0xaa, 0x07, 0x3002}, - {0xaa, 0x20, 0x1100}, - {0xaa, 0x2f, 0xf7b0}, - {0xaa, 0x30, 0x0005}, - {0xaa, 0x31, 0x0000}, - {0xaa, 0x34, 0x0100}, - {0xaa, 0x35, 0x0060}, - {0xaa, 0x3d, 0x068f}, - {0xaa, 0x40, 0x01e0}, - {0xaa, 0x58, 0x0078}, - {0xaa, 0x62, 0x0411}, - {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x09, 0x01ad}, /*jfm: was 00 */ - {0xa0, 0x15, 0x01ae}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /*jfm: was 6c*/ - {} -}; -static const struct usb_action pb0330_InitialScale[] = { /* 320x240 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */ - {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, - {0xdd, 0x00, 0x0200}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xaa, 0x01, 0x0006}, - {0xaa, 0x02, 0x0011}, - {0xaa, 0x03, 0x01e7}, - {0xaa, 0x04, 0x0287}, - {0xaa, 0x06, 0x0003}, - {0xaa, 0x07, 0x3002}, - {0xaa, 0x20, 0x1100}, - {0xaa, 0x2f, 0xf7b0}, - {0xaa, 0x30, 0x0005}, - {0xaa, 0x31, 0x0000}, - {0xaa, 0x34, 0x0100}, - {0xaa, 0x35, 0x0060}, - {0xaa, 0x3d, 0x068f}, - {0xaa, 0x40, 0x01e0}, - {0xaa, 0x58, 0x0078}, - {0xaa, 0x62, 0x0411}, - {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x09, 0x01ad}, - {0xa0, 0x15, 0x01ae}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /*jfm: was 6c*/ - {} -}; -static const struct usb_action pb0330_50HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xbb, 0x00, 0x055c}, - {0xbb, 0x01, 0x09aa}, - {0xbb, 0x00, 0x1001}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xc4, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x5c, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {} -}; -static const struct usb_action pb0330_50HZScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xbb, 0x00, 0x0566}, - {0xbb, 0x02, 0x09b2}, - {0xbb, 0x00, 0x1002}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x8c, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x8a, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, - {} -}; -static const struct usb_action pb0330_60HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xbb, 0x00, 0x0535}, - {0xbb, 0x01, 0x0974}, - {0xbb, 0x00, 0x1001}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xfe, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x35, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xd0, ZC3XX_R020_HSYNC_3}, - {} -}; -static const struct usb_action pb0330_60HZScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xbb, 0x00, 0x0535}, - {0xbb, 0x02, 0x096c}, - {0xbb, 0x00, 0x1002}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xc0, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x7c, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x35, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xd0, ZC3XX_R020_HSYNC_3}, - {} -}; -static const struct usb_action pb0330_NoFliker[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xbb, 0x00, 0x0509}, - {0xbb, 0x02, 0x0940}, - {0xbb, 0x00, 0x1002}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x09, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xe0, ZC3XX_R020_HSYNC_3}, - {} -}; -static const struct usb_action pb0330_NoFlikerScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, - {0xbb, 0x00, 0x0535}, - {0xbb, 0x01, 0x0980}, - {0xbb, 0x00, 0x1001}, - {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x35, ZC3XX_R01D_HSYNC_0}, - {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, - {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, - {0xa0, 0xe0, ZC3XX_R020_HSYNC_3}, - {} -}; - -/* from oem9.inf */ -static const struct usb_action po2030_Initial[] = { /* 640x480 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ - {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ - {0xa0, 0x04, ZC3XX_R080_HBLANKHIGH}, /* 00,80,04,cc */ - {0xa0, 0x05, ZC3XX_R081_HBLANKLOW}, /* 00,81,05,cc */ - {0xa0, 0x16, ZC3XX_R083_RGAINADDR}, /* 00,83,16,cc */ - {0xa0, 0x18, ZC3XX_R085_BGAINADDR}, /* 00,85,18,cc */ - {0xa0, 0x1a, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,1a,cc */ - {0xa0, 0x1b, ZC3XX_R087_EXPTIMEMID}, /* 00,87,1b,cc */ - {0xa0, 0x1c, ZC3XX_R088_EXPTIMELOW}, /* 00,88,1c,cc */ - {0xa0, 0xee, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,ee,cc */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */ - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */ - {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */ - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */ - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */ - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */ - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */ - {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc */ - {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */ - {0xaa, 0x09, 0x00ce}, /* 00,09,ce,aa */ - {0xaa, 0x0b, 0x0005}, /* 00,0b,05,aa */ - {0xaa, 0x0d, 0x0054}, /* 00,0d,54,aa */ - {0xaa, 0x0f, 0x00eb}, /* 00,0f,eb,aa */ - {0xaa, 0x87, 0x0000}, /* 00,87,00,aa */ - {0xaa, 0x88, 0x0004}, /* 00,88,04,aa */ - {0xaa, 0x89, 0x0000}, /* 00,89,00,aa */ - {0xaa, 0x8a, 0x0005}, /* 00,8a,05,aa */ - {0xaa, 0x13, 0x0003}, /* 00,13,03,aa */ - {0xaa, 0x16, 0x0040}, /* 00,16,40,aa */ - {0xaa, 0x18, 0x0040}, /* 00,18,40,aa */ - {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */ - {0xaa, 0x29, 0x00e8}, /* 00,29,e8,aa */ - {0xaa, 0x45, 0x0045}, /* 00,45,45,aa */ - {0xaa, 0x50, 0x00ed}, /* 00,50,ed,aa */ - {0xaa, 0x51, 0x0025}, /* 00,51,25,aa */ - {0xaa, 0x52, 0x0042}, /* 00,52,42,aa */ - {0xaa, 0x53, 0x002f}, /* 00,53,2f,aa */ - {0xaa, 0x79, 0x0025}, /* 00,79,25,aa */ - {0xaa, 0x7b, 0x0000}, /* 00,7b,00,aa */ - {0xaa, 0x7e, 0x0025}, /* 00,7e,25,aa */ - {0xaa, 0x7f, 0x0025}, /* 00,7f,25,aa */ - {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */ - {0xaa, 0x33, 0x0036}, /* 00,33,36,aa */ - {0xaa, 0x36, 0x0060}, /* 00,36,60,aa */ - {0xaa, 0x37, 0x0008}, /* 00,37,08,aa */ - {0xaa, 0x3b, 0x0031}, /* 00,3b,31,aa */ - {0xaa, 0x44, 0x000f}, /* 00,44,0f,aa */ - {0xaa, 0x58, 0x0002}, /* 00,58,02,aa */ - {0xaa, 0x66, 0x00c0}, /* 00,66,c0,aa */ - {0xaa, 0x67, 0x0044}, /* 00,67,44,aa */ - {0xaa, 0x6b, 0x00a0}, /* 00,6b,a0,aa */ - {0xaa, 0x6c, 0x0054}, /* 00,6c,54,aa */ - {0xaa, 0xd6, 0x0007}, /* 00,d6,07,aa */ - {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,f7,cc */ - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */ - {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ - {0xa0, 0x7a, ZC3XX_R116_RGAIN}, /* 01,16,7a,cc */ - {0xa0, 0x4a, ZC3XX_R118_BGAIN}, /* 01,18,4a,cc */ - {} -}; - -/* from oem9.inf */ -static const struct usb_action po2030_InitialScale[] = { /* 320x240 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ - {0xa0, 0x04, ZC3XX_R080_HBLANKHIGH}, /* 00,80,04,cc */ - {0xa0, 0x05, ZC3XX_R081_HBLANKLOW}, /* 00,81,05,cc */ - {0xa0, 0x16, ZC3XX_R083_RGAINADDR}, /* 00,83,16,cc */ - {0xa0, 0x18, ZC3XX_R085_BGAINADDR}, /* 00,85,18,cc */ - {0xa0, 0x1a, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,1a,cc */ - {0xa0, 0x1b, ZC3XX_R087_EXPTIMEMID}, /* 00,87,1b,cc */ - {0xa0, 0x1c, ZC3XX_R088_EXPTIMELOW}, /* 00,88,1c,cc */ - {0xa0, 0xee, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,ee,cc */ - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */ - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */ - {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */ - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */ - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */ - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */ - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */ - {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc */ - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */ - {0xaa, 0x09, 0x00cc}, /* 00,09,cc,aa */ - {0xaa, 0x0b, 0x0005}, /* 00,0b,05,aa */ - {0xaa, 0x0d, 0x0058}, /* 00,0d,58,aa */ - {0xaa, 0x0f, 0x00ed}, /* 00,0f,ed,aa */ - {0xaa, 0x87, 0x0000}, /* 00,87,00,aa */ - {0xaa, 0x88, 0x0004}, /* 00,88,04,aa */ - {0xaa, 0x89, 0x0000}, /* 00,89,00,aa */ - {0xaa, 0x8a, 0x0005}, /* 00,8a,05,aa */ - {0xaa, 0x13, 0x0003}, /* 00,13,03,aa */ - {0xaa, 0x16, 0x0040}, /* 00,16,40,aa */ - {0xaa, 0x18, 0x0040}, /* 00,18,40,aa */ - {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */ - {0xaa, 0x29, 0x00e8}, /* 00,29,e8,aa */ - {0xaa, 0x45, 0x0045}, /* 00,45,45,aa */ - {0xaa, 0x50, 0x00ed}, /* 00,50,ed,aa */ - {0xaa, 0x51, 0x0025}, /* 00,51,25,aa */ - {0xaa, 0x52, 0x0042}, /* 00,52,42,aa */ - {0xaa, 0x53, 0x002f}, /* 00,53,2f,aa */ - {0xaa, 0x79, 0x0025}, /* 00,79,25,aa */ - {0xaa, 0x7b, 0x0000}, /* 00,7b,00,aa */ - {0xaa, 0x7e, 0x0025}, /* 00,7e,25,aa */ - {0xaa, 0x7f, 0x0025}, /* 00,7f,25,aa */ - {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */ - {0xaa, 0x33, 0x0036}, /* 00,33,36,aa */ - {0xaa, 0x36, 0x0060}, /* 00,36,60,aa */ - {0xaa, 0x37, 0x0008}, /* 00,37,08,aa */ - {0xaa, 0x3b, 0x0031}, /* 00,3b,31,aa */ - {0xaa, 0x44, 0x000f}, /* 00,44,0f,aa */ - {0xaa, 0x58, 0x0002}, /* 00,58,02,aa */ - {0xaa, 0x66, 0x00c0}, /* 00,66,c0,aa */ - {0xaa, 0x67, 0x0044}, /* 00,67,44,aa */ - {0xaa, 0x6b, 0x00a0}, /* 00,6b,a0,aa */ - {0xaa, 0x6c, 0x0054}, /* 00,6c,54,aa */ - {0xaa, 0xd6, 0x0007}, /* 00,d6,07,aa */ - {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,f7,cc */ - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */ - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */ - {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */ - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ - {0xa0, 0x7a, ZC3XX_R116_RGAIN}, /* 01,16,7a,cc */ - {0xa0, 0x4a, ZC3XX_R118_BGAIN}, /* 01,18,4a,cc */ - {} -}; - -static const struct usb_action po2030_50HZ[] = { - {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */ - {0xaa, 0x1a, 0x0001}, /* 00,1a,01,aa */ - {0xaa, 0x1b, 0x000a}, /* 00,1b,0a,aa */ - {0xaa, 0x1c, 0x00b0}, /* 00,1c,b0,aa */ - {0xa0, 0x05, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,05,cc */ - {0xa0, 0x35, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,35,cc */ - {0xa0, 0x70, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,70,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x85, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,85,cc */ - {0xa0, 0x58, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,58,cc */ - {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */ - {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */ - {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */ - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */ - {0xa0, 0x22, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,22,cc */ - {0xa0, 0x88, ZC3XX_R18D_YTARGET}, /* 01,8d,88,cc */ - {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc */ - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */ - {} -}; - -static const struct usb_action po2030_60HZ[] = { - {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */ - {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */ - {0xaa, 0x1b, 0x00de}, /* 00,1b,de,aa */ - {0xaa, 0x1c, 0x0040}, /* 00,1c,40,aa */ - {0xa0, 0x08, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,08,cc */ - {0xa0, 0xae, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,ae,cc */ - {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,80,cc */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x6f, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,6f,cc */ - {0xa0, 0x20, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,20,cc */ - {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */ - {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */ - {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */ - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */ - {0xa0, 0x22, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,22,cc */ - {0xa0, 0x88, ZC3XX_R18D_YTARGET}, /* 01,8d,88,cc */ - /* win: 01,8d,80 */ - {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc */ - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */ - {} -}; - -static const struct usb_action po2030_NoFliker[] = { - {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */ - {0xaa, 0x8d, 0x000d}, /* 00,8d,0d,aa */ - {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */ - {0xaa, 0x1b, 0x0002}, /* 00,1b,02,aa */ - {0xaa, 0x1c, 0x0078}, /* 00,1c,78,aa */ - {0xaa, 0x46, 0x0000}, /* 00,46,00,aa */ - {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */ - {} -}; - -static const struct usb_action tas5130c_InitialScale[] = { /* 320x240 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - - {0xa0, 0x04, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x0f, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x04, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x0f, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, - {0xa0, 0x06, ZC3XX_R08D_COMPABILITYMODE}, - {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x70, ZC3XX_R18D_YTARGET}, - {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x00, 0x01ad}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN}, - {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL}, - {} -}; -static const struct usb_action tas5130c_Initial[] = { /* 640x480 */ - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, - {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, - {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x05, ZC3XX_R098_WINYSTARTLOW}, - {0xa0, 0x0f, ZC3XX_R09A_WINXSTARTLOW}, - {0xa0, 0x05, ZC3XX_R11A_FIRSTYLOW}, - {0xa0, 0x0f, ZC3XX_R11C_FIRSTXLOW}, - {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, - {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, - {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, - {0xa0, 0x06, ZC3XX_R08D_COMPABILITYMODE}, - {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, - {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, - {0xa0, 0x70, ZC3XX_R18D_YTARGET}, - {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x00, 0x01ad}, - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN}, - {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL}, - {} -}; -static const struct usb_action tas5130c_50HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */ - {0xaa, 0xa4, 0x0063}, /* 00,a4,63,aa */ - {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ - {0xa0, 0x63, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,63,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xfe, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc */ - {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xd3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,d3,cc */ - {0xa0, 0xda, ZC3XX_R01E_HSYNC_1}, /* 00,1e,da,cc */ - {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */ - {0xa0, 0x4c, ZC3XX_R0A0_MAXXLOW}, - {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, - {} -}; -static const struct usb_action tas5130c_50HZScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */ - {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */ - {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ - {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xd0, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */ - {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xf0, ZC3XX_R01D_HSYNC_0}, /* 00,1d,f0,cc */ - {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,f4,cc */ - {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f8,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */ - {0xa0, 0xc0, ZC3XX_R0A0_MAXXLOW}, - {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, - {} -}; -static const struct usb_action tas5130c_60HZ[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */ - {0xaa, 0xa4, 0x0036}, /* 00,a4,36,aa */ - {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ - {0xa0, 0x36, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,36,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x54, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3e,cc */ - {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xca, ZC3XX_R01D_HSYNC_0}, /* 00,1d,ca,cc */ - {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */ - {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */ - {0xa0, 0x28, ZC3XX_R0A0_MAXXLOW}, - {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, - {} -}; -static const struct usb_action tas5130c_60HZScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */ - {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */ - {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ - {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x09, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x47, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ - {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */ - {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */ - {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */ - {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */ - {0xa0, 0x20, ZC3XX_R0A0_MAXXLOW}, - {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, - {} -}; -static const struct usb_action tas5130c_NoFliker[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */ - {0xaa, 0xa4, 0x0040}, /* 00,a4,40,aa */ - {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ - {0xa0, 0x40, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,40,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ - {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */ - {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */ - {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */ - {0xa0, 0xf0, ZC3XX_R0A0_MAXXLOW}, - {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, - {} -}; - -static const struct usb_action tas5130c_NoFlikerScale[] = { - {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ - {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */ - {0xaa, 0xa4, 0x0090}, /* 00,a4,90,aa */ - {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */ - {0xa0, 0x90, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,90,cc */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ - {0xa0, 0x0a, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, - {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW}, - {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, - {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, - {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ - {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ - {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */ - {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */ - {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ - {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */ - {0xa0, 0xf0, ZC3XX_R0A0_MAXXLOW}, - {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, - {} -}; - -/* from usbvm305.inf 0ac8:305b 07/06/15 (3 - tas5130c) */ -static const struct usb_action gc0303_Initial[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ - {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ - {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc, */ - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc, */ - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc, */ - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc, */ - {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc, */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc, */ - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc, */ - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc, */ - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc, */ - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc, */ - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc, */ - {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc, - * 6<->8 */ - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc, - * 6<->8 */ - {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, /* 00,87,10,cc, */ - {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */ - {0xaa, 0x01, 0x0000}, - {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */ - {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */ - {0xaa, 0x1b, 0x0000}, - {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc, */ - {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc, */ - {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc, */ - {0xaa, 0x05, 0x0010}, /* 00,05,10,aa, */ - {0xaa, 0x0a, 0x0002}, - {0xaa, 0x0b, 0x0000}, - {0xaa, 0x0c, 0x0002}, - {0xaa, 0x0d, 0x0000}, - {0xaa, 0x0e, 0x0002}, - {0xaa, 0x0f, 0x0000}, - {0xaa, 0x10, 0x0002}, - {0xaa, 0x11, 0x0000}, - {0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */ - {0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa, (e6 -> e8) */ - {0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */ - {0xaa, 0x19, 0x0088}, /* 00,19,86,aa, */ - {0xaa, 0x20, 0x0020}, /* 00,20,20,aa, */ - {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc, */ - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc, */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc, */ - {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc, */ - {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc, */ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc, */ - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc, */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc, */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc, */ - {0xa0, 0x58, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x61, ZC3XX_R116_RGAIN}, /* 01,16,61,cc, */ - {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */ - {0xaa, 0x1b, 0x0000}, - {} -}; - -static const struct usb_action gc0303_InitialScale[] = { - {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ - {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ - {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ - {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, - {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc, */ - {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc, */ - {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc, */ - {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc, */ - {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */ - {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc, */ - {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc, */ - {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc, */ - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc, */ - {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc, */ - {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc, */ - {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc, */ - {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc, - * 8<->6 */ - {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc, - * 8<->6 */ - {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, /* 00,87,10,cc, */ - {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */ - {0xaa, 0x01, 0x0000}, - {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */ - {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */ - {0xaa, 0x1b, 0x0000}, - {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc, */ - {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc, */ - {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc, */ - {0xaa, 0x05, 0x0010}, /* 00,05,10,aa, */ - {0xaa, 0x0a, 0x0001}, - {0xaa, 0x0b, 0x0000}, - {0xaa, 0x0c, 0x0001}, - {0xaa, 0x0d, 0x0000}, - {0xaa, 0x0e, 0x0001}, - {0xaa, 0x0f, 0x0000}, - {0xaa, 0x10, 0x0001}, - {0xaa, 0x11, 0x0000}, - {0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */ - {0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa (e6 -> e8) */ - {0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */ - {0xaa, 0x19, 0x0088}, /* 00,19,88,aa, */ - {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc, */ - {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc, */ - {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc, */ - {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc, */ - {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc, */ - {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc, */ - {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc, */ - {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc, */ - {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc, */ - {0xa0, 0x58, ZC3XX_R1A8_DIGITALGAIN}, - {0xa0, 0x61, ZC3XX_R116_RGAIN}, /* 01,16,61,cc, */ - {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */ - {0xaa, 0x1b, 0x0000}, - {} -}; -static const struct usb_action gc0303_50HZ[] = { - {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ - {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ - {0xaa, 0x84, 0x0063}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */ - {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0d,cc, */ - {0xa0, 0xa8, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc, */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */ - {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc, */ - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */ - {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */ - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */ - {0xa0, 0x48, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */ - {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */ - {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */ - {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */ - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */ - {0xa0, 0x7f, ZC3XX_R18D_YTARGET}, - {} -}; - -static const struct usb_action gc0303_50HZScale[] = { - {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ - {0xaa, 0x83, 0x0003}, /* 00,83,03,aa */ - {0xaa, 0x84, 0x0054}, /* 00,84,54,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */ - {0xa0, 0x0d, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0d,cc, */ - {0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc, */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */ - {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,8e,cc, */ - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */ - {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */ - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */ - {0xa0, 0x48, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */ - {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */ - {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */ - {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */ - {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */ - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */ - {0xa0, 0x7f, ZC3XX_R18D_YTARGET}, - {} -}; - -static const struct usb_action gc0303_60HZ[] = { - {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ - {0xaa, 0x83, 0x0000}, - {0xaa, 0x84, 0x003b}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */ - {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,05,cc, */ - {0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,88,cc, */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */ - {0xa0, 0x3b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3b,cc, */ - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */ - {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */ - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */ - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */ - {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */ - {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */ - {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */ - {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */ - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */ - {0xa0, 0x80, ZC3XX_R18D_YTARGET}, - {} -}; - -static const struct usb_action gc0303_60HZScale[] = { - {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ - {0xaa, 0x83, 0x0000}, - {0xaa, 0x84, 0x0076}, - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */ - {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,1,0b,cc, */ - {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,2,10,cc, */ - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,5,00,cc, */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,6,00,cc, */ - {0xa0, 0x76, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,7,76,cc, */ - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,c,0e,cc, */ - {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,f,15,cc, */ - {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,9,10,cc, */ - {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,a,24,cc, */ - {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,d,62,cc, */ - {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,e,90,cc, */ - {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,f,c8,cc, */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,0,ff,cc, */ - {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,d,58,cc, */ - {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */ - {0xa0, 0x80, ZC3XX_R18D_YTARGET}, - {} -}; - -static const struct usb_action gc0303_NoFliker[] = { - {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ - {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ - {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ - {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,0,00,cc, */ - {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */ - {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc, */ - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */ - {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */ - {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */ - {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */ - {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */ - {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */ - {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,03,cc */ - {} -}; - -static const struct usb_action gc0303_NoFlikerScale[] = { - {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ - {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ - {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ - {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */ - {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */ - {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID}, - {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW}, - {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */ - {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */ - {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc, */ - {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */ - {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */ - {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */ - {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */ - {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */ - {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */ - {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */ - {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,03,cc */ - {} -}; - -static u8 reg_r(struct gspca_dev *gspca_dev, - u16 index) -{ - int ret; - - if (gspca_dev->usb_err < 0) - return 0; - ret = usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - 0xa1, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x01, /* value */ - index, gspca_dev->usb_buf, 1, - 500); - if (ret < 0) { - pr_err("reg_r err %d\n", ret); - gspca_dev->usb_err = ret; - return 0; - } - return gspca_dev->usb_buf[0]; -} - -static void reg_w(struct gspca_dev *gspca_dev, - u8 value, - u16 index) -{ - int ret; - - if (gspca_dev->usb_err < 0) - return; - ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0xa0, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, NULL, 0, - 500); - if (ret < 0) { - pr_err("reg_w_i err %d\n", ret); - gspca_dev->usb_err = ret; - } -} - -static u16 i2c_read(struct gspca_dev *gspca_dev, - u8 reg) -{ - u8 retbyte; - u16 retval; - - if (gspca_dev->usb_err < 0) - return 0; - reg_w(gspca_dev, reg, 0x0092); - reg_w(gspca_dev, 0x02, 0x0090); /* <- read command */ - msleep(20); - retbyte = reg_r(gspca_dev, 0x0091); /* read status */ - if (retbyte != 0x00) - pr_err("i2c_r status error %02x\n", retbyte); - retval = reg_r(gspca_dev, 0x0095); /* read Lowbyte */ - retval |= reg_r(gspca_dev, 0x0096) << 8; /* read Hightbyte */ - return retval; -} - -static u8 i2c_write(struct gspca_dev *gspca_dev, - u8 reg, - u8 valL, - u8 valH) -{ - u8 retbyte; - - if (gspca_dev->usb_err < 0) - return 0; - reg_w(gspca_dev, reg, 0x92); - reg_w(gspca_dev, valL, 0x93); - reg_w(gspca_dev, valH, 0x94); - reg_w(gspca_dev, 0x01, 0x90); /* <- write command */ - msleep(1); - retbyte = reg_r(gspca_dev, 0x0091); /* read status */ - if (retbyte != 0x00) - pr_err("i2c_w status error %02x\n", retbyte); - return retbyte; -} - -static void usb_exchange(struct gspca_dev *gspca_dev, - const struct usb_action *action) -{ - while (action->req) { - switch (action->req) { - case 0xa0: /* write register */ - reg_w(gspca_dev, action->val, action->idx); - break; - case 0xa1: /* read status */ - reg_r(gspca_dev, action->idx); - break; - case 0xaa: - i2c_write(gspca_dev, - action->val, /* reg */ - action->idx & 0xff, /* valL */ - action->idx >> 8); /* valH */ - break; - case 0xbb: - i2c_write(gspca_dev, - action->idx >> 8, /* reg */ - action->idx & 0xff, /* valL */ - action->val); /* valH */ - break; - default: -/* case 0xdd: * delay */ - msleep(action->idx); - break; - } - action++; - msleep(1); - } -} - -static void setmatrix(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i; - const u8 *matrix; - static const u8 adcm2700_matrix[9] = -/* {0x66, 0xed, 0xed, 0xed, 0x66, 0xed, 0xed, 0xed, 0x66}; */ -/*ms-win*/ - {0x74, 0xed, 0xed, 0xed, 0x74, 0xed, 0xed, 0xed, 0x74}; - static const u8 gc0305_matrix[9] = - {0x50, 0xf8, 0xf8, 0xf8, 0x50, 0xf8, 0xf8, 0xf8, 0x50}; - static const u8 ov7620_matrix[9] = - {0x58, 0xf4, 0xf4, 0xf4, 0x58, 0xf4, 0xf4, 0xf4, 0x58}; - static const u8 pas202b_matrix[9] = - {0x4c, 0xf5, 0xff, 0xf9, 0x51, 0xf5, 0xfb, 0xed, 0x5f}; - static const u8 po2030_matrix[9] = - {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60}; - static const u8 tas5130c_matrix[9] = - {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68}; - static const u8 gc0303_matrix[9] = - {0x6c, 0xea, 0xea, 0xea, 0x6c, 0xea, 0xea, 0xea, 0x6c}; - static const u8 *matrix_tb[SENSOR_MAX] = { - [SENSOR_ADCM2700] = adcm2700_matrix, - [SENSOR_CS2102] = ov7620_matrix, - [SENSOR_CS2102K] = NULL, - [SENSOR_GC0303] = gc0303_matrix, - [SENSOR_GC0305] = gc0305_matrix, - [SENSOR_HDCS2020] = NULL, - [SENSOR_HV7131B] = NULL, - [SENSOR_HV7131R] = po2030_matrix, - [SENSOR_ICM105A] = po2030_matrix, - [SENSOR_MC501CB] = NULL, - [SENSOR_MT9V111_1] = gc0305_matrix, - [SENSOR_MT9V111_3] = gc0305_matrix, - [SENSOR_OV7620] = ov7620_matrix, - [SENSOR_OV7630C] = NULL, - [SENSOR_PAS106] = NULL, - [SENSOR_PAS202B] = pas202b_matrix, - [SENSOR_PB0330] = gc0305_matrix, - [SENSOR_PO2030] = po2030_matrix, - [SENSOR_TAS5130C] = tas5130c_matrix, - }; - - matrix = matrix_tb[sd->sensor]; - if (matrix == NULL) - return; /* matrix already loaded */ - for (i = 0; i < ARRAY_SIZE(ov7620_matrix); i++) - reg_w(gspca_dev, matrix[i], 0x010a + i); -} - -static void setsharpness(struct gspca_dev *gspca_dev, s32 val) -{ - static const u8 sharpness_tb[][2] = { - {0x02, 0x03}, - {0x04, 0x07}, - {0x08, 0x0f}, - {0x10, 0x1e} - }; - - reg_w(gspca_dev, sharpness_tb[val][0], 0x01c6); - reg_r(gspca_dev, 0x01c8); - reg_r(gspca_dev, 0x01c9); - reg_r(gspca_dev, 0x01ca); - reg_w(gspca_dev, sharpness_tb[val][1], 0x01cb); -} - -static void setcontrast(struct gspca_dev *gspca_dev, - s32 gamma, s32 brightness, s32 contrast) -{ - const u8 *Tgamma; - int g, i, adj, gp1, gp2; - u8 gr[16]; - static const u8 delta_b[16] = /* delta for brightness */ - {0x50, 0x38, 0x2d, 0x28, 0x24, 0x21, 0x1e, 0x1d, - 0x1d, 0x1b, 0x1b, 0x1b, 0x19, 0x18, 0x18, 0x18}; - static const u8 delta_c[16] = /* delta for contrast */ - {0x2c, 0x1a, 0x12, 0x0c, 0x0a, 0x06, 0x06, 0x06, - 0x04, 0x06, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02}; - static const u8 gamma_tb[6][16] = { - {0x00, 0x00, 0x03, 0x0d, 0x1b, 0x2e, 0x45, 0x5f, - 0x79, 0x93, 0xab, 0xc1, 0xd4, 0xe5, 0xf3, 0xff}, - {0x01, 0x0c, 0x1f, 0x3a, 0x53, 0x6d, 0x85, 0x9c, - 0xb0, 0xc2, 0xd1, 0xde, 0xe9, 0xf2, 0xf9, 0xff}, - {0x04, 0x16, 0x30, 0x4e, 0x68, 0x81, 0x98, 0xac, - 0xbe, 0xcd, 0xda, 0xe4, 0xed, 0xf5, 0xfb, 0xff}, - {0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, - 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff}, - {0x20, 0x4b, 0x6e, 0x8d, 0xa3, 0xb5, 0xc5, 0xd2, - 0xdc, 0xe5, 0xec, 0xf2, 0xf6, 0xfa, 0xfd, 0xff}, - {0x24, 0x44, 0x64, 0x84, 0x9d, 0xb2, 0xc4, 0xd3, - 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff}, - }; - - Tgamma = gamma_tb[gamma - 1]; - - contrast -= 128; /* -128 / 127 */ - brightness -= 128; /* -128 / 92 */ - adj = 0; - gp1 = gp2 = 0; - for (i = 0; i < 16; i++) { - g = Tgamma[i] + delta_b[i] * brightness / 256 - - delta_c[i] * contrast / 256 - adj / 2; - if (g > 0xff) - g = 0xff; - else if (g < 0) - g = 0; - reg_w(gspca_dev, g, 0x0120 + i); /* gamma */ - if (contrast > 0) - adj--; - else if (contrast < 0) - adj++; - if (i > 1) - gr[i - 1] = (g - gp2) / 2; - else if (i != 0) - gr[0] = gp1 == 0 ? 0 : (g - gp1); - gp2 = gp1; - gp1 = g; - } - gr[15] = (0xff - gp2) / 2; - for (i = 0; i < 16; i++) - reg_w(gspca_dev, gr[i], 0x0130 + i); /* gradient */ -} - -static s32 getexposure(struct gspca_dev *gspca_dev) -{ - return (i2c_read(gspca_dev, 0x25) << 9) - | (i2c_read(gspca_dev, 0x26) << 1) - | (i2c_read(gspca_dev, 0x27) >> 7); -} - -static void setexposure(struct gspca_dev *gspca_dev, s32 val) -{ - i2c_write(gspca_dev, 0x25, val >> 9, 0x00); - i2c_write(gspca_dev, 0x26, val >> 1, 0x00); - i2c_write(gspca_dev, 0x27, val << 7, 0x00); -} - -static void setquality(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - jpeg_set_qual(sd->jpeg_hdr, jpeg_qual[sd->reg08 >> 1]); - reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING); -} - -/* Matches the sensor's internal frame rate to the lighting frequency. - * Valid frequencies are: - * 50Hz, for European and Asian lighting (default) - * 60Hz, for American lighting - * 0 = No Fliker (for outdoore usage) - */ -static void setlightfreq(struct gspca_dev *gspca_dev, s32 val) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i, mode; - const struct usb_action *zc3_freq; - static const struct usb_action *freq_tb[SENSOR_MAX][6] = { - [SENSOR_ADCM2700] = - {adcm2700_NoFliker, adcm2700_NoFliker, - adcm2700_50HZ, adcm2700_50HZ, - adcm2700_60HZ, adcm2700_60HZ}, - [SENSOR_CS2102] = - {cs2102_NoFliker, cs2102_NoFlikerScale, - cs2102_50HZ, cs2102_50HZScale, - cs2102_60HZ, cs2102_60HZScale}, - [SENSOR_CS2102K] = - {cs2102_NoFliker, cs2102_NoFlikerScale, - NULL, NULL, /* currently disabled */ - NULL, NULL}, - [SENSOR_GC0303] = - {gc0303_NoFliker, gc0303_NoFlikerScale, - gc0303_50HZ, gc0303_50HZScale, - gc0303_60HZ, gc0303_60HZScale}, - [SENSOR_GC0305] = - {gc0305_NoFliker, gc0305_NoFliker, - gc0305_50HZ, gc0305_50HZ, - gc0305_60HZ, gc0305_60HZ}, - [SENSOR_HDCS2020] = - {hdcs2020_NoFliker, hdcs2020_NoFliker, - hdcs2020_50HZ, hdcs2020_50HZ, - hdcs2020_60HZ, hdcs2020_60HZ}, - [SENSOR_HV7131B] = - {hv7131b_NoFliker, hv7131b_NoFlikerScale, - hv7131b_50HZ, hv7131b_50HZScale, - hv7131b_60HZ, hv7131b_60HZScale}, - [SENSOR_HV7131R] = - {hv7131r_NoFliker, hv7131r_NoFlikerScale, - hv7131r_50HZ, hv7131r_50HZScale, - hv7131r_60HZ, hv7131r_60HZScale}, - [SENSOR_ICM105A] = - {icm105a_NoFliker, icm105a_NoFlikerScale, - icm105a_50HZ, icm105a_50HZScale, - icm105a_60HZ, icm105a_60HZScale}, - [SENSOR_MC501CB] = - {mc501cb_NoFliker, mc501cb_NoFlikerScale, - mc501cb_50HZ, mc501cb_50HZScale, - mc501cb_60HZ, mc501cb_60HZScale}, - [SENSOR_MT9V111_1] = - {mt9v111_1_AENoFliker, mt9v111_1_AENoFlikerScale, - mt9v111_1_AE50HZ, mt9v111_1_AE50HZScale, - mt9v111_1_AE60HZ, mt9v111_1_AE60HZScale}, - [SENSOR_MT9V111_3] = - {mt9v111_3_AENoFliker, mt9v111_3_AENoFlikerScale, - mt9v111_3_AE50HZ, mt9v111_3_AE50HZScale, - mt9v111_3_AE60HZ, mt9v111_3_AE60HZScale}, - [SENSOR_OV7620] = - {ov7620_NoFliker, ov7620_NoFliker, - ov7620_50HZ, ov7620_50HZ, - ov7620_60HZ, ov7620_60HZ}, - [SENSOR_OV7630C] = - {NULL, NULL, - NULL, NULL, - NULL, NULL}, - [SENSOR_PAS106] = - {pas106b_NoFliker, pas106b_NoFliker, - pas106b_50HZ, pas106b_50HZ, - pas106b_60HZ, pas106b_60HZ}, - [SENSOR_PAS202B] = - {pas202b_NoFliker, pas202b_NoFlikerScale, - pas202b_50HZ, pas202b_50HZScale, - pas202b_60HZ, pas202b_60HZScale}, - [SENSOR_PB0330] = - {pb0330_NoFliker, pb0330_NoFlikerScale, - pb0330_50HZ, pb0330_50HZScale, - pb0330_60HZ, pb0330_60HZScale}, - [SENSOR_PO2030] = - {po2030_NoFliker, po2030_NoFliker, - po2030_50HZ, po2030_50HZ, - po2030_60HZ, po2030_60HZ}, - [SENSOR_TAS5130C] = - {tas5130c_NoFliker, tas5130c_NoFlikerScale, - tas5130c_50HZ, tas5130c_50HZScale, - tas5130c_60HZ, tas5130c_60HZScale}, - }; - - i = val * 2; - mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - if (mode) - i++; /* 320x240 */ - zc3_freq = freq_tb[sd->sensor][i]; - if (zc3_freq == NULL) - return; - usb_exchange(gspca_dev, zc3_freq); - switch (sd->sensor) { - case SENSOR_GC0305: - if (mode /* if 320x240 */ - && val == 1) /* and 50Hz */ - reg_w(gspca_dev, 0x85, 0x018d); - /* win: 0x80, 0x018d */ - break; - case SENSOR_OV7620: - if (!mode) { /* if 640x480 */ - if (val != 0) /* and filter */ - reg_w(gspca_dev, 0x40, 0x0002); - else - reg_w(gspca_dev, 0x44, 0x0002); - } - break; - case SENSOR_PAS202B: - reg_w(gspca_dev, 0x00, 0x01a7); - break; - } -} - -static void setautogain(struct gspca_dev *gspca_dev, s32 val) -{ - reg_w(gspca_dev, val ? 0x42 : 0x02, 0x0180); -} - -/* - * Update the transfer parameters. - * This function is executed from a work queue. - */ -static void transfer_update(struct work_struct *work) -{ - struct sd *sd = container_of(work, struct sd, work); - struct gspca_dev *gspca_dev = &sd->gspca_dev; - int change, good; - u8 reg07, reg11; - - /* reg07 gets set to 0 by sd_start before starting us */ - reg07 = 0; - - good = 0; - for (;;) { - msleep(100); - - mutex_lock(&gspca_dev->usb_lock); -#ifdef CONFIG_PM - if (gspca_dev->frozen) - goto err; -#endif - if (!gspca_dev->dev || !gspca_dev->streaming) - goto err; - - /* Bit 0 of register 11 indicates FIFO overflow */ - gspca_dev->usb_err = 0; - reg11 = reg_r(gspca_dev, 0x0011); - if (gspca_dev->usb_err) - goto err; - - change = reg11 & 0x01; - if (change) { /* overflow */ - good = 0; - - if (reg07 == 0) /* Bit Rate Control not enabled? */ - reg07 = 0x32; /* Allow 98 bytes / unit */ - else if (reg07 > 2) - reg07 -= 2; /* Decrease allowed bytes / unit */ - else - change = 0; - } else { /* no overflow */ - good++; - if (good >= 10) { - good = 0; - if (reg07) { /* BRC enabled? */ - change = 1; - if (reg07 < 0x32) - reg07 += 2; - else - reg07 = 0; - } - } - } - if (change) { - gspca_dev->usb_err = 0; - reg_w(gspca_dev, reg07, 0x0007); - if (gspca_dev->usb_err) - goto err; - } - mutex_unlock(&gspca_dev->usb_lock); - } - return; -err: - mutex_unlock(&gspca_dev->usb_lock); -} - -static void send_unknown(struct gspca_dev *gspca_dev, int sensor) -{ - reg_w(gspca_dev, 0x01, 0x0000); /* bridge reset */ - switch (sensor) { - case SENSOR_PAS106: - reg_w(gspca_dev, 0x03, 0x003a); - reg_w(gspca_dev, 0x0c, 0x003b); - reg_w(gspca_dev, 0x08, 0x0038); - break; - case SENSOR_ADCM2700: - case SENSOR_GC0305: - case SENSOR_OV7620: - case SENSOR_MT9V111_1: - case SENSOR_MT9V111_3: - case SENSOR_PB0330: - case SENSOR_PO2030: - reg_w(gspca_dev, 0x0d, 0x003a); - reg_w(gspca_dev, 0x02, 0x003b); - reg_w(gspca_dev, 0x00, 0x0038); - break; - case SENSOR_HV7131R: - case SENSOR_PAS202B: - reg_w(gspca_dev, 0x03, 0x003b); - reg_w(gspca_dev, 0x0c, 0x003a); - reg_w(gspca_dev, 0x0b, 0x0039); - if (sensor == SENSOR_PAS202B) - reg_w(gspca_dev, 0x0b, 0x0038); - break; - } -} - -/* start probe 2 wires */ -static void start_2wr_probe(struct gspca_dev *gspca_dev, int sensor) -{ - reg_w(gspca_dev, 0x01, 0x0000); - reg_w(gspca_dev, sensor, 0x0010); - reg_w(gspca_dev, 0x01, 0x0001); - reg_w(gspca_dev, 0x03, 0x0012); - reg_w(gspca_dev, 0x01, 0x0012); -/* msleep(2); */ -} - -static int sif_probe(struct gspca_dev *gspca_dev) -{ - u16 checkword; - - start_2wr_probe(gspca_dev, 0x0f); /* PAS106 */ - reg_w(gspca_dev, 0x08, 0x008d); - msleep(150); - checkword = ((i2c_read(gspca_dev, 0x00) & 0x0f) << 4) - | ((i2c_read(gspca_dev, 0x01) & 0xf0) >> 4); - PDEBUG(D_PROBE, "probe sif 0x%04x", checkword); - if (checkword == 0x0007) { - send_unknown(gspca_dev, SENSOR_PAS106); - return 0x0f; /* PAS106 */ - } - return -1; -} - -static int vga_2wr_probe(struct gspca_dev *gspca_dev) -{ - u16 retword; - - start_2wr_probe(gspca_dev, 0x00); /* HV7131B */ - i2c_write(gspca_dev, 0x01, 0xaa, 0x00); - retword = i2c_read(gspca_dev, 0x01); - if (retword != 0) - return 0x00; /* HV7131B */ - - start_2wr_probe(gspca_dev, 0x04); /* CS2102 */ - i2c_write(gspca_dev, 0x01, 0xaa, 0x00); - retword = i2c_read(gspca_dev, 0x01); - if (retword != 0) - return 0x04; /* CS2102 */ - - start_2wr_probe(gspca_dev, 0x06); /* OmniVision */ - reg_w(gspca_dev, 0x08, 0x008d); - i2c_write(gspca_dev, 0x11, 0xaa, 0x00); - retword = i2c_read(gspca_dev, 0x11); - if (retword != 0) { - /* (should have returned 0xaa) --> Omnivision? */ - /* reg_r 0x10 -> 0x06 --> */ - goto ov_check; - } - - start_2wr_probe(gspca_dev, 0x08); /* HDCS2020 */ - i2c_write(gspca_dev, 0x1c, 0x00, 0x00); - i2c_write(gspca_dev, 0x15, 0xaa, 0x00); - retword = i2c_read(gspca_dev, 0x15); - if (retword != 0) - return 0x08; /* HDCS2020 */ - - start_2wr_probe(gspca_dev, 0x0a); /* PB0330 */ - i2c_write(gspca_dev, 0x07, 0xaa, 0xaa); - retword = i2c_read(gspca_dev, 0x07); - if (retword != 0) - return 0x0a; /* PB0330 */ - retword = i2c_read(gspca_dev, 0x03); - if (retword != 0) - return 0x0a; /* PB0330 ?? */ - retword = i2c_read(gspca_dev, 0x04); - if (retword != 0) - return 0x0a; /* PB0330 ?? */ - - start_2wr_probe(gspca_dev, 0x0c); /* ICM105A */ - i2c_write(gspca_dev, 0x01, 0x11, 0x00); - retword = i2c_read(gspca_dev, 0x01); - if (retword != 0) - return 0x0c; /* ICM105A */ - - start_2wr_probe(gspca_dev, 0x0e); /* PAS202BCB */ - reg_w(gspca_dev, 0x08, 0x008d); - i2c_write(gspca_dev, 0x03, 0xaa, 0x00); - msleep(50); - retword = i2c_read(gspca_dev, 0x03); - if (retword != 0) { - send_unknown(gspca_dev, SENSOR_PAS202B); - return 0x0e; /* PAS202BCB */ - } - - start_2wr_probe(gspca_dev, 0x02); /* TAS5130C */ - i2c_write(gspca_dev, 0x01, 0xaa, 0x00); - retword = i2c_read(gspca_dev, 0x01); - if (retword != 0) - return 0x02; /* TAS5130C */ -ov_check: - reg_r(gspca_dev, 0x0010); /* ?? */ - reg_r(gspca_dev, 0x0010); - - reg_w(gspca_dev, 0x01, 0x0000); - reg_w(gspca_dev, 0x01, 0x0001); - reg_w(gspca_dev, 0x06, 0x0010); /* OmniVision */ - reg_w(gspca_dev, 0xa1, 0x008b); - reg_w(gspca_dev, 0x08, 0x008d); - msleep(500); - reg_w(gspca_dev, 0x01, 0x0012); - i2c_write(gspca_dev, 0x12, 0x80, 0x00); /* sensor reset */ - retword = i2c_read(gspca_dev, 0x0a) << 8; - retword |= i2c_read(gspca_dev, 0x0b); - PDEBUG(D_PROBE, "probe 2wr ov vga 0x%04x", retword); - switch (retword) { - case 0x7631: /* OV7630C */ - reg_w(gspca_dev, 0x06, 0x0010); - break; - case 0x7620: /* OV7620 */ - case 0x7648: /* OV7648 */ - break; - default: - return -1; /* not OmniVision */ - } - return retword; -} - -struct sensor_by_chipset_revision { - u16 revision; - u8 internal_sensor_id; -}; -static const struct sensor_by_chipset_revision chipset_revision_sensor[] = { - {0xc000, 0x12}, /* TAS5130C */ - {0xc001, 0x13}, /* MT9V111 */ - {0xe001, 0x13}, - {0x8001, 0x13}, - {0x8000, 0x14}, /* CS2102K */ - {0x8400, 0x15}, /* MT9V111 */ - {0xe400, 0x15}, -}; - -static int vga_3wr_probe(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i; - u16 retword; - -/*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/ - reg_w(gspca_dev, 0x02, 0x0010); - reg_r(gspca_dev, 0x0010); - reg_w(gspca_dev, 0x01, 0x0000); - reg_w(gspca_dev, 0x00, 0x0010); - reg_w(gspca_dev, 0x01, 0x0001); - reg_w(gspca_dev, 0x91, 0x008b); - reg_w(gspca_dev, 0x03, 0x0012); - reg_w(gspca_dev, 0x01, 0x0012); - reg_w(gspca_dev, 0x05, 0x0012); - retword = i2c_read(gspca_dev, 0x14); - if (retword != 0) - return 0x11; /* HV7131R */ - retword = i2c_read(gspca_dev, 0x15); - if (retword != 0) - return 0x11; /* HV7131R */ - retword = i2c_read(gspca_dev, 0x16); - if (retword != 0) - return 0x11; /* HV7131R */ - - reg_w(gspca_dev, 0x02, 0x0010); - retword = reg_r(gspca_dev, 0x000b) << 8; - retword |= reg_r(gspca_dev, 0x000a); - PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", retword); - reg_r(gspca_dev, 0x0010); - if ((retword & 0xff00) == 0x6400) - return 0x02; /* TAS5130C */ - for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) { - if (chipset_revision_sensor[i].revision == retword) { - sd->chip_revision = retword; - send_unknown(gspca_dev, SENSOR_PB0330); - return chipset_revision_sensor[i].internal_sensor_id; - } - } - - reg_w(gspca_dev, 0x01, 0x0000); /* check PB0330 */ - reg_w(gspca_dev, 0x01, 0x0001); - reg_w(gspca_dev, 0xdd, 0x008b); - reg_w(gspca_dev, 0x0a, 0x0010); - reg_w(gspca_dev, 0x03, 0x0012); - reg_w(gspca_dev, 0x01, 0x0012); - retword = i2c_read(gspca_dev, 0x00); - if (retword != 0) { - PDEBUG(D_PROBE, "probe 3wr vga type 0a"); - return 0x0a; /* PB0330 */ - } - - /* probe gc0303 / gc0305 */ - reg_w(gspca_dev, 0x01, 0x0000); - reg_w(gspca_dev, 0x01, 0x0001); - reg_w(gspca_dev, 0x98, 0x008b); - reg_w(gspca_dev, 0x01, 0x0010); - reg_w(gspca_dev, 0x03, 0x0012); - msleep(2); - reg_w(gspca_dev, 0x01, 0x0012); - retword = i2c_read(gspca_dev, 0x00); - if (retword != 0) { - PDEBUG(D_PROBE, "probe 3wr vga type %02x", retword); - if (retword == 0x0011) /* gc0303 */ - return 0x0303; - if (retword == 0x0029) /* gc0305 */ - send_unknown(gspca_dev, SENSOR_GC0305); - return retword; - } - - reg_w(gspca_dev, 0x01, 0x0000); /* check OmniVision */ - reg_w(gspca_dev, 0x01, 0x0001); - reg_w(gspca_dev, 0xa1, 0x008b); - reg_w(gspca_dev, 0x08, 0x008d); - reg_w(gspca_dev, 0x06, 0x0010); - reg_w(gspca_dev, 0x01, 0x0012); - reg_w(gspca_dev, 0x05, 0x0012); - if (i2c_read(gspca_dev, 0x1c) == 0x007f /* OV7610 - manufacturer ID */ - && i2c_read(gspca_dev, 0x1d) == 0x00a2) { - send_unknown(gspca_dev, SENSOR_OV7620); - return 0x06; /* OmniVision confirm ? */ - } - - reg_w(gspca_dev, 0x01, 0x0000); - reg_w(gspca_dev, 0x00, 0x0002); - reg_w(gspca_dev, 0x01, 0x0010); - reg_w(gspca_dev, 0x01, 0x0001); - reg_w(gspca_dev, 0xee, 0x008b); - reg_w(gspca_dev, 0x03, 0x0012); - reg_w(gspca_dev, 0x01, 0x0012); - reg_w(gspca_dev, 0x05, 0x0012); - retword = i2c_read(gspca_dev, 0x00) << 8; /* ID 0 */ - retword |= i2c_read(gspca_dev, 0x01); /* ID 1 */ - PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", retword); - if (retword == 0x2030) { -#ifdef GSPCA_DEBUG - u8 retbyte; - - retbyte = i2c_read(gspca_dev, 0x02); /* revision number */ - PDEBUG(D_PROBE, "sensor PO2030 rev 0x%02x", retbyte); -#endif - send_unknown(gspca_dev, SENSOR_PO2030); - return retword; - } - - reg_w(gspca_dev, 0x01, 0x0000); - reg_w(gspca_dev, 0x0a, 0x0010); - reg_w(gspca_dev, 0xd3, 0x008b); - reg_w(gspca_dev, 0x01, 0x0001); - reg_w(gspca_dev, 0x03, 0x0012); - reg_w(gspca_dev, 0x01, 0x0012); - reg_w(gspca_dev, 0x05, 0x0012); - reg_w(gspca_dev, 0xd3, 0x008b); - retword = i2c_read(gspca_dev, 0x01); - if (retword != 0) { - PDEBUG(D_PROBE, "probe 3wr vga type 0a ? ret: %04x", retword); - return 0x16; /* adcm2700 (6100/6200) */ - } - return -1; -} - -static int zcxx_probeSensor(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int sensor; - - switch (sd->sensor) { - case SENSOR_MC501CB: - return -1; /* don't probe */ - case SENSOR_GC0303: - /* may probe but with no write in reg 0x0010 */ - return -1; /* don't probe */ - case SENSOR_PAS106: - sensor = sif_probe(gspca_dev); - if (sensor >= 0) - return sensor; - break; - } - sensor = vga_2wr_probe(gspca_dev); - if (sensor >= 0) - return sensor; - return vga_3wr_probe(gspca_dev); -} - -/* this function is called at probe time */ -static int sd_config(struct gspca_dev *gspca_dev, - const struct usb_device_id *id) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (id->idProduct == 0x301b) - sd->bridge = BRIDGE_ZC301; - else - sd->bridge = BRIDGE_ZC303; - - /* define some sensors from the vendor/product */ - sd->sensor = id->driver_info; - - sd->reg08 = REG08_DEF; - - INIT_WORK(&sd->work, transfer_update); - - return 0; -} - -static int zcxx_g_volatile_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - - switch (ctrl->id) { - case V4L2_CID_AUTOGAIN: - gspca_dev->usb_err = 0; - if (ctrl->val && sd->exposure && gspca_dev->streaming) - sd->exposure->val = getexposure(gspca_dev); - return gspca_dev->usb_err; - } - return -EINVAL; -} - -static int zcxx_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct gspca_dev *gspca_dev = - container_of(ctrl->handler, struct gspca_dev, ctrl_handler); - struct sd *sd = (struct sd *)gspca_dev; - int i, qual; - - gspca_dev->usb_err = 0; - - if (ctrl->id == V4L2_CID_JPEG_COMPRESSION_QUALITY) { - qual = sd->reg08 >> 1; - - for (i = 0; i < ARRAY_SIZE(jpeg_qual); i++) { - if (ctrl->val <= jpeg_qual[i]) - break; - } - if (i > 0 && i == qual && ctrl->val < jpeg_qual[i]) - i--; - - /* With high quality settings we need max bandwidth */ - if (i >= 2 && gspca_dev->streaming && - !gspca_dev->cam.needs_full_bandwidth) - return -EBUSY; - - sd->reg08 = (i << 1) | 1; - ctrl->val = jpeg_qual[i]; - } - - if (!gspca_dev->streaming) - return 0; - - switch (ctrl->id) { - /* gamma/brightness/contrast cluster */ - case V4L2_CID_GAMMA: - setcontrast(gspca_dev, sd->gamma->val, - sd->brightness->val, sd->contrast->val); - break; - /* autogain/exposure cluster */ - case V4L2_CID_AUTOGAIN: - setautogain(gspca_dev, ctrl->val); - if (!gspca_dev->usb_err && !ctrl->val && sd->exposure) - setexposure(gspca_dev, sd->exposure->val); - break; - case V4L2_CID_POWER_LINE_FREQUENCY: - setlightfreq(gspca_dev, ctrl->val); - break; - case V4L2_CID_SHARPNESS: - setsharpness(gspca_dev, ctrl->val); - break; - case V4L2_CID_JPEG_COMPRESSION_QUALITY: - setquality(gspca_dev); - break; - } - return gspca_dev->usb_err; -} - -static const struct v4l2_ctrl_ops zcxx_ctrl_ops = { - .g_volatile_ctrl = zcxx_g_volatile_ctrl, - .s_ctrl = zcxx_s_ctrl, -}; - -static int sd_init_controls(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *)gspca_dev; - struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; - static const u8 gamma[SENSOR_MAX] = { - [SENSOR_ADCM2700] = 4, - [SENSOR_CS2102] = 4, - [SENSOR_CS2102K] = 5, - [SENSOR_GC0303] = 3, - [SENSOR_GC0305] = 4, - [SENSOR_HDCS2020] = 4, - [SENSOR_HV7131B] = 4, - [SENSOR_HV7131R] = 4, - [SENSOR_ICM105A] = 4, - [SENSOR_MC501CB] = 4, - [SENSOR_MT9V111_1] = 4, - [SENSOR_MT9V111_3] = 4, - [SENSOR_OV7620] = 3, - [SENSOR_OV7630C] = 4, - [SENSOR_PAS106] = 4, - [SENSOR_PAS202B] = 4, - [SENSOR_PB0330] = 4, - [SENSOR_PO2030] = 4, - [SENSOR_TAS5130C] = 3, - }; - - gspca_dev->vdev.ctrl_handler = hdl; - v4l2_ctrl_handler_init(hdl, 8); - sd->brightness = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); - sd->contrast = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, - V4L2_CID_CONTRAST, 0, 255, 1, 128); - sd->gamma = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, - V4L2_CID_GAMMA, 1, 6, 1, gamma[sd->sensor]); - if (sd->sensor == SENSOR_HV7131R) - sd->exposure = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, - V4L2_CID_EXPOSURE, 0x30d, 0x493e, 1, 0x927); - sd->autogain = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, 1); - if (sd->sensor != SENSOR_OV7630C) - sd->plfreq = v4l2_ctrl_new_std_menu(hdl, &zcxx_ctrl_ops, - V4L2_CID_POWER_LINE_FREQUENCY, - V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, - V4L2_CID_POWER_LINE_FREQUENCY_DISABLED); - sd->sharpness = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, - V4L2_CID_SHARPNESS, 0, 3, 1, - sd->sensor == SENSOR_PO2030 ? 0 : 2); - sd->jpegqual = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, - V4L2_CID_JPEG_COMPRESSION_QUALITY, - jpeg_qual[0], jpeg_qual[ARRAY_SIZE(jpeg_qual) - 1], 1, - jpeg_qual[REG08_DEF >> 1]); - if (hdl->error) { - pr_err("Could not initialize controls\n"); - return hdl->error; - } - v4l2_ctrl_cluster(3, &sd->gamma); - if (sd->sensor == SENSOR_HV7131R) - v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, true); - return 0; -} - -/* this function is called at probe and resume time */ -static int sd_init(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct cam *cam; - int sensor; - static const u8 mode_tb[SENSOR_MAX] = { - [SENSOR_ADCM2700] = 2, - [SENSOR_CS2102] = 1, - [SENSOR_CS2102K] = 1, - [SENSOR_GC0303] = 1, - [SENSOR_GC0305] = 1, - [SENSOR_HDCS2020] = 1, - [SENSOR_HV7131B] = 1, - [SENSOR_HV7131R] = 1, - [SENSOR_ICM105A] = 1, - [SENSOR_MC501CB] = 2, - [SENSOR_MT9V111_1] = 1, - [SENSOR_MT9V111_3] = 1, - [SENSOR_OV7620] = 2, - [SENSOR_OV7630C] = 1, - [SENSOR_PAS106] = 0, - [SENSOR_PAS202B] = 1, - [SENSOR_PB0330] = 1, - [SENSOR_PO2030] = 1, - [SENSOR_TAS5130C] = 1, - }; - - sensor = zcxx_probeSensor(gspca_dev); - if (sensor >= 0) - PDEBUG(D_PROBE, "probe sensor -> %04x", sensor); - if ((unsigned) force_sensor < SENSOR_MAX) { - sd->sensor = force_sensor; - PDEBUG(D_PROBE, "sensor forced to %d", force_sensor); - } else { - switch (sensor) { - case -1: - switch (sd->sensor) { - case SENSOR_MC501CB: - PDEBUG(D_PROBE, "Sensor MC501CB"); - break; - case SENSOR_GC0303: - PDEBUG(D_PROBE, "Sensor GC0303"); - break; - default: - pr_warn("Unknown sensor - set to TAS5130C\n"); - sd->sensor = SENSOR_TAS5130C; - } - break; - case 0: - /* check the sensor type */ - sensor = i2c_read(gspca_dev, 0x00); - PDEBUG(D_PROBE, "Sensor hv7131 type %d", sensor); - switch (sensor) { - case 0: /* hv7131b */ - case 1: /* hv7131e */ - PDEBUG(D_PROBE, "Find Sensor HV7131B"); - sd->sensor = SENSOR_HV7131B; - break; - default: -/* case 2: * hv7131r */ - PDEBUG(D_PROBE, "Find Sensor HV7131R"); - sd->sensor = SENSOR_HV7131R; - break; - } - break; - case 0x02: - PDEBUG(D_PROBE, "Sensor TAS5130C"); - sd->sensor = SENSOR_TAS5130C; - break; - case 0x04: - PDEBUG(D_PROBE, "Find Sensor CS2102"); - sd->sensor = SENSOR_CS2102; - break; - case 0x08: - PDEBUG(D_PROBE, "Find Sensor HDCS2020"); - sd->sensor = SENSOR_HDCS2020; - break; - case 0x0a: - PDEBUG(D_PROBE, - "Find Sensor PB0330. Chip revision %x", - sd->chip_revision); - sd->sensor = SENSOR_PB0330; - break; - case 0x0c: - PDEBUG(D_PROBE, "Find Sensor ICM105A"); - sd->sensor = SENSOR_ICM105A; - break; - case 0x0e: - PDEBUG(D_PROBE, "Find Sensor PAS202B"); - sd->sensor = SENSOR_PAS202B; - break; - case 0x0f: - PDEBUG(D_PROBE, "Find Sensor PAS106"); - sd->sensor = SENSOR_PAS106; - break; - case 0x10: - case 0x12: - PDEBUG(D_PROBE, "Find Sensor TAS5130C"); - sd->sensor = SENSOR_TAS5130C; - break; - case 0x11: - PDEBUG(D_PROBE, "Find Sensor HV7131R"); - sd->sensor = SENSOR_HV7131R; - break; - case 0x13: - case 0x15: - PDEBUG(D_PROBE, - "Sensor MT9V111. Chip revision %04x", - sd->chip_revision); - sd->sensor = sd->bridge == BRIDGE_ZC301 - ? SENSOR_MT9V111_1 - : SENSOR_MT9V111_3; - break; - case 0x14: - PDEBUG(D_PROBE, - "Find Sensor CS2102K?. Chip revision %x", - sd->chip_revision); - sd->sensor = SENSOR_CS2102K; - break; - case 0x16: - PDEBUG(D_PROBE, "Find Sensor ADCM2700"); - sd->sensor = SENSOR_ADCM2700; - break; - case 0x29: - PDEBUG(D_PROBE, "Find Sensor GC0305"); - sd->sensor = SENSOR_GC0305; - break; - case 0x0303: - PDEBUG(D_PROBE, "Sensor GC0303"); - sd->sensor = SENSOR_GC0303; - break; - case 0x2030: - PDEBUG(D_PROBE, "Find Sensor PO2030"); - sd->sensor = SENSOR_PO2030; - break; - case 0x7620: - PDEBUG(D_PROBE, "Find Sensor OV7620"); - sd->sensor = SENSOR_OV7620; - break; - case 0x7631: - PDEBUG(D_PROBE, "Find Sensor OV7630C"); - sd->sensor = SENSOR_OV7630C; - break; - case 0x7648: - PDEBUG(D_PROBE, "Find Sensor OV7648"); - sd->sensor = SENSOR_OV7620; /* same sensor (?) */ - break; - default: - pr_err("Unknown sensor %04x\n", sensor); - return -EINVAL; - } - } - if (sensor < 0x20) { - if (sensor == -1 || sensor == 0x10 || sensor == 0x12) - reg_w(gspca_dev, 0x02, 0x0010); - reg_r(gspca_dev, 0x0010); - } - - cam = &gspca_dev->cam; - switch (mode_tb[sd->sensor]) { - case 0: - cam->cam_mode = sif_mode; - cam->nmodes = ARRAY_SIZE(sif_mode); - break; - case 1: - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); - break; - default: -/* case 2: */ - cam->cam_mode = broken_vga_mode; - cam->nmodes = ARRAY_SIZE(broken_vga_mode); - break; - } - - /* switch off the led */ - reg_w(gspca_dev, 0x01, 0x0000); - return gspca_dev->usb_err; -} - -static int sd_pre_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - gspca_dev->cam.needs_full_bandwidth = (sd->reg08 >= 4) ? 1 : 0; - return 0; -} - -static int sd_start(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - int mode; - static const struct usb_action *init_tb[SENSOR_MAX][2] = { - [SENSOR_ADCM2700] = - {adcm2700_Initial, adcm2700_InitialScale}, - [SENSOR_CS2102] = - {cs2102_Initial, cs2102_InitialScale}, - [SENSOR_CS2102K] = - {cs2102K_Initial, cs2102K_InitialScale}, - [SENSOR_GC0303] = - {gc0303_Initial, gc0303_InitialScale}, - [SENSOR_GC0305] = - {gc0305_Initial, gc0305_InitialScale}, - [SENSOR_HDCS2020] = - {hdcs2020_Initial, hdcs2020_InitialScale}, - [SENSOR_HV7131B] = - {hv7131b_Initial, hv7131b_InitialScale}, - [SENSOR_HV7131R] = - {hv7131r_Initial, hv7131r_InitialScale}, - [SENSOR_ICM105A] = - {icm105a_Initial, icm105a_InitialScale}, - [SENSOR_MC501CB] = - {mc501cb_Initial, mc501cb_InitialScale}, - [SENSOR_MT9V111_1] = - {mt9v111_1_Initial, mt9v111_1_InitialScale}, - [SENSOR_MT9V111_3] = - {mt9v111_3_Initial, mt9v111_3_InitialScale}, - [SENSOR_OV7620] = - {ov7620_Initial, ov7620_InitialScale}, - [SENSOR_OV7630C] = - {ov7630c_Initial, ov7630c_InitialScale}, - [SENSOR_PAS106] = - {pas106b_Initial, pas106b_InitialScale}, - [SENSOR_PAS202B] = - {pas202b_Initial, pas202b_InitialScale}, - [SENSOR_PB0330] = - {pb0330_Initial, pb0330_InitialScale}, - [SENSOR_PO2030] = - {po2030_Initial, po2030_InitialScale}, - [SENSOR_TAS5130C] = - {tas5130c_Initial, tas5130c_InitialScale}, - }; - - /* create the JPEG header */ - jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, - 0x21); /* JPEG 422 */ - - mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; - switch (sd->sensor) { - case SENSOR_HV7131R: - zcxx_probeSensor(gspca_dev); - break; - case SENSOR_PAS106: - usb_exchange(gspca_dev, pas106b_Initial_com); - break; - } - usb_exchange(gspca_dev, init_tb[sd->sensor][mode]); - - switch (sd->sensor) { - case SENSOR_ADCM2700: - case SENSOR_GC0305: - case SENSOR_OV7620: - case SENSOR_PO2030: - case SENSOR_TAS5130C: - case SENSOR_GC0303: -/* msleep(100); * ?? */ - reg_r(gspca_dev, 0x0002); /* --> 0x40 */ - reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */ - reg_w(gspca_dev, 0x15, 0x01ae); - if (sd->sensor == SENSOR_TAS5130C) - break; - reg_w(gspca_dev, 0x0d, 0x003a); - reg_w(gspca_dev, 0x02, 0x003b); - reg_w(gspca_dev, 0x00, 0x0038); - break; - case SENSOR_HV7131R: - case SENSOR_PAS202B: - reg_w(gspca_dev, 0x03, 0x003b); - reg_w(gspca_dev, 0x0c, 0x003a); - reg_w(gspca_dev, 0x0b, 0x0039); - if (sd->sensor == SENSOR_HV7131R) - reg_w(gspca_dev, 0x50, ZC3XX_R11D_GLOBALGAIN); - break; - } - - setmatrix(gspca_dev); - switch (sd->sensor) { - case SENSOR_ADCM2700: - case SENSOR_OV7620: - reg_r(gspca_dev, 0x0008); - reg_w(gspca_dev, 0x00, 0x0008); - break; - case SENSOR_PAS202B: - case SENSOR_GC0305: - case SENSOR_HV7131R: - case SENSOR_TAS5130C: - reg_r(gspca_dev, 0x0008); - /* fall thru */ - case SENSOR_PO2030: - reg_w(gspca_dev, 0x03, 0x0008); - break; - } - setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness)); - - /* set the gamma tables when not set */ - switch (sd->sensor) { - case SENSOR_CS2102K: /* gamma set in xxx_Initial */ - case SENSOR_HDCS2020: - case SENSOR_OV7630C: - break; - default: - setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma), - v4l2_ctrl_g_ctrl(sd->brightness), - v4l2_ctrl_g_ctrl(sd->contrast)); - break; - } - setmatrix(gspca_dev); /* one more time? */ - switch (sd->sensor) { - case SENSOR_OV7620: - case SENSOR_PAS202B: - reg_r(gspca_dev, 0x0180); /* from win */ - reg_w(gspca_dev, 0x00, 0x0180); - break; - } - setquality(gspca_dev); - /* Start with BRC disabled, transfer_update will enable it if needed */ - reg_w(gspca_dev, 0x00, 0x0007); - if (sd->plfreq) - setlightfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->plfreq)); - - switch (sd->sensor) { - case SENSOR_ADCM2700: - reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */ - reg_w(gspca_dev, 0x15, 0x01ae); - reg_w(gspca_dev, 0x02, 0x0180); - /* ms-win + */ - reg_w(gspca_dev, 0x40, 0x0117); - break; - case SENSOR_HV7131R: - setexposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure)); - reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN); - break; - case SENSOR_GC0305: - case SENSOR_TAS5130C: - reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */ - reg_w(gspca_dev, 0x15, 0x01ae); - /* fall thru */ - case SENSOR_PAS202B: - case SENSOR_PO2030: -/* reg_w(gspca_dev, 0x40, ZC3XX_R117_GGAIN); in win traces */ - reg_r(gspca_dev, 0x0180); - break; - case SENSOR_OV7620: - reg_w(gspca_dev, 0x09, 0x01ad); - reg_w(gspca_dev, 0x15, 0x01ae); - i2c_read(gspca_dev, 0x13); /*fixme: returns 0xa3 */ - i2c_write(gspca_dev, 0x13, 0xa3, 0x00); - /*fixme: returned value to send? */ - reg_w(gspca_dev, 0x40, 0x0117); - reg_r(gspca_dev, 0x0180); - break; - } - - setautogain(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain)); - - if (gspca_dev->usb_err < 0) - return gspca_dev->usb_err; - - /* Start the transfer parameters update thread */ - sd->work_thread = create_singlethread_workqueue(KBUILD_MODNAME); - queue_work(sd->work_thread, &sd->work); - - return 0; -} - -/* called on streamoff with alt 0 and on disconnect */ -static void sd_stop0(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->work_thread != NULL) { - mutex_unlock(&gspca_dev->usb_lock); - destroy_workqueue(sd->work_thread); - mutex_lock(&gspca_dev->usb_lock); - sd->work_thread = NULL; - } - if (!gspca_dev->dev) - return; - send_unknown(gspca_dev, sd->sensor); -} - -static void sd_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, - int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* check the JPEG end of frame */ - if (len >= 3 - && data[len - 3] == 0xff && data[len - 2] == 0xd9) { -/*fixme: what does the last byte mean?*/ - gspca_frame_add(gspca_dev, LAST_PACKET, - data, len - 1); - return; - } - - /* check the JPEG start of a frame */ - if (data[0] == 0xff && data[1] == 0xd8) { - /* put the JPEG header in the new frame */ - gspca_frame_add(gspca_dev, FIRST_PACKET, - sd->jpeg_hdr, JPEG_HDR_SZ); - - /* remove the webcam's header: - * ff d8 ff fe 00 0e 00 00 ss ss 00 01 ww ww hh hh pp pp - * - 'ss ss' is the frame sequence number (BE) - * - 'ww ww' and 'hh hh' are the window dimensions (BE) - * - 'pp pp' is the packet sequence number (BE) - */ - data += 18; - len -= 18; - } - gspca_frame_add(gspca_dev, INTER_PACKET, data, len); -} - -static int sd_set_jcomp(struct gspca_dev *gspca_dev, - struct v4l2_jpegcompression *jcomp) -{ - struct sd *sd = (struct sd *) gspca_dev; - int ret; - - ret = v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality); - if (ret) - return ret; - jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual); - return 0; -} - -static int sd_get_jcomp(struct gspca_dev *gspca_dev, - struct v4l2_jpegcompression *jcomp) -{ - struct sd *sd = (struct sd *) gspca_dev; - - memset(jcomp, 0, sizeof *jcomp); - jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual); - jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT - | V4L2_JPEG_MARKER_DQT; - return 0; -} - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) -static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, - u8 *data, /* interrupt packet data */ - int len) /* interrput packet length */ -{ - if (len == 8 && data[4] == 1) { - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); - input_sync(gspca_dev->input_dev); - input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); - input_sync(gspca_dev->input_dev); - } - - return 0; -} -#endif - -static const struct sd_desc sd_desc = { - .name = KBUILD_MODNAME, - .config = sd_config, - .init = sd_init, - .init_controls = sd_init_controls, - .isoc_init = sd_pre_start, - .start = sd_start, - .stop0 = sd_stop0, - .pkt_scan = sd_pkt_scan, - .get_jcomp = sd_get_jcomp, - .set_jcomp = sd_set_jcomp, -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - .int_pkt_scan = sd_int_pkt_scan, -#endif -}; - -static const struct usb_device_id device_table[] = { - {USB_DEVICE(0x03f0, 0x1b07)}, - {USB_DEVICE(0x041e, 0x041e)}, - {USB_DEVICE(0x041e, 0x4017)}, - {USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106}, - {USB_DEVICE(0x041e, 0x401e)}, - {USB_DEVICE(0x041e, 0x401f)}, - {USB_DEVICE(0x041e, 0x4022)}, - {USB_DEVICE(0x041e, 0x4029)}, - {USB_DEVICE(0x041e, 0x4034), .driver_info = SENSOR_PAS106}, - {USB_DEVICE(0x041e, 0x4035), .driver_info = SENSOR_PAS106}, - {USB_DEVICE(0x041e, 0x4036)}, - {USB_DEVICE(0x041e, 0x403a)}, - {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_GC0303}, - {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_GC0303}, - {USB_DEVICE(0x0458, 0x7007)}, - {USB_DEVICE(0x0458, 0x700c)}, - {USB_DEVICE(0x0458, 0x700f)}, - {USB_DEVICE(0x0461, 0x0a00)}, - {USB_DEVICE(0x046d, 0x089d), .driver_info = SENSOR_MC501CB}, - {USB_DEVICE(0x046d, 0x08a0)}, - {USB_DEVICE(0x046d, 0x08a1)}, - {USB_DEVICE(0x046d, 0x08a2)}, - {USB_DEVICE(0x046d, 0x08a3)}, - {USB_DEVICE(0x046d, 0x08a6)}, - {USB_DEVICE(0x046d, 0x08a7)}, - {USB_DEVICE(0x046d, 0x08a9)}, - {USB_DEVICE(0x046d, 0x08aa)}, - {USB_DEVICE(0x046d, 0x08ac)}, - {USB_DEVICE(0x046d, 0x08ad)}, - {USB_DEVICE(0x046d, 0x08ae)}, - {USB_DEVICE(0x046d, 0x08af)}, - {USB_DEVICE(0x046d, 0x08b9)}, - {USB_DEVICE(0x046d, 0x08d7)}, - {USB_DEVICE(0x046d, 0x08d8)}, - {USB_DEVICE(0x046d, 0x08d9)}, - {USB_DEVICE(0x046d, 0x08da)}, - {USB_DEVICE(0x046d, 0x08dd), .driver_info = SENSOR_MC501CB}, - {USB_DEVICE(0x0471, 0x0325), .driver_info = SENSOR_PAS106}, - {USB_DEVICE(0x0471, 0x0326), .driver_info = SENSOR_PAS106}, - {USB_DEVICE(0x0471, 0x032d), .driver_info = SENSOR_PAS106}, - {USB_DEVICE(0x0471, 0x032e), .driver_info = SENSOR_PAS106}, - {USB_DEVICE(0x055f, 0xc005)}, - {USB_DEVICE(0x055f, 0xd003)}, - {USB_DEVICE(0x055f, 0xd004)}, - {USB_DEVICE(0x0698, 0x2003)}, - {USB_DEVICE(0x0ac8, 0x0301), .driver_info = SENSOR_PAS106}, - {USB_DEVICE(0x0ac8, 0x0302), .driver_info = SENSOR_PAS106}, - {USB_DEVICE(0x0ac8, 0x301b)}, - {USB_DEVICE(0x0ac8, 0x303b)}, - {USB_DEVICE(0x0ac8, 0x305b)}, - {USB_DEVICE(0x0ac8, 0x307b)}, - {USB_DEVICE(0x10fd, 0x0128)}, - {USB_DEVICE(0x10fd, 0x804d)}, - {USB_DEVICE(0x10fd, 0x8050)}, - {} /* end of entry */ -}; -MODULE_DEVICE_TABLE(usb, device_table); - -/* -- device connect -- */ -static int sd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), - THIS_MODULE); -} - -/* USB driver */ -static struct usb_driver sd_driver = { - .name = KBUILD_MODNAME, - .id_table = device_table, - .probe = sd_probe, - .disconnect = gspca_disconnect, -#ifdef CONFIG_PM - .suspend = gspca_suspend, - .resume = gspca_resume, - .reset_resume = gspca_resume, -#endif -}; - -module_usb_driver(sd_driver); - -module_param(force_sensor, int, 0644); -MODULE_PARM_DESC(force_sensor, - "Force sensor. Only for experts!!!"); diff --git a/drivers/media/video/hdpvr/Kconfig b/drivers/media/video/hdpvr/Kconfig deleted file mode 100644 index de247f3c7d05..000000000000 --- a/drivers/media/video/hdpvr/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ - -config VIDEO_HDPVR - tristate "Hauppauge HD PVR support" - depends on VIDEO_DEV - ---help--- - This is a video4linux driver for Hauppauge's HD PVR USB device. - - To compile this driver as a module, choose M here: the - module will be called hdpvr - diff --git a/drivers/media/video/hdpvr/Makefile b/drivers/media/video/hdpvr/Makefile deleted file mode 100644 index 52f057f24e39..000000000000 --- a/drivers/media/video/hdpvr/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-video.o hdpvr-i2c.o - -obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o - -ccflags-y += -Idrivers/media/video - -ccflags-y += $(extra-cflags-y) $(extra-cflags-m) diff --git a/drivers/media/video/hdpvr/hdpvr-control.c b/drivers/media/video/hdpvr/hdpvr-control.c deleted file mode 100644 index ae8f229d1141..000000000000 --- a/drivers/media/video/hdpvr/hdpvr-control.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Hauppauge HD PVR USB driver - video 4 linux 2 interface - * - * Copyright (C) 2008 Janne Grunau (j@jannau.net) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/usb.h> -#include <linux/mutex.h> - -#include <linux/videodev2.h> - -#include <media/v4l2-common.h> - -#include "hdpvr.h" - - -int hdpvr_config_call(struct hdpvr_device *dev, uint value, u8 valbuf) -{ - int ret; - char request_type = 0x38, snd_request = 0x01; - - mutex_lock(&dev->usbc_mutex); - dev->usbc_buf[0] = valbuf; - ret = usb_control_msg(dev->udev, - usb_sndctrlpipe(dev->udev, 0), - snd_request, 0x00 | request_type, - value, CTRL_DEFAULT_INDEX, - dev->usbc_buf, 1, 10000); - - mutex_unlock(&dev->usbc_mutex); - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "config call request for value 0x%x returned %d\n", value, - ret); - - return ret < 0 ? ret : 0; -} - -struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev) -{ - struct hdpvr_video_info *vidinf = NULL; -#ifdef HDPVR_DEBUG - char print_buf[15]; -#endif - int ret; - - vidinf = kzalloc(sizeof(struct hdpvr_video_info), GFP_KERNEL); - if (!vidinf) { - v4l2_err(&dev->v4l2_dev, "out of memory\n"); - goto err; - } - - mutex_lock(&dev->usbc_mutex); - ret = usb_control_msg(dev->udev, - usb_rcvctrlpipe(dev->udev, 0), - 0x81, 0x80 | 0x38, - 0x1400, 0x0003, - dev->usbc_buf, 5, - 1000); - if (ret == 5) { - vidinf->width = dev->usbc_buf[1] << 8 | dev->usbc_buf[0]; - vidinf->height = dev->usbc_buf[3] << 8 | dev->usbc_buf[2]; - vidinf->fps = dev->usbc_buf[4]; - } - -#ifdef HDPVR_DEBUG - if (hdpvr_debug & MSG_INFO) { - hex_dump_to_buffer(dev->usbc_buf, 5, 16, 1, print_buf, - sizeof(print_buf), 0); - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "get video info returned: %d, %s\n", ret, print_buf); - } -#endif - mutex_unlock(&dev->usbc_mutex); - - if (!vidinf->width || !vidinf->height || !vidinf->fps) { - kfree(vidinf); - vidinf = NULL; - } -err: - return vidinf; -} - -int get_input_lines_info(struct hdpvr_device *dev) -{ -#ifdef HDPVR_DEBUG - char print_buf[9]; -#endif - int ret, lines; - - mutex_lock(&dev->usbc_mutex); - ret = usb_control_msg(dev->udev, - usb_rcvctrlpipe(dev->udev, 0), - 0x81, 0x80 | 0x38, - 0x1800, 0x0003, - dev->usbc_buf, 3, - 1000); - -#ifdef HDPVR_DEBUG - if (hdpvr_debug & MSG_INFO) { - hex_dump_to_buffer(dev->usbc_buf, 3, 16, 1, print_buf, - sizeof(print_buf), 0); - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "get input lines info returned: %d, %s\n", ret, - print_buf); - } -#else - (void)ret; /* suppress compiler warning */ -#endif - lines = dev->usbc_buf[1] << 8 | dev->usbc_buf[0]; - mutex_unlock(&dev->usbc_mutex); - return lines; -} - - -int hdpvr_set_bitrate(struct hdpvr_device *dev) -{ - int ret; - - mutex_lock(&dev->usbc_mutex); - memset(dev->usbc_buf, 0, 4); - dev->usbc_buf[0] = dev->options.bitrate; - dev->usbc_buf[2] = dev->options.peak_bitrate; - - ret = usb_control_msg(dev->udev, - usb_sndctrlpipe(dev->udev, 0), - 0x01, 0x38, CTRL_BITRATE_VALUE, - CTRL_DEFAULT_INDEX, dev->usbc_buf, 4, 1000); - mutex_unlock(&dev->usbc_mutex); - - return ret; -} - -int hdpvr_set_audio(struct hdpvr_device *dev, u8 input, - enum v4l2_mpeg_audio_encoding codec) -{ - int ret = 0; - - if (dev->flags & HDPVR_FLAG_AC3_CAP) { - mutex_lock(&dev->usbc_mutex); - memset(dev->usbc_buf, 0, 2); - dev->usbc_buf[0] = input; - if (codec == V4L2_MPEG_AUDIO_ENCODING_AAC) - dev->usbc_buf[1] = 0; - else if (codec == V4L2_MPEG_AUDIO_ENCODING_AC3) - dev->usbc_buf[1] = 1; - else { - mutex_unlock(&dev->usbc_mutex); - v4l2_err(&dev->v4l2_dev, "invalid audio codec %d\n", - codec); - ret = -EINVAL; - goto error; - } - - ret = usb_control_msg(dev->udev, - usb_sndctrlpipe(dev->udev, 0), - 0x01, 0x38, CTRL_AUDIO_INPUT_VALUE, - CTRL_DEFAULT_INDEX, dev->usbc_buf, 2, - 1000); - mutex_unlock(&dev->usbc_mutex); - if (ret == 2) - ret = 0; - } else - ret = hdpvr_config_call(dev, CTRL_AUDIO_INPUT_VALUE, input); -error: - return ret; -} - -int hdpvr_set_options(struct hdpvr_device *dev) -{ - hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, dev->options.video_std); - - hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, - dev->options.video_input+1); - - hdpvr_set_audio(dev, dev->options.audio_input+1, - dev->options.audio_codec); - - hdpvr_set_bitrate(dev); - hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, - dev->options.bitrate_mode); - hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, dev->options.gop_mode); - - hdpvr_config_call(dev, CTRL_BRIGHTNESS, dev->options.brightness); - hdpvr_config_call(dev, CTRL_CONTRAST, dev->options.contrast); - hdpvr_config_call(dev, CTRL_HUE, dev->options.hue); - hdpvr_config_call(dev, CTRL_SATURATION, dev->options.saturation); - hdpvr_config_call(dev, CTRL_SHARPNESS, dev->options.sharpness); - - return 0; -} diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c deleted file mode 100644 index 304f43ef59eb..000000000000 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Hauppauge HD PVR USB driver - * - * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2008 Janne Grunau (j@jannau.net) - * Copyright (C) 2008 John Poet - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/uaccess.h> -#include <linux/atomic.h> -#include <linux/usb.h> -#include <linux/mutex.h> -#include <linux/i2c.h> - -#include <linux/videodev2.h> -#include <media/v4l2-dev.h> -#include <media/v4l2-common.h> - -#include "hdpvr.h" - -static int video_nr[HDPVR_MAX] = {[0 ... (HDPVR_MAX - 1)] = UNSET}; -module_param_array(video_nr, int, NULL, 0); -MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)"); - -/* holds the number of currently registered devices */ -static atomic_t dev_nr = ATOMIC_INIT(-1); - -int hdpvr_debug; -module_param(hdpvr_debug, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(hdpvr_debug, "enable debugging output"); - -static uint default_video_input = HDPVR_VIDEO_INPUTS; -module_param(default_video_input, uint, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(default_video_input, "default video input: 0=Component / " - "1=S-Video / 2=Composite"); - -static uint default_audio_input = HDPVR_AUDIO_INPUTS; -module_param(default_audio_input, uint, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / " - "1=RCA front / 2=S/PDIF"); - -static bool boost_audio; -module_param(boost_audio, bool, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(boost_audio, "boost the audio signal"); - - -/* table of devices that work with this driver */ -static struct usb_device_id hdpvr_table[] = { - { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID) }, - { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID1) }, - { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID2) }, - { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID3) }, - { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID4) }, - { } /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(usb, hdpvr_table); - - -void hdpvr_delete(struct hdpvr_device *dev) -{ - hdpvr_free_buffers(dev); - - if (dev->video_dev) - video_device_release(dev->video_dev); - - usb_put_dev(dev->udev); -} - -static void challenge(u8 *bytes) -{ - u64 *i64P, tmp64; - uint i, idx; - - for (idx = 0; idx < 32; ++idx) { - - if (idx & 0x3) - bytes[(idx >> 3) + 3] = bytes[(idx >> 2) & 0x3]; - - switch (idx & 0x3) { - case 0x3: - bytes[2] += bytes[3] * 4 + bytes[4] + bytes[5]; - bytes[4] += bytes[(idx & 0x1) * 2] * 9 + 9; - break; - case 0x1: - bytes[0] *= 8; - bytes[0] += 7*idx + 4; - bytes[6] += bytes[3] * 3; - break; - case 0x0: - bytes[3 - (idx >> 3)] = bytes[idx >> 2]; - bytes[5] += bytes[6] * 3; - for (i = 0; i < 3; i++) - bytes[3] *= bytes[3] + 1; - break; - case 0x2: - for (i = 0; i < 3; i++) - bytes[1] *= bytes[6] + 1; - for (i = 0; i < 3; i++) { - i64P = (u64 *)bytes; - tmp64 = le64_to_cpup(i64P); - tmp64 <<= bytes[7] & 0x0f; - *i64P += cpu_to_le64(tmp64); - } - break; - } - } -} - -/* try to init the device like the windows driver */ -static int device_authorization(struct hdpvr_device *dev) -{ - - int ret, retval = -ENOMEM; - char request_type = 0x38, rcv_request = 0x81; - char *response; -#ifdef HDPVR_DEBUG - size_t buf_size = 46; - char *print_buf = kzalloc(5*buf_size+1, GFP_KERNEL); - if (!print_buf) { - v4l2_err(&dev->v4l2_dev, "Out of memory\n"); - return retval; - } -#endif - - mutex_lock(&dev->usbc_mutex); - ret = usb_control_msg(dev->udev, - usb_rcvctrlpipe(dev->udev, 0), - rcv_request, 0x80 | request_type, - 0x0400, 0x0003, - dev->usbc_buf, 46, - 10000); - if (ret != 46) { - v4l2_err(&dev->v4l2_dev, - "unexpected answer of status request, len %d\n", ret); - goto unlock; - } -#ifdef HDPVR_DEBUG - else { - hex_dump_to_buffer(dev->usbc_buf, 46, 16, 1, print_buf, - 5*buf_size+1, 0); - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "Status request returned, len %d: %s\n", - ret, print_buf); - } -#endif - - dev->fw_ver = dev->usbc_buf[1]; - - v4l2_info(&dev->v4l2_dev, "firmware version 0x%x dated %s\n", - dev->fw_ver, &dev->usbc_buf[2]); - - if (dev->fw_ver > 0x15) { - dev->options.brightness = 0x80; - dev->options.contrast = 0x40; - dev->options.hue = 0xf; - dev->options.saturation = 0x40; - dev->options.sharpness = 0x80; - } - - switch (dev->fw_ver) { - case HDPVR_FIRMWARE_VERSION: - dev->flags &= ~HDPVR_FLAG_AC3_CAP; - break; - case HDPVR_FIRMWARE_VERSION_AC3: - case HDPVR_FIRMWARE_VERSION_0X12: - case HDPVR_FIRMWARE_VERSION_0X15: - dev->flags |= HDPVR_FLAG_AC3_CAP; - break; - default: - v4l2_info(&dev->v4l2_dev, "untested firmware, the driver might" - " not work.\n"); - if (dev->fw_ver >= HDPVR_FIRMWARE_VERSION_AC3) - dev->flags |= HDPVR_FLAG_AC3_CAP; - else - dev->flags &= ~HDPVR_FLAG_AC3_CAP; - } - - response = dev->usbc_buf+38; -#ifdef HDPVR_DEBUG - hex_dump_to_buffer(response, 8, 16, 1, print_buf, 5*buf_size+1, 0); - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "challenge: %s\n", - print_buf); -#endif - challenge(response); -#ifdef HDPVR_DEBUG - hex_dump_to_buffer(response, 8, 16, 1, print_buf, 5*buf_size+1, 0); - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, " response: %s\n", - print_buf); -#endif - - msleep(100); - ret = usb_control_msg(dev->udev, - usb_sndctrlpipe(dev->udev, 0), - 0xd1, 0x00 | request_type, - 0x0000, 0x0000, - response, 8, - 10000); - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "magic request returned %d\n", ret); - - retval = ret != 8; -unlock: - mutex_unlock(&dev->usbc_mutex); - return retval; -} - -static int hdpvr_device_init(struct hdpvr_device *dev) -{ - int ret; - u8 *buf; - struct hdpvr_video_info *vidinf; - - if (device_authorization(dev)) - return -EACCES; - - /* default options for init */ - hdpvr_set_options(dev); - - /* set filter options */ - mutex_lock(&dev->usbc_mutex); - buf = dev->usbc_buf; - buf[0] = 0x03; buf[1] = 0x03; buf[2] = 0x00; buf[3] = 0x00; - ret = usb_control_msg(dev->udev, - usb_sndctrlpipe(dev->udev, 0), - 0x01, 0x38, - CTRL_LOW_PASS_FILTER_VALUE, CTRL_DEFAULT_INDEX, - buf, 4, - 1000); - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "control request returned %d\n", ret); - mutex_unlock(&dev->usbc_mutex); - - vidinf = get_video_info(dev); - if (!vidinf) - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "no valid video signal or device init failed\n"); - else - kfree(vidinf); - - /* enable fan and bling leds */ - mutex_lock(&dev->usbc_mutex); - buf[0] = 0x1; - ret = usb_control_msg(dev->udev, - usb_sndctrlpipe(dev->udev, 0), - 0xd4, 0x38, 0, 0, buf, 1, - 1000); - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "control request returned %d\n", ret); - - /* boost analog audio */ - buf[0] = boost_audio; - ret = usb_control_msg(dev->udev, - usb_sndctrlpipe(dev->udev, 0), - 0xd5, 0x38, 0, 0, buf, 1, - 1000); - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "control request returned %d\n", ret); - mutex_unlock(&dev->usbc_mutex); - - dev->status = STATUS_IDLE; - return 0; -} - -static const struct hdpvr_options hdpvr_default_options = { - .video_std = HDPVR_60HZ, - .video_input = HDPVR_COMPONENT, - .audio_input = HDPVR_RCA_BACK, - .bitrate = 65, /* 6 mbps */ - .peak_bitrate = 90, /* 9 mbps */ - .bitrate_mode = HDPVR_CONSTANT, - .gop_mode = HDPVR_SIMPLE_IDR_GOP, - .audio_codec = V4L2_MPEG_AUDIO_ENCODING_AAC, - /* original picture controls for firmware version <= 0x15 */ - /* updated in device_authorization() for newer firmware */ - .brightness = 0x86, - .contrast = 0x80, - .hue = 0x80, - .saturation = 0x80, - .sharpness = 0x80, -}; - -static int hdpvr_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct hdpvr_device *dev; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - struct i2c_client *client; - size_t buffer_size; - int i; - int retval = -ENOMEM; - - /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) { - dev_err(&interface->dev, "Out of memory\n"); - goto error; - } - - dev->workqueue = 0; - - /* register v4l2_device early so it can be used for printks */ - if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) { - dev_err(&interface->dev, "v4l2_device_register failed\n"); - goto error; - } - - mutex_init(&dev->io_mutex); - mutex_init(&dev->i2c_mutex); - mutex_init(&dev->usbc_mutex); - dev->usbc_buf = kmalloc(64, GFP_KERNEL); - if (!dev->usbc_buf) { - v4l2_err(&dev->v4l2_dev, "Out of memory\n"); - goto error; - } - - init_waitqueue_head(&dev->wait_buffer); - init_waitqueue_head(&dev->wait_data); - - dev->workqueue = create_singlethread_workqueue("hdpvr_buffer"); - if (!dev->workqueue) - goto error; - - /* init video transfer queues */ - INIT_LIST_HEAD(&dev->free_buff_list); - INIT_LIST_HEAD(&dev->rec_buff_list); - - dev->options = hdpvr_default_options; - - if (default_video_input < HDPVR_VIDEO_INPUTS) - dev->options.video_input = default_video_input; - - if (default_audio_input < HDPVR_AUDIO_INPUTS) { - dev->options.audio_input = default_audio_input; - if (default_audio_input == HDPVR_SPDIF) - dev->options.audio_codec = - V4L2_MPEG_AUDIO_ENCODING_AC3; - } - - dev->udev = usb_get_dev(interface_to_usbdev(interface)); - - /* set up the endpoint information */ - /* use only the first bulk-in and bulk-out endpoints */ - iface_desc = interface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - - if (!dev->bulk_in_endpointAddr && - usb_endpoint_is_bulk_in(endpoint)) { - /* USB interface description is buggy, reported max - * packet size is 512 bytes, windows driver uses 8192 */ - buffer_size = 8192; - dev->bulk_in_size = buffer_size; - dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; - } - - } - if (!dev->bulk_in_endpointAddr) { - v4l2_err(&dev->v4l2_dev, "Could not find bulk-in endpoint\n"); - goto error; - } - - /* init the device */ - if (hdpvr_device_init(dev)) { - v4l2_err(&dev->v4l2_dev, "device init failed\n"); - goto error; - } - - mutex_lock(&dev->io_mutex); - if (hdpvr_alloc_buffers(dev, NUM_BUFFERS)) { - mutex_unlock(&dev->io_mutex); - v4l2_err(&dev->v4l2_dev, - "allocating transfer buffers failed\n"); - goto error; - } - mutex_unlock(&dev->io_mutex); - - if (hdpvr_register_videodev(dev, &interface->dev, - video_nr[atomic_inc_return(&dev_nr)])) { - v4l2_err(&dev->v4l2_dev, "registering videodev failed\n"); - goto error; - } - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - retval = hdpvr_register_i2c_adapter(dev); - if (retval < 0) { - v4l2_err(&dev->v4l2_dev, "i2c adapter register failed\n"); - goto error; - } - - client = hdpvr_register_ir_rx_i2c(dev); - if (!client) { - v4l2_err(&dev->v4l2_dev, "i2c IR RX device register failed\n"); - goto reg_fail; - } - - client = hdpvr_register_ir_tx_i2c(dev); - if (!client) { - v4l2_err(&dev->v4l2_dev, "i2c IR TX device register failed\n"); - goto reg_fail; - } -#endif - - /* let the user know what node this device is now attached to */ - v4l2_info(&dev->v4l2_dev, "device now attached to %s\n", - video_device_node_name(dev->video_dev)); - return 0; - -reg_fail: -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_adapter(&dev->i2c_adapter); -#endif -error: - if (dev) { - /* Destroy single thread */ - if (dev->workqueue) - destroy_workqueue(dev->workqueue); - /* this frees allocated memory */ - hdpvr_delete(dev); - } - return retval; -} - -static void hdpvr_disconnect(struct usb_interface *interface) -{ - struct hdpvr_device *dev = to_hdpvr_dev(usb_get_intfdata(interface)); - - v4l2_info(&dev->v4l2_dev, "device %s disconnected\n", - video_device_node_name(dev->video_dev)); - /* prevent more I/O from starting and stop any ongoing */ - mutex_lock(&dev->io_mutex); - dev->status = STATUS_DISCONNECTED; - wake_up_interruptible(&dev->wait_data); - wake_up_interruptible(&dev->wait_buffer); - mutex_unlock(&dev->io_mutex); - v4l2_device_disconnect(&dev->v4l2_dev); - msleep(100); - flush_workqueue(dev->workqueue); - mutex_lock(&dev->io_mutex); - hdpvr_cancel_queue(dev); - mutex_unlock(&dev->io_mutex); -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_adapter(&dev->i2c_adapter); -#endif - video_unregister_device(dev->video_dev); - atomic_dec(&dev_nr); -} - - -static struct usb_driver hdpvr_usb_driver = { - .name = "hdpvr", - .probe = hdpvr_probe, - .disconnect = hdpvr_disconnect, - .id_table = hdpvr_table, -}; - -module_usb_driver(hdpvr_usb_driver); - -MODULE_LICENSE("GPL"); -MODULE_VERSION("0.2.1"); -MODULE_AUTHOR("Janne Grunau"); -MODULE_DESCRIPTION("Hauppauge HD PVR driver"); diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c deleted file mode 100644 index 82e819fa91c0..000000000000 --- a/drivers/media/video/hdpvr/hdpvr-i2c.c +++ /dev/null @@ -1,231 +0,0 @@ - -/* - * Hauppauge HD PVR USB driver - * - * Copyright (C) 2008 Janne Grunau (j@jannau.net) - * - * IR device registration code is - * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - -#include <linux/i2c.h> -#include <linux/slab.h> -#include <linux/export.h> - -#include "hdpvr.h" - -#define CTRL_READ_REQUEST 0xb8 -#define CTRL_WRITE_REQUEST 0x38 - -#define REQTYPE_I2C_READ 0xb1 -#define REQTYPE_I2C_WRITE 0xb0 -#define REQTYPE_I2C_WRITE_STATT 0xd0 - -#define Z8F0811_IR_TX_I2C_ADDR 0x70 -#define Z8F0811_IR_RX_I2C_ADDR 0x71 - - -struct i2c_client *hdpvr_register_ir_tx_i2c(struct hdpvr_device *dev) -{ - struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data; - struct i2c_board_info hdpvr_ir_tx_i2c_board_info = { - I2C_BOARD_INFO("ir_tx_z8f0811_hdpvr", Z8F0811_IR_TX_I2C_ADDR), - }; - - init_data->name = "HD-PVR"; - hdpvr_ir_tx_i2c_board_info.platform_data = init_data; - - return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_tx_i2c_board_info); -} - -struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev) -{ - struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data; - struct i2c_board_info hdpvr_ir_rx_i2c_board_info = { - I2C_BOARD_INFO("ir_rx_z8f0811_hdpvr", Z8F0811_IR_RX_I2C_ADDR), - }; - - /* Our default information for ir-kbd-i2c.c to use */ - init_data->ir_codes = RC_MAP_HAUPPAUGE; - init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; - init_data->type = RC_TYPE_RC5; - init_data->name = "HD-PVR"; - init_data->polling_interval = 405; /* ms, duplicated from Windows */ - hdpvr_ir_rx_i2c_board_info.platform_data = init_data; - - return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_rx_i2c_board_info); -} - -static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus, - unsigned char addr, char *wdata, int wlen, - char *data, int len) -{ - int ret; - - if ((len > sizeof(dev->i2c_buf)) || (wlen > sizeof(dev->i2c_buf))) - return -EINVAL; - - if (wlen) { - memcpy(&dev->i2c_buf, wdata, wlen); - ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), - REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST, - (bus << 8) | addr, 0, &dev->i2c_buf, - wlen, 1000); - if (ret < 0) - return ret; - } - - ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), - REQTYPE_I2C_READ, CTRL_READ_REQUEST, - (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000); - - if (ret == len) { - memcpy(data, &dev->i2c_buf, len); - ret = 0; - } else if (ret >= 0) - ret = -EIO; - - return ret; -} - -static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus, - unsigned char addr, char *data, int len) -{ - int ret; - - if (len > sizeof(dev->i2c_buf)) - return -EINVAL; - - memcpy(&dev->i2c_buf, data, len); - ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), - REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST, - (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000); - - if (ret < 0) - return ret; - - ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), - REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST, - 0, 0, &dev->i2c_buf, 2, 1000); - - if ((ret == 2) && (dev->i2c_buf[1] == (len - 1))) - ret = 0; - else if (ret >= 0) - ret = -EIO; - - return ret; -} - -static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs, - int num) -{ - struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter); - int retval = 0, addr; - - if (num <= 0) - return 0; - - mutex_lock(&dev->i2c_mutex); - - addr = msgs[0].addr << 1; - - if (num == 1) { - if (msgs[0].flags & I2C_M_RD) - retval = hdpvr_i2c_read(dev, 1, addr, NULL, 0, - msgs[0].buf, msgs[0].len); - else - retval = hdpvr_i2c_write(dev, 1, addr, msgs[0].buf, - msgs[0].len); - } else if (num == 2) { - if (msgs[0].addr != msgs[1].addr) { - v4l2_warn(&dev->v4l2_dev, "refusing 2-phase i2c xfer " - "with conflicting target addresses\n"); - retval = -EINVAL; - goto out; - } - - if ((msgs[0].flags & I2C_M_RD) || !(msgs[1].flags & I2C_M_RD)) { - v4l2_warn(&dev->v4l2_dev, "refusing complex xfer with " - "r0=%d, r1=%d\n", msgs[0].flags & I2C_M_RD, - msgs[1].flags & I2C_M_RD); - retval = -EINVAL; - goto out; - } - - /* - * Write followed by atomic read is the only complex xfer that - * we actually support here. - */ - retval = hdpvr_i2c_read(dev, 1, addr, msgs[0].buf, msgs[0].len, - msgs[1].buf, msgs[1].len); - } else { - v4l2_warn(&dev->v4l2_dev, "refusing %d-phase i2c xfer\n", num); - } - -out: - mutex_unlock(&dev->i2c_mutex); - - return retval ? retval : num; -} - -static u32 hdpvr_functionality(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static struct i2c_algorithm hdpvr_algo = { - .master_xfer = hdpvr_transfer, - .functionality = hdpvr_functionality, -}; - -static struct i2c_adapter hdpvr_i2c_adapter_template = { - .name = "Hauppage HD PVR I2C", - .owner = THIS_MODULE, - .algo = &hdpvr_algo, -}; - -static int hdpvr_activate_ir(struct hdpvr_device *dev) -{ - char buffer[2]; - - mutex_lock(&dev->i2c_mutex); - - hdpvr_i2c_read(dev, 0, 0x54, NULL, 0, buffer, 1); - - buffer[0] = 0; - buffer[1] = 0x8; - hdpvr_i2c_write(dev, 1, 0x54, buffer, 2); - - buffer[1] = 0x18; - hdpvr_i2c_write(dev, 1, 0x54, buffer, 2); - - mutex_unlock(&dev->i2c_mutex); - - return 0; -} - -int hdpvr_register_i2c_adapter(struct hdpvr_device *dev) -{ - int retval = -ENOMEM; - - hdpvr_activate_ir(dev); - - memcpy(&dev->i2c_adapter, &hdpvr_i2c_adapter_template, - sizeof(struct i2c_adapter)); - dev->i2c_adapter.dev.parent = &dev->udev->dev; - - i2c_set_adapdata(&dev->i2c_adapter, dev); - - retval = i2c_add_adapter(&dev->i2c_adapter); - - return retval; -} - -#endif diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c deleted file mode 100644 index 0e9e156bb2aa..000000000000 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ /dev/null @@ -1,1289 +0,0 @@ -/* - * Hauppauge HD PVR USB driver - video 4 linux 2 interface - * - * Copyright (C) 2008 Janne Grunau (j@jannau.net) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/uaccess.h> -#include <linux/usb.h> -#include <linux/mutex.h> -#include <linux/workqueue.h> - -#include <linux/videodev2.h> -#include <media/v4l2-dev.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include "hdpvr.h" - -#define BULK_URB_TIMEOUT 90 /* 0.09 seconds */ - -#define print_buffer_status() { \ - v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, \ - "%s:%d buffer stat: %d free, %d proc\n", \ - __func__, __LINE__, \ - list_size(&dev->free_buff_list), \ - list_size(&dev->rec_buff_list)); } - -struct hdpvr_fh { - struct hdpvr_device *dev; -}; - -static uint list_size(struct list_head *list) -{ - struct list_head *tmp; - uint count = 0; - - list_for_each(tmp, list) { - count++; - } - - return count; -} - -/*=========================================================================*/ -/* urb callback */ -static void hdpvr_read_bulk_callback(struct urb *urb) -{ - struct hdpvr_buffer *buf = (struct hdpvr_buffer *)urb->context; - struct hdpvr_device *dev = buf->dev; - - /* marking buffer as received and wake waiting */ - buf->status = BUFSTAT_READY; - wake_up_interruptible(&dev->wait_data); -} - -/*=========================================================================*/ -/* bufffer bits */ - -/* function expects dev->io_mutex to be hold by caller */ -int hdpvr_cancel_queue(struct hdpvr_device *dev) -{ - struct hdpvr_buffer *buf; - - list_for_each_entry(buf, &dev->rec_buff_list, buff_list) { - usb_kill_urb(buf->urb); - buf->status = BUFSTAT_AVAILABLE; - } - - list_splice_init(&dev->rec_buff_list, dev->free_buff_list.prev); - - return 0; -} - -static int hdpvr_free_queue(struct list_head *q) -{ - struct list_head *tmp; - struct list_head *p; - struct hdpvr_buffer *buf; - struct urb *urb; - - for (p = q->next; p != q;) { - buf = list_entry(p, struct hdpvr_buffer, buff_list); - - urb = buf->urb; - usb_free_coherent(urb->dev, urb->transfer_buffer_length, - urb->transfer_buffer, urb->transfer_dma); - usb_free_urb(urb); - tmp = p->next; - list_del(p); - kfree(buf); - p = tmp; - } - - return 0; -} - -/* function expects dev->io_mutex to be hold by caller */ -int hdpvr_free_buffers(struct hdpvr_device *dev) -{ - hdpvr_cancel_queue(dev); - - hdpvr_free_queue(&dev->free_buff_list); - hdpvr_free_queue(&dev->rec_buff_list); - - return 0; -} - -/* function expects dev->io_mutex to be hold by caller */ -int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count) -{ - uint i; - int retval = -ENOMEM; - u8 *mem; - struct hdpvr_buffer *buf; - struct urb *urb; - - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "allocating %u buffers\n", count); - - for (i = 0; i < count; i++) { - - buf = kzalloc(sizeof(struct hdpvr_buffer), GFP_KERNEL); - if (!buf) { - v4l2_err(&dev->v4l2_dev, "cannot allocate buffer\n"); - goto exit; - } - buf->dev = dev; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - v4l2_err(&dev->v4l2_dev, "cannot allocate urb\n"); - goto exit_urb; - } - buf->urb = urb; - - mem = usb_alloc_coherent(dev->udev, dev->bulk_in_size, GFP_KERNEL, - &urb->transfer_dma); - if (!mem) { - v4l2_err(&dev->v4l2_dev, - "cannot allocate usb transfer buffer\n"); - goto exit_urb_buffer; - } - - usb_fill_bulk_urb(buf->urb, dev->udev, - usb_rcvbulkpipe(dev->udev, - dev->bulk_in_endpointAddr), - mem, dev->bulk_in_size, - hdpvr_read_bulk_callback, buf); - - buf->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - buf->status = BUFSTAT_AVAILABLE; - list_add_tail(&buf->buff_list, &dev->free_buff_list); - } - return 0; -exit_urb_buffer: - usb_free_urb(urb); -exit_urb: - kfree(buf); -exit: - hdpvr_free_buffers(dev); - return retval; -} - -static int hdpvr_submit_buffers(struct hdpvr_device *dev) -{ - struct hdpvr_buffer *buf; - struct urb *urb; - int ret = 0, err_count = 0; - - mutex_lock(&dev->io_mutex); - - while (dev->status == STATUS_STREAMING && - !list_empty(&dev->free_buff_list)) { - - buf = list_entry(dev->free_buff_list.next, struct hdpvr_buffer, - buff_list); - if (buf->status != BUFSTAT_AVAILABLE) { - v4l2_err(&dev->v4l2_dev, - "buffer not marked as available\n"); - ret = -EFAULT; - goto err; - } - - urb = buf->urb; - urb->status = 0; - urb->actual_length = 0; - ret = usb_submit_urb(urb, GFP_KERNEL); - if (ret) { - v4l2_err(&dev->v4l2_dev, - "usb_submit_urb in %s returned %d\n", - __func__, ret); - if (++err_count > 2) - break; - continue; - } - buf->status = BUFSTAT_INPROGRESS; - list_move_tail(&buf->buff_list, &dev->rec_buff_list); - } -err: - print_buffer_status(); - mutex_unlock(&dev->io_mutex); - return ret; -} - -static struct hdpvr_buffer *hdpvr_get_next_buffer(struct hdpvr_device *dev) -{ - struct hdpvr_buffer *buf; - - mutex_lock(&dev->io_mutex); - - if (list_empty(&dev->rec_buff_list)) { - mutex_unlock(&dev->io_mutex); - return NULL; - } - - buf = list_entry(dev->rec_buff_list.next, struct hdpvr_buffer, - buff_list); - mutex_unlock(&dev->io_mutex); - - return buf; -} - -static void hdpvr_transmit_buffers(struct work_struct *work) -{ - struct hdpvr_device *dev = container_of(work, struct hdpvr_device, - worker); - - while (dev->status == STATUS_STREAMING) { - - if (hdpvr_submit_buffers(dev)) { - v4l2_err(&dev->v4l2_dev, "couldn't submit buffers\n"); - goto error; - } - if (wait_event_interruptible(dev->wait_buffer, - !list_empty(&dev->free_buff_list) || - dev->status != STATUS_STREAMING)) - goto error; - } - - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "transmit worker exited\n"); - return; -error: - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "transmit buffers errored\n"); - dev->status = STATUS_ERROR; -} - -/* function expects dev->io_mutex to be hold by caller */ -static int hdpvr_start_streaming(struct hdpvr_device *dev) -{ - int ret; - struct hdpvr_video_info *vidinf; - - if (dev->status == STATUS_STREAMING) - return 0; - else if (dev->status != STATUS_IDLE) - return -EAGAIN; - - vidinf = get_video_info(dev); - - if (vidinf) { - v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, - "video signal: %dx%d@%dhz\n", vidinf->width, - vidinf->height, vidinf->fps); - kfree(vidinf); - - /* start streaming 2 request */ - ret = usb_control_msg(dev->udev, - usb_sndctrlpipe(dev->udev, 0), - 0xb8, 0x38, 0x1, 0, NULL, 0, 8000); - v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, - "encoder start control request returned %d\n", ret); - - hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00); - - dev->status = STATUS_STREAMING; - - INIT_WORK(&dev->worker, hdpvr_transmit_buffers); - queue_work(dev->workqueue, &dev->worker); - - v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, - "streaming started\n"); - - return 0; - } - msleep(250); - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "no video signal at input %d\n", dev->options.video_input); - return -EAGAIN; -} - - -/* function expects dev->io_mutex to be hold by caller */ -static int hdpvr_stop_streaming(struct hdpvr_device *dev) -{ - int actual_length; - uint c = 0; - u8 *buf; - - if (dev->status == STATUS_IDLE) - return 0; - else if (dev->status != STATUS_STREAMING) - return -EAGAIN; - - buf = kmalloc(dev->bulk_in_size, GFP_KERNEL); - if (!buf) - v4l2_err(&dev->v4l2_dev, "failed to allocate temporary buffer " - "for emptying the internal device buffer. " - "Next capture start will be slow\n"); - - dev->status = STATUS_SHUTTING_DOWN; - hdpvr_config_call(dev, CTRL_STOP_STREAMING_VALUE, 0x00); - mutex_unlock(&dev->io_mutex); - - wake_up_interruptible(&dev->wait_buffer); - msleep(50); - - flush_workqueue(dev->workqueue); - - mutex_lock(&dev->io_mutex); - /* kill the still outstanding urbs */ - hdpvr_cancel_queue(dev); - - /* emptying the device buffer beforeshutting it down */ - while (buf && ++c < 500 && - !usb_bulk_msg(dev->udev, - usb_rcvbulkpipe(dev->udev, - dev->bulk_in_endpointAddr), - buf, dev->bulk_in_size, &actual_length, - BULK_URB_TIMEOUT)) { - v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, - "%2d: got %d bytes\n", c, actual_length); - } - kfree(buf); - v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, - "used %d urbs to empty device buffers\n", c-1); - msleep(10); - - dev->status = STATUS_IDLE; - - return 0; -} - - -/*=======================================================================*/ -/* - * video 4 linux 2 file operations - */ - -static int hdpvr_open(struct file *file) -{ - struct hdpvr_device *dev; - struct hdpvr_fh *fh; - int retval = -ENOMEM; - - dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file)); - if (!dev) { - pr_err("open failing with with ENODEV\n"); - retval = -ENODEV; - goto err; - } - - fh = kzalloc(sizeof(struct hdpvr_fh), GFP_KERNEL); - if (!fh) { - v4l2_err(&dev->v4l2_dev, "Out of memory\n"); - goto err; - } - /* lock the device to allow correctly handling errors - * in resumption */ - mutex_lock(&dev->io_mutex); - dev->open_count++; - mutex_unlock(&dev->io_mutex); - - fh->dev = dev; - - /* save our object in the file's private structure */ - file->private_data = fh; - - retval = 0; -err: - return retval; -} - -static int hdpvr_release(struct file *file) -{ - struct hdpvr_fh *fh = file->private_data; - struct hdpvr_device *dev = fh->dev; - - if (!dev) - return -ENODEV; - - mutex_lock(&dev->io_mutex); - if (!(--dev->open_count) && dev->status == STATUS_STREAMING) - hdpvr_stop_streaming(dev); - - mutex_unlock(&dev->io_mutex); - - return 0; -} - -/* - * hdpvr_v4l2_read() - * will allocate buffers when called for the first time - */ -static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, - loff_t *pos) -{ - struct hdpvr_fh *fh = file->private_data; - struct hdpvr_device *dev = fh->dev; - struct hdpvr_buffer *buf = NULL; - struct urb *urb; - unsigned int ret = 0; - int rem, cnt; - - if (*pos) - return -ESPIPE; - - if (!dev) - return -ENODEV; - - mutex_lock(&dev->io_mutex); - if (dev->status == STATUS_IDLE) { - if (hdpvr_start_streaming(dev)) { - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "start_streaming failed\n"); - ret = -EIO; - msleep(200); - dev->status = STATUS_IDLE; - mutex_unlock(&dev->io_mutex); - goto err; - } - print_buffer_status(); - } - mutex_unlock(&dev->io_mutex); - - /* wait for the first buffer */ - if (!(file->f_flags & O_NONBLOCK)) { - if (wait_event_interruptible(dev->wait_data, - hdpvr_get_next_buffer(dev))) - return -ERESTARTSYS; - } - - buf = hdpvr_get_next_buffer(dev); - - while (count > 0 && buf) { - - if (buf->status != BUFSTAT_READY && - dev->status != STATUS_DISCONNECTED) { - /* return nonblocking */ - if (file->f_flags & O_NONBLOCK) { - if (!ret) - ret = -EAGAIN; - goto err; - } - - if (wait_event_interruptible(dev->wait_data, - buf->status == BUFSTAT_READY)) { - ret = -ERESTARTSYS; - goto err; - } - } - - if (buf->status != BUFSTAT_READY) - break; - - /* set remaining bytes to copy */ - urb = buf->urb; - rem = urb->actual_length - buf->pos; - cnt = rem > count ? count : rem; - - if (copy_to_user(buffer, urb->transfer_buffer + buf->pos, - cnt)) { - v4l2_err(&dev->v4l2_dev, "read: copy_to_user failed\n"); - if (!ret) - ret = -EFAULT; - goto err; - } - - buf->pos += cnt; - count -= cnt; - buffer += cnt; - ret += cnt; - - /* finished, take next buffer */ - if (buf->pos == urb->actual_length) { - mutex_lock(&dev->io_mutex); - buf->pos = 0; - buf->status = BUFSTAT_AVAILABLE; - - list_move_tail(&buf->buff_list, &dev->free_buff_list); - - print_buffer_status(); - - mutex_unlock(&dev->io_mutex); - - wake_up_interruptible(&dev->wait_buffer); - - buf = hdpvr_get_next_buffer(dev); - } - } -err: - if (!ret && !buf) - ret = -EAGAIN; - return ret; -} - -static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) -{ - struct hdpvr_buffer *buf = NULL; - struct hdpvr_fh *fh = filp->private_data; - struct hdpvr_device *dev = fh->dev; - unsigned int mask = 0; - - mutex_lock(&dev->io_mutex); - - if (!video_is_registered(dev->video_dev)) { - mutex_unlock(&dev->io_mutex); - return -EIO; - } - - if (dev->status == STATUS_IDLE) { - if (hdpvr_start_streaming(dev)) { - v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, - "start_streaming failed\n"); - dev->status = STATUS_IDLE; - } - - print_buffer_status(); - } - mutex_unlock(&dev->io_mutex); - - buf = hdpvr_get_next_buffer(dev); - /* only wait if no data is available */ - if (!buf || buf->status != BUFSTAT_READY) { - poll_wait(filp, &dev->wait_data, wait); - buf = hdpvr_get_next_buffer(dev); - } - if (buf && buf->status == BUFSTAT_READY) - mask |= POLLIN | POLLRDNORM; - - return mask; -} - - -static const struct v4l2_file_operations hdpvr_fops = { - .owner = THIS_MODULE, - .open = hdpvr_open, - .release = hdpvr_release, - .read = hdpvr_read, - .poll = hdpvr_poll, - .unlocked_ioctl = video_ioctl2, -}; - -/*=======================================================================*/ -/* - * V4L2 ioctl handling - */ - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct hdpvr_device *dev = video_drvdata(file); - - strcpy(cap->driver, "hdpvr"); - strcpy(cap->card, "Hauppauge HD PVR"); - usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_AUDIO | - V4L2_CAP_READWRITE; - return 0; -} - -static int vidioc_s_std(struct file *file, void *private_data, - v4l2_std_id *std) -{ - struct hdpvr_fh *fh = file->private_data; - struct hdpvr_device *dev = fh->dev; - u8 std_type = 1; - - if (*std & (V4L2_STD_NTSC | V4L2_STD_PAL_60)) - std_type = 0; - - return hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, std_type); -} - -static const char *iname[] = { - [HDPVR_COMPONENT] = "Component", - [HDPVR_SVIDEO] = "S-Video", - [HDPVR_COMPOSITE] = "Composite", -}; - -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *i) -{ - struct hdpvr_fh *fh = file->private_data; - struct hdpvr_device *dev = fh->dev; - unsigned int n; - - n = i->index; - if (n >= HDPVR_VIDEO_INPUTS) - return -EINVAL; - - i->type = V4L2_INPUT_TYPE_CAMERA; - - strncpy(i->name, iname[n], sizeof(i->name) - 1); - i->name[sizeof(i->name) - 1] = '\0'; - - i->audioset = 1<<HDPVR_RCA_FRONT | 1<<HDPVR_RCA_BACK | 1<<HDPVR_SPDIF; - - i->std = dev->video_dev->tvnorms; - - return 0; -} - -static int vidioc_s_input(struct file *file, void *private_data, - unsigned int index) -{ - struct hdpvr_fh *fh = file->private_data; - struct hdpvr_device *dev = fh->dev; - int retval; - - if (index >= HDPVR_VIDEO_INPUTS) - return -EINVAL; - - if (dev->status != STATUS_IDLE) - return -EAGAIN; - - retval = hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, index+1); - if (!retval) - dev->options.video_input = index; - - return retval; -} - -static int vidioc_g_input(struct file *file, void *private_data, - unsigned int *index) -{ - struct hdpvr_fh *fh = file->private_data; - struct hdpvr_device *dev = fh->dev; - - *index = dev->options.video_input; - return 0; -} - - -static const char *audio_iname[] = { - [HDPVR_RCA_FRONT] = "RCA front", - [HDPVR_RCA_BACK] = "RCA back", - [HDPVR_SPDIF] = "SPDIF", -}; - -static int vidioc_enumaudio(struct file *file, void *priv, - struct v4l2_audio *audio) -{ - unsigned int n; - - n = audio->index; - if (n >= HDPVR_AUDIO_INPUTS) - return -EINVAL; - - audio->capability = V4L2_AUDCAP_STEREO; - - strncpy(audio->name, audio_iname[n], sizeof(audio->name) - 1); - audio->name[sizeof(audio->name) - 1] = '\0'; - - return 0; -} - -static int vidioc_s_audio(struct file *file, void *private_data, - struct v4l2_audio *audio) -{ - struct hdpvr_fh *fh = file->private_data; - struct hdpvr_device *dev = fh->dev; - int retval; - - if (audio->index >= HDPVR_AUDIO_INPUTS) - return -EINVAL; - - if (dev->status != STATUS_IDLE) - return -EAGAIN; - - retval = hdpvr_set_audio(dev, audio->index+1, dev->options.audio_codec); - if (!retval) - dev->options.audio_input = audio->index; - - return retval; -} - -static int vidioc_g_audio(struct file *file, void *private_data, - struct v4l2_audio *audio) -{ - struct hdpvr_fh *fh = file->private_data; - struct hdpvr_device *dev = fh->dev; - - audio->index = dev->options.audio_input; - audio->capability = V4L2_AUDCAP_STEREO; - strncpy(audio->name, audio_iname[audio->index], sizeof(audio->name)); - audio->name[sizeof(audio->name) - 1] = '\0'; - return 0; -} - -static const s32 supported_v4l2_ctrls[] = { - V4L2_CID_BRIGHTNESS, - V4L2_CID_CONTRAST, - V4L2_CID_SATURATION, - V4L2_CID_HUE, - V4L2_CID_SHARPNESS, - V4L2_CID_MPEG_AUDIO_ENCODING, - V4L2_CID_MPEG_VIDEO_ENCODING, - V4L2_CID_MPEG_VIDEO_BITRATE_MODE, - V4L2_CID_MPEG_VIDEO_BITRATE, - V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, -}; - -static int fill_queryctrl(struct hdpvr_options *opt, struct v4l2_queryctrl *qc, - int ac3, int fw_ver) -{ - int err; - - if (fw_ver > 0x15) { - switch (qc->id) { - case V4L2_CID_BRIGHTNESS: - return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); - case V4L2_CID_CONTRAST: - return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x40); - case V4L2_CID_SATURATION: - return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x40); - case V4L2_CID_HUE: - return v4l2_ctrl_query_fill(qc, 0x0, 0x1e, 1, 0xf); - case V4L2_CID_SHARPNESS: - return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); - } - } else { - switch (qc->id) { - case V4L2_CID_BRIGHTNESS: - return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x86); - case V4L2_CID_CONTRAST: - return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); - case V4L2_CID_SATURATION: - return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); - case V4L2_CID_HUE: - return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); - case V4L2_CID_SHARPNESS: - return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); - } - } - - switch (qc->id) { - case V4L2_CID_MPEG_AUDIO_ENCODING: - return v4l2_ctrl_query_fill( - qc, V4L2_MPEG_AUDIO_ENCODING_AAC, - ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 - : V4L2_MPEG_AUDIO_ENCODING_AAC, - 1, V4L2_MPEG_AUDIO_ENCODING_AAC); - case V4L2_CID_MPEG_VIDEO_ENCODING: - return v4l2_ctrl_query_fill( - qc, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, - V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1, - V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC); - -/* case V4L2_CID_MPEG_VIDEO_? maybe keyframe interval: */ -/* return v4l2_ctrl_query_fill(qc, 0, 128, 128, 0); */ - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - return v4l2_ctrl_query_fill( - qc, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, - V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, - V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); - - case V4L2_CID_MPEG_VIDEO_BITRATE: - return v4l2_ctrl_query_fill(qc, 1000000, 13500000, 100000, - 6500000); - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - err = v4l2_ctrl_query_fill(qc, 1100000, 20200000, 100000, - 9000000); - if (!err && opt->bitrate_mode == HDPVR_CONSTANT) - qc->flags |= V4L2_CTRL_FLAG_INACTIVE; - return err; - default: - return -EINVAL; - } -} - -static int vidioc_queryctrl(struct file *file, void *private_data, - struct v4l2_queryctrl *qc) -{ - struct hdpvr_fh *fh = file->private_data; - struct hdpvr_device *dev = fh->dev; - int i, next; - u32 id = qc->id; - - memset(qc, 0, sizeof(*qc)); - - next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL); - qc->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL; - - for (i = 0; i < ARRAY_SIZE(supported_v4l2_ctrls); i++) { - if (next) { - if (qc->id < supported_v4l2_ctrls[i]) - qc->id = supported_v4l2_ctrls[i]; - else - continue; - } - - if (qc->id == supported_v4l2_ctrls[i]) - return fill_queryctrl(&dev->options, qc, - dev->flags & HDPVR_FLAG_AC3_CAP, - dev->fw_ver); - - if (qc->id < supported_v4l2_ctrls[i]) - break; - } - - return -EINVAL; -} - -static int vidioc_g_ctrl(struct file *file, void *private_data, - struct v4l2_control *ctrl) -{ - struct hdpvr_fh *fh = file->private_data; - struct hdpvr_device *dev = fh->dev; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ctrl->value = dev->options.brightness; - break; - case V4L2_CID_CONTRAST: - ctrl->value = dev->options.contrast; - break; - case V4L2_CID_SATURATION: - ctrl->value = dev->options.saturation; - break; - case V4L2_CID_HUE: - ctrl->value = dev->options.hue; - break; - case V4L2_CID_SHARPNESS: - ctrl->value = dev->options.sharpness; - break; - default: - return -EINVAL; - } - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *private_data, - struct v4l2_control *ctrl) -{ - struct hdpvr_fh *fh = file->private_data; - struct hdpvr_device *dev = fh->dev; - int retval; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - retval = hdpvr_config_call(dev, CTRL_BRIGHTNESS, ctrl->value); - if (!retval) - dev->options.brightness = ctrl->value; - break; - case V4L2_CID_CONTRAST: - retval = hdpvr_config_call(dev, CTRL_CONTRAST, ctrl->value); - if (!retval) - dev->options.contrast = ctrl->value; - break; - case V4L2_CID_SATURATION: - retval = hdpvr_config_call(dev, CTRL_SATURATION, ctrl->value); - if (!retval) - dev->options.saturation = ctrl->value; - break; - case V4L2_CID_HUE: - retval = hdpvr_config_call(dev, CTRL_HUE, ctrl->value); - if (!retval) - dev->options.hue = ctrl->value; - break; - case V4L2_CID_SHARPNESS: - retval = hdpvr_config_call(dev, CTRL_SHARPNESS, ctrl->value); - if (!retval) - dev->options.sharpness = ctrl->value; - break; - default: - return -EINVAL; - } - - return retval; -} - - -static int hdpvr_get_ctrl(struct hdpvr_options *opt, - struct v4l2_ext_control *ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_MPEG_AUDIO_ENCODING: - ctrl->value = opt->audio_codec; - break; - case V4L2_CID_MPEG_VIDEO_ENCODING: - ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC; - break; -/* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ -/* ctrl->value = (opt->gop_mode & 0x2) ? 0 : 128; */ -/* break; */ - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - ctrl->value = opt->bitrate_mode == HDPVR_CONSTANT - ? V4L2_MPEG_VIDEO_BITRATE_MODE_CBR - : V4L2_MPEG_VIDEO_BITRATE_MODE_VBR; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE: - ctrl->value = opt->bitrate * 100000; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - ctrl->value = opt->peak_bitrate * 100000; - break; - case V4L2_CID_MPEG_STREAM_TYPE: - ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; - break; - default: - return -EINVAL; - } - return 0; -} - -static int vidioc_g_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *ctrls) -{ - struct hdpvr_fh *fh = file->private_data; - struct hdpvr_device *dev = fh->dev; - int i, err = 0; - - if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { - for (i = 0; i < ctrls->count; i++) { - struct v4l2_ext_control *ctrl = ctrls->controls + i; - - err = hdpvr_get_ctrl(&dev->options, ctrl); - if (err) { - ctrls->error_idx = i; - break; - } - } - return err; - - } - - return -EINVAL; -} - - -static int hdpvr_try_ctrl(struct v4l2_ext_control *ctrl, int ac3) -{ - int ret = -EINVAL; - - switch (ctrl->id) { - case V4L2_CID_MPEG_AUDIO_ENCODING: - if (ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AAC || - (ac3 && ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AC3)) - ret = 0; - break; - case V4L2_CID_MPEG_VIDEO_ENCODING: - if (ctrl->value == V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC) - ret = 0; - break; -/* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ -/* if (ctrl->value == 0 || ctrl->value == 128) */ -/* ret = 0; */ -/* break; */ - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR || - ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) - ret = 0; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE: - { - uint bitrate = ctrl->value / 100000; - if (bitrate >= 10 && bitrate <= 135) - ret = 0; - break; - } - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - { - uint peak_bitrate = ctrl->value / 100000; - if (peak_bitrate >= 10 && peak_bitrate <= 202) - ret = 0; - break; - } - case V4L2_CID_MPEG_STREAM_TYPE: - if (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS) - ret = 0; - break; - default: - return -EINVAL; - } - return ret; -} - -static int vidioc_try_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *ctrls) -{ - struct hdpvr_fh *fh = file->private_data; - struct hdpvr_device *dev = fh->dev; - int i, err = 0; - - if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { - for (i = 0; i < ctrls->count; i++) { - struct v4l2_ext_control *ctrl = ctrls->controls + i; - - err = hdpvr_try_ctrl(ctrl, - dev->flags & HDPVR_FLAG_AC3_CAP); - if (err) { - ctrls->error_idx = i; - break; - } - } - return err; - } - - return -EINVAL; -} - - -static int hdpvr_set_ctrl(struct hdpvr_device *dev, - struct v4l2_ext_control *ctrl) -{ - struct hdpvr_options *opt = &dev->options; - int ret = 0; - - switch (ctrl->id) { - case V4L2_CID_MPEG_AUDIO_ENCODING: - if (dev->flags & HDPVR_FLAG_AC3_CAP) { - opt->audio_codec = ctrl->value; - ret = hdpvr_set_audio(dev, opt->audio_input, - opt->audio_codec); - } - break; - case V4L2_CID_MPEG_VIDEO_ENCODING: - break; -/* case V4L2_CID_MPEG_VIDEO_B_FRAMES: */ -/* if (ctrl->value == 0 && !(opt->gop_mode & 0x2)) { */ -/* opt->gop_mode |= 0x2; */ -/* hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, */ -/* opt->gop_mode); */ -/* } */ -/* if (ctrl->value == 128 && opt->gop_mode & 0x2) { */ -/* opt->gop_mode &= ~0x2; */ -/* hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, */ -/* opt->gop_mode); */ -/* } */ -/* break; */ - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR && - opt->bitrate_mode != HDPVR_CONSTANT) { - opt->bitrate_mode = HDPVR_CONSTANT; - hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, - opt->bitrate_mode); - } - if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && - opt->bitrate_mode == HDPVR_CONSTANT) { - opt->bitrate_mode = HDPVR_VARIABLE_AVERAGE; - hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, - opt->bitrate_mode); - } - break; - case V4L2_CID_MPEG_VIDEO_BITRATE: { - uint bitrate = ctrl->value / 100000; - - opt->bitrate = bitrate; - if (bitrate >= opt->peak_bitrate) - opt->peak_bitrate = bitrate+1; - - hdpvr_set_bitrate(dev); - break; - } - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: { - uint peak_bitrate = ctrl->value / 100000; - - if (opt->bitrate_mode == HDPVR_CONSTANT) - break; - - if (opt->bitrate < peak_bitrate) { - opt->peak_bitrate = peak_bitrate; - hdpvr_set_bitrate(dev); - } else - ret = -EINVAL; - break; - } - case V4L2_CID_MPEG_STREAM_TYPE: - break; - default: - return -EINVAL; - } - return ret; -} - -static int vidioc_s_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *ctrls) -{ - struct hdpvr_fh *fh = file->private_data; - struct hdpvr_device *dev = fh->dev; - int i, err = 0; - - if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) { - for (i = 0; i < ctrls->count; i++) { - struct v4l2_ext_control *ctrl = ctrls->controls + i; - - err = hdpvr_try_ctrl(ctrl, - dev->flags & HDPVR_FLAG_AC3_CAP); - if (err) { - ctrls->error_idx = i; - break; - } - err = hdpvr_set_ctrl(dev, ctrl); - if (err) { - ctrls->error_idx = i; - break; - } - } - return err; - - } - - return -EINVAL; -} - -static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data, - struct v4l2_fmtdesc *f) -{ - - if (f->index != 0 || f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - f->flags = V4L2_FMT_FLAG_COMPRESSED; - strncpy(f->description, "MPEG2-TS with AVC/AAC streams", 32); - f->pixelformat = V4L2_PIX_FMT_MPEG; - - return 0; -} - -static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data, - struct v4l2_format *f) -{ - struct hdpvr_fh *fh = file->private_data; - struct hdpvr_device *dev = fh->dev; - struct hdpvr_video_info *vid_info; - - if (!dev) - return -ENODEV; - - vid_info = get_video_info(dev); - if (!vid_info) - return -EFAULT; - - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.width = vid_info->width; - f->fmt.pix.height = vid_info->height; - f->fmt.pix.sizeimage = dev->bulk_in_size; - f->fmt.pix.colorspace = 0; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.field = V4L2_FIELD_ANY; - - kfree(vid_info); - return 0; -} - -static int vidioc_encoder_cmd(struct file *filp, void *priv, - struct v4l2_encoder_cmd *a) -{ - struct hdpvr_fh *fh = filp->private_data; - struct hdpvr_device *dev = fh->dev; - int res; - - mutex_lock(&dev->io_mutex); - - memset(&a->raw, 0, sizeof(a->raw)); - switch (a->cmd) { - case V4L2_ENC_CMD_START: - a->flags = 0; - res = hdpvr_start_streaming(dev); - break; - case V4L2_ENC_CMD_STOP: - res = hdpvr_stop_streaming(dev); - break; - default: - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "Unsupported encoder cmd %d\n", a->cmd); - res = -EINVAL; - } - mutex_unlock(&dev->io_mutex); - return res; -} - -static int vidioc_try_encoder_cmd(struct file *filp, void *priv, - struct v4l2_encoder_cmd *a) -{ - switch (a->cmd) { - case V4L2_ENC_CMD_START: - case V4L2_ENC_CMD_STOP: - return 0; - default: - return -EINVAL; - } -} - -static const struct v4l2_ioctl_ops hdpvr_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .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_enumaudio = vidioc_enumaudio, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, - .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, - .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_encoder_cmd = vidioc_encoder_cmd, - .vidioc_try_encoder_cmd = vidioc_try_encoder_cmd, -}; - -static void hdpvr_device_release(struct video_device *vdev) -{ - struct hdpvr_device *dev = video_get_drvdata(vdev); - - hdpvr_delete(dev); - mutex_lock(&dev->io_mutex); - destroy_workqueue(dev->workqueue); - mutex_unlock(&dev->io_mutex); - - v4l2_device_unregister(&dev->v4l2_dev); - - /* deregister I2C adapter */ -#if defined(CONFIG_I2C) || (CONFIG_I2C_MODULE) - mutex_lock(&dev->i2c_mutex); - i2c_del_adapter(&dev->i2c_adapter); - mutex_unlock(&dev->i2c_mutex); -#endif /* CONFIG_I2C */ - - kfree(dev->usbc_buf); - kfree(dev); -} - -static const struct video_device hdpvr_video_template = { -/* .type = VFL_TYPE_GRABBER, */ -/* .type2 = VID_TYPE_CAPTURE | VID_TYPE_MPEG_ENCODER, */ - .fops = &hdpvr_fops, - .release = hdpvr_device_release, - .ioctl_ops = &hdpvr_ioctl_ops, - .tvnorms = - V4L2_STD_NTSC | V4L2_STD_SECAM | V4L2_STD_PAL_B | - V4L2_STD_PAL_G | V4L2_STD_PAL_H | V4L2_STD_PAL_I | - V4L2_STD_PAL_D | V4L2_STD_PAL_M | V4L2_STD_PAL_N | - V4L2_STD_PAL_60, - .current_norm = V4L2_STD_NTSC | V4L2_STD_PAL_M | - V4L2_STD_PAL_60, -}; - -int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, - int devnum) -{ - /* setup and register video device */ - dev->video_dev = video_device_alloc(); - if (!dev->video_dev) { - v4l2_err(&dev->v4l2_dev, "video_device_alloc() failed\n"); - goto error; - } - - *(dev->video_dev) = hdpvr_video_template; - strcpy(dev->video_dev->name, "Hauppauge HD PVR"); - dev->video_dev->parent = parent; - video_set_drvdata(dev->video_dev, dev); - - if (video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum)) { - v4l2_err(&dev->v4l2_dev, "video_device registration failed\n"); - goto error; - } - - return 0; -error: - return -ENOMEM; -} diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h deleted file mode 100644 index fea3c6926997..000000000000 --- a/drivers/media/video/hdpvr/hdpvr.h +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Hauppauge HD PVR USB driver - * - * Copyright (C) 2008 Janne Grunau (j@jannau.net) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#include <linux/usb.h> -#include <linux/i2c.h> -#include <linux/mutex.h> -#include <linux/workqueue.h> -#include <linux/videodev2.h> - -#include <media/v4l2-device.h> -#include <media/ir-kbd-i2c.h> - -#define HDPVR_MAX 8 -#define HDPVR_I2C_MAX_SIZE 128 - -/* Define these values to match your devices */ -#define HD_PVR_VENDOR_ID 0x2040 -#define HD_PVR_PRODUCT_ID 0x4900 -#define HD_PVR_PRODUCT_ID1 0x4901 -#define HD_PVR_PRODUCT_ID2 0x4902 -#define HD_PVR_PRODUCT_ID4 0x4903 -#define HD_PVR_PRODUCT_ID3 0x4982 - -#define UNSET (-1U) - -#define NUM_BUFFERS 64 - -#define HDPVR_FIRMWARE_VERSION 0x08 -#define HDPVR_FIRMWARE_VERSION_AC3 0x0d -#define HDPVR_FIRMWARE_VERSION_0X12 0x12 -#define HDPVR_FIRMWARE_VERSION_0X15 0x15 - -/* #define HDPVR_DEBUG */ - -extern int hdpvr_debug; - -#define MSG_INFO 1 -#define MSG_BUFFER 2 - -struct hdpvr_options { - u8 video_std; - u8 video_input; - u8 audio_input; - u8 bitrate; /* in 100kbps */ - u8 peak_bitrate; /* in 100kbps */ - u8 bitrate_mode; - u8 gop_mode; - enum v4l2_mpeg_audio_encoding audio_codec; - u8 brightness; - u8 contrast; - u8 hue; - u8 saturation; - u8 sharpness; -}; - -/* Structure to hold all of our device specific stuff */ -struct hdpvr_device { - /* the v4l device for this device */ - struct video_device *video_dev; - /* the usb device for this device */ - struct usb_device *udev; - /* v4l2-device unused */ - struct v4l2_device v4l2_dev; - - /* the max packet size of the bulk endpoint */ - size_t bulk_in_size; - /* the address of the bulk in endpoint */ - __u8 bulk_in_endpointAddr; - - /* holds the current device status */ - __u8 status; - /* count the number of openers */ - uint open_count; - - /* holds the cureent set options */ - struct hdpvr_options options; - - uint flags; - - /* synchronize I/O */ - struct mutex io_mutex; - /* available buffers */ - struct list_head free_buff_list; - /* in progress buffers */ - struct list_head rec_buff_list; - /* waitqueue for buffers */ - wait_queue_head_t wait_buffer; - /* waitqueue for data */ - wait_queue_head_t wait_data; - /**/ - struct workqueue_struct *workqueue; - /**/ - struct work_struct worker; - - /* I2C adapter */ - struct i2c_adapter i2c_adapter; - /* I2C lock */ - struct mutex i2c_mutex; - /* I2C message buffer space */ - char i2c_buf[HDPVR_I2C_MAX_SIZE]; - - /* For passing data to ir-kbd-i2c */ - struct IR_i2c_init_data ir_i2c_init_data; - - /* usb control transfer buffer and lock */ - struct mutex usbc_mutex; - u8 *usbc_buf; - u8 fw_ver; -}; - -static inline struct hdpvr_device *to_hdpvr_dev(struct v4l2_device *v4l2_dev) -{ - return container_of(v4l2_dev, struct hdpvr_device, v4l2_dev); -} - - -/* buffer one bulk urb of data */ -struct hdpvr_buffer { - struct list_head buff_list; - - struct urb *urb; - - struct hdpvr_device *dev; - - uint pos; - - __u8 status; -}; - -/* */ - -struct hdpvr_video_info { - u16 width; - u16 height; - u8 fps; -}; - -enum { - STATUS_UNINITIALIZED = 0, - STATUS_IDLE, - STATUS_STARTING, - STATUS_SHUTTING_DOWN, - STATUS_STREAMING, - STATUS_ERROR, - STATUS_DISCONNECTED, -}; - -enum { - HDPVR_FLAG_AC3_CAP = 1, -}; - -enum { - BUFSTAT_UNINITIALIZED = 0, - BUFSTAT_AVAILABLE, - BUFSTAT_INPROGRESS, - BUFSTAT_READY, -}; - -#define CTRL_START_STREAMING_VALUE 0x0700 -#define CTRL_STOP_STREAMING_VALUE 0x0800 -#define CTRL_BITRATE_VALUE 0x1000 -#define CTRL_BITRATE_MODE_VALUE 0x1200 -#define CTRL_GOP_MODE_VALUE 0x1300 -#define CTRL_VIDEO_INPUT_VALUE 0x1500 -#define CTRL_VIDEO_STD_TYPE 0x1700 -#define CTRL_AUDIO_INPUT_VALUE 0x2500 -#define CTRL_BRIGHTNESS 0x2900 -#define CTRL_CONTRAST 0x2a00 -#define CTRL_HUE 0x2b00 -#define CTRL_SATURATION 0x2c00 -#define CTRL_SHARPNESS 0x2d00 -#define CTRL_LOW_PASS_FILTER_VALUE 0x3100 - -#define CTRL_DEFAULT_INDEX 0x0003 - - - /* :0 s 38 01 1000 0003 0004 4 = 0a00ca00 - * BITRATE SETTING - * 1st and 2nd byte (little endian): average bitrate in 100 000 bit/s - * min: 1 mbit/s, max: 13.5 mbit/s - * 3rd and 4th byte (little endian): peak bitrate in 100 000 bit/s - * min: average + 100kbit/s, - * max: 20.2 mbit/s - */ - - /* :0 s 38 01 1200 0003 0001 1 = 02 - * BIT RATE MODE - * constant = 1, variable (peak) = 2, variable (average) = 3 - */ - - /* :0 s 38 01 1300 0003 0001 1 = 03 - * GOP MODE (2 bit) - * low bit 0/1: advanced/simple GOP - * high bit 0/1: IDR(4/32/128) / no IDR (4/32/0) - */ - - /* :0 s 38 01 1700 0003 0001 1 = 00 - * VIDEO STANDARD or FREQUNCY 0 = 60hz, 1 = 50hz - */ - - /* :0 s 38 01 3100 0003 0004 4 = 03030000 - * FILTER CONTROL - * 1st byte luma low pass filter strength, - * 2nd byte chroma low pass filter strength, - * 3rd byte MF enable chroma, min=0, max=1 - * 4th byte n - */ - - - /* :0 s 38 b9 0001 0000 0000 0 */ - - - -/* :0 s 38 d3 0000 0000 0001 1 = 00 */ -/* ret = usb_control_msg(dev->udev, */ -/* usb_sndctrlpipe(dev->udev, 0), */ -/* 0xd3, 0x38, */ -/* 0, 0, */ -/* "\0", 1, */ -/* 1000); */ - -/* info("control request returned %d", ret); */ -/* msleep(5000); */ - - - /* :0 s b8 81 1400 0003 0005 5 < - * :0 0 5 = d0024002 19 - * QUERY FRAME SIZE AND RATE - * 1st and 2nd byte (little endian): horizontal resolution - * 3rd and 4th byte (little endian): vertical resolution - * 5th byte: frame rate - */ - - /* :0 s b8 81 1800 0003 0003 3 < - * :0 0 3 = 030104 - * QUERY SIGNAL AND DETECTED LINES, maybe INPUT - */ - -enum hdpvr_video_std { - HDPVR_60HZ = 0, - HDPVR_50HZ, -}; - -enum hdpvr_video_input { - HDPVR_COMPONENT = 0, - HDPVR_SVIDEO, - HDPVR_COMPOSITE, - HDPVR_VIDEO_INPUTS -}; - -enum hdpvr_audio_inputs { - HDPVR_RCA_BACK = 0, - HDPVR_RCA_FRONT, - HDPVR_SPDIF, - HDPVR_AUDIO_INPUTS -}; - -enum hdpvr_bitrate_mode { - HDPVR_CONSTANT = 1, - HDPVR_VARIABLE_PEAK, - HDPVR_VARIABLE_AVERAGE, -}; - -enum hdpvr_gop_mode { - HDPVR_ADVANCED_IDR_GOP = 0, - HDPVR_SIMPLE_IDR_GOP, - HDPVR_ADVANCED_NOIDR_GOP, - HDPVR_SIMPLE_NOIDR_GOP, -}; - -void hdpvr_delete(struct hdpvr_device *dev); - -/*========================================================================*/ -/* hardware control functions */ -int hdpvr_set_options(struct hdpvr_device *dev); - -int hdpvr_set_bitrate(struct hdpvr_device *dev); - -int hdpvr_set_audio(struct hdpvr_device *dev, u8 input, - enum v4l2_mpeg_audio_encoding codec); - -int hdpvr_config_call(struct hdpvr_device *dev, uint value, - unsigned char valbuf); - -struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev); - -/* :0 s b8 81 1800 0003 0003 3 < */ -/* :0 0 3 = 0301ff */ -int get_input_lines_info(struct hdpvr_device *dev); - - -/*========================================================================*/ -/* v4l2 registration */ -int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, - int devnumber); - -int hdpvr_cancel_queue(struct hdpvr_device *dev); - -/*========================================================================*/ -/* i2c adapter registration */ -int hdpvr_register_i2c_adapter(struct hdpvr_device *dev); - -struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev); -struct i2c_client *hdpvr_register_ir_tx_i2c(struct hdpvr_device *dev); - -/*========================================================================*/ -/* buffer management */ -int hdpvr_free_buffers(struct hdpvr_device *dev); -int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count); diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig deleted file mode 100644 index 25e412ecad2c..000000000000 --- a/drivers/media/video/pvrusb2/Kconfig +++ /dev/null @@ -1,65 +0,0 @@ -config VIDEO_PVRUSB2 - tristate "Hauppauge WinTV-PVR USB2 support" - depends on VIDEO_V4L2 && I2C - select VIDEO_TUNER - select VIDEO_TVEEPROM - select VIDEO_CX2341X - select VIDEO_SAA711X - select VIDEO_CX25840 - select VIDEO_MSP3400 - select VIDEO_WM8775 - select VIDEO_CS53L32A - ---help--- - This is a video4linux driver for Conexant 23416 based - usb2 personal video recorder devices. - - To compile this driver as a module, choose M here: the - module will be called pvrusb2 - -config VIDEO_PVRUSB2_SYSFS - bool "pvrusb2 sysfs support (EXPERIMENTAL)" - default y - depends on VIDEO_PVRUSB2 && SYSFS && EXPERIMENTAL - ---help--- - This option enables the operation of a sysfs based - interface for query and control of the pvrusb2 driver. - - This is not generally needed for v4l applications, - although certain applications are optimized to take - advantage of this feature. - - If you are in doubt, say Y. - - Note: This feature is experimental and subject to change. - -config VIDEO_PVRUSB2_DVB - bool "pvrusb2 ATSC/DVB support (EXPERIMENTAL)" - default y - depends on VIDEO_PVRUSB2 && DVB_CORE && EXPERIMENTAL - select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_S5H1409 if !DVB_FE_CUSTOMISE - select DVB_S5H1411 if !DVB_FE_CUSTOMISE - select DVB_TDA10048 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE - select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE - ---help--- - - This option enables a DVB interface for the pvrusb2 driver. - If your device does not support digital television, this - feature will have no affect on the driver's operation. - - If you are in doubt, say Y. - -config VIDEO_PVRUSB2_DEBUGIFC - bool "pvrusb2 debug interface" - depends on VIDEO_PVRUSB2_SYSFS - ---help--- - This option enables the inclusion of a debug interface - in the pvrusb2 driver, hosted through sysfs. - - You do not need to select this option unless you plan - on debugging the driver or performing a manual firmware - extraction. - - If you are in doubt, say N. diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile deleted file mode 100644 index bc716db797e3..000000000000 --- a/drivers/media/video/pvrusb2/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o -obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o -obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o - -pvrusb2-objs := pvrusb2-i2c-core.o \ - pvrusb2-audio.o \ - pvrusb2-encoder.o pvrusb2-video-v4l.o \ - pvrusb2-eeprom.o \ - pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \ - pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \ - pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \ - pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \ - pvrusb2-cs53l32a.o \ - $(obj-pvrusb2-dvb-y) \ - $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y) - -obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o - -ccflags-y += -Idrivers/media/video -ccflags-y += -Idrivers/media/tuners -ccflags-y += -Idrivers/media/dvb-core -ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c deleted file mode 100644 index cc06d5e4adcc..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "pvrusb2-audio.h" -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-debug.h" -#include <linux/videodev2.h> -#include <media/msp3400.h> -#include <media/v4l2-common.h> - - -struct routing_scheme { - const int *def; - unsigned int cnt; -}; - -static const int routing_scheme0[] = { - [PVR2_CVAL_INPUT_TV] = MSP_INPUT_DEFAULT, - [PVR2_CVAL_INPUT_RADIO] = MSP_INPUT(MSP_IN_SCART2, - MSP_IN_TUNER1, - MSP_DSP_IN_SCART, - MSP_DSP_IN_SCART), - [PVR2_CVAL_INPUT_COMPOSITE] = MSP_INPUT(MSP_IN_SCART1, - MSP_IN_TUNER1, - MSP_DSP_IN_SCART, - MSP_DSP_IN_SCART), - [PVR2_CVAL_INPUT_SVIDEO] = MSP_INPUT(MSP_IN_SCART1, - MSP_IN_TUNER1, - MSP_DSP_IN_SCART, - MSP_DSP_IN_SCART), -}; - -static const struct routing_scheme routing_def0 = { - .def = routing_scheme0, - .cnt = ARRAY_SIZE(routing_scheme0), -}; - -static const struct routing_scheme *routing_schemes[] = { - [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0, -}; - -void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) -{ - if (hdw->input_dirty || hdw->force_dirty) { - const struct routing_scheme *sp; - unsigned int sid = hdw->hdw_desc->signal_routing_scheme; - u32 input; - - pvr2_trace(PVR2_TRACE_CHIPS, "subdev msp3400 v4l2 set_stereo"); - sp = (sid < ARRAY_SIZE(routing_schemes)) ? - routing_schemes[sid] : NULL; - - if ((sp != NULL) && - (hdw->input_val >= 0) && - (hdw->input_val < sp->cnt)) { - input = sp->def[hdw->input_val]; - } else { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "*** WARNING *** subdev msp3400 set_input:" - " Invalid routing scheme (%u)" - " and/or input (%d)", - sid, hdw->input_val); - return; - } - sd->ops->audio->s_routing(sd, input, - MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0); - } -} - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.h b/drivers/media/video/pvrusb2/pvrusb2-audio.h deleted file mode 100644 index e3e63d750891..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef __PVRUSB2_AUDIO_H -#define __PVRUSB2_AUDIO_H - -#include "pvrusb2-hdw-internal.h" -void pvr2_msp3400_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); -#endif /* __PVRUSB2_AUDIO_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c deleted file mode 100644 index 7c19ff72e6b3..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-context.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "pvrusb2-context.h" -#include "pvrusb2-io.h" -#include "pvrusb2-ioread.h" -#include "pvrusb2-hdw.h" -#include "pvrusb2-debug.h" -#include <linux/wait.h> -#include <linux/kthread.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/slab.h> - -static struct pvr2_context *pvr2_context_exist_first; -static struct pvr2_context *pvr2_context_exist_last; -static struct pvr2_context *pvr2_context_notify_first; -static struct pvr2_context *pvr2_context_notify_last; -static DEFINE_MUTEX(pvr2_context_mutex); -static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_sync_data); -static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_cleanup_data); -static int pvr2_context_cleanup_flag; -static int pvr2_context_cleaned_flag; -static struct task_struct *pvr2_context_thread_ptr; - - -static void pvr2_context_set_notify(struct pvr2_context *mp, int fl) -{ - int signal_flag = 0; - mutex_lock(&pvr2_context_mutex); - if (fl) { - if (!mp->notify_flag) { - signal_flag = (pvr2_context_notify_first == NULL); - mp->notify_prev = pvr2_context_notify_last; - mp->notify_next = NULL; - pvr2_context_notify_last = mp; - if (mp->notify_prev) { - mp->notify_prev->notify_next = mp; - } else { - pvr2_context_notify_first = mp; - } - mp->notify_flag = !0; - } - } else { - if (mp->notify_flag) { - mp->notify_flag = 0; - if (mp->notify_next) { - mp->notify_next->notify_prev = mp->notify_prev; - } else { - pvr2_context_notify_last = mp->notify_prev; - } - if (mp->notify_prev) { - mp->notify_prev->notify_next = mp->notify_next; - } else { - pvr2_context_notify_first = mp->notify_next; - } - } - } - mutex_unlock(&pvr2_context_mutex); - if (signal_flag) wake_up(&pvr2_context_sync_data); -} - - -static void pvr2_context_destroy(struct pvr2_context *mp) -{ - pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp); - if (mp->hdw) pvr2_hdw_destroy(mp->hdw); - pvr2_context_set_notify(mp, 0); - mutex_lock(&pvr2_context_mutex); - if (mp->exist_next) { - mp->exist_next->exist_prev = mp->exist_prev; - } else { - pvr2_context_exist_last = mp->exist_prev; - } - if (mp->exist_prev) { - mp->exist_prev->exist_next = mp->exist_next; - } else { - pvr2_context_exist_first = mp->exist_next; - } - if (!pvr2_context_exist_first) { - /* Trigger wakeup on control thread in case it is waiting - for an exit condition. */ - wake_up(&pvr2_context_sync_data); - } - mutex_unlock(&pvr2_context_mutex); - kfree(mp); -} - - -static void pvr2_context_notify(struct pvr2_context *mp) -{ - pvr2_context_set_notify(mp,!0); -} - - -static void pvr2_context_check(struct pvr2_context *mp) -{ - struct pvr2_channel *ch1, *ch2; - pvr2_trace(PVR2_TRACE_CTXT, - "pvr2_context %p (notify)", mp); - if (!mp->initialized_flag && !mp->disconnect_flag) { - mp->initialized_flag = !0; - pvr2_trace(PVR2_TRACE_CTXT, - "pvr2_context %p (initialize)", mp); - /* Finish hardware initialization */ - if (pvr2_hdw_initialize(mp->hdw, - (void (*)(void *))pvr2_context_notify, - mp)) { - mp->video_stream.stream = - pvr2_hdw_get_video_stream(mp->hdw); - /* Trigger interface initialization. By doing this - here initialization runs in our own safe and - cozy thread context. */ - if (mp->setup_func) mp->setup_func(mp); - } else { - pvr2_trace(PVR2_TRACE_CTXT, - "pvr2_context %p (thread skipping setup)", - mp); - /* Even though initialization did not succeed, - we're still going to continue anyway. We need - to do this in order to await the expected - disconnect (which we will detect in the normal - course of operation). */ - } - } - - for (ch1 = mp->mc_first; ch1; ch1 = ch2) { - ch2 = ch1->mc_next; - if (ch1->check_func) ch1->check_func(ch1); - } - - if (mp->disconnect_flag && !mp->mc_first) { - /* Go away... */ - pvr2_context_destroy(mp); - return; - } -} - - -static int pvr2_context_shutok(void) -{ - return pvr2_context_cleanup_flag && (pvr2_context_exist_first == NULL); -} - - -static int pvr2_context_thread_func(void *foo) -{ - struct pvr2_context *mp; - - pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread start"); - - do { - while ((mp = pvr2_context_notify_first) != NULL) { - pvr2_context_set_notify(mp, 0); - pvr2_context_check(mp); - } - wait_event_interruptible( - pvr2_context_sync_data, - ((pvr2_context_notify_first != NULL) || - pvr2_context_shutok())); - } while (!pvr2_context_shutok()); - - pvr2_context_cleaned_flag = !0; - wake_up(&pvr2_context_cleanup_data); - - pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread cleaned up"); - - wait_event_interruptible( - pvr2_context_sync_data, - kthread_should_stop()); - - pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread end"); - - return 0; -} - - -int pvr2_context_global_init(void) -{ - pvr2_context_thread_ptr = kthread_run(pvr2_context_thread_func, - NULL, - "pvrusb2-context"); - return (pvr2_context_thread_ptr ? 0 : -ENOMEM); -} - - -void pvr2_context_global_done(void) -{ - pvr2_context_cleanup_flag = !0; - wake_up(&pvr2_context_sync_data); - wait_event_interruptible( - pvr2_context_cleanup_data, - pvr2_context_cleaned_flag); - kthread_stop(pvr2_context_thread_ptr); -} - - -struct pvr2_context *pvr2_context_create( - struct usb_interface *intf, - const struct usb_device_id *devid, - void (*setup_func)(struct pvr2_context *)) -{ - struct pvr2_context *mp = NULL; - mp = kzalloc(sizeof(*mp),GFP_KERNEL); - if (!mp) goto done; - pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (create)",mp); - mp->setup_func = setup_func; - mutex_init(&mp->mutex); - mutex_lock(&pvr2_context_mutex); - mp->exist_prev = pvr2_context_exist_last; - mp->exist_next = NULL; - pvr2_context_exist_last = mp; - if (mp->exist_prev) { - mp->exist_prev->exist_next = mp; - } else { - pvr2_context_exist_first = mp; - } - mutex_unlock(&pvr2_context_mutex); - mp->hdw = pvr2_hdw_create(intf,devid); - if (!mp->hdw) { - pvr2_context_destroy(mp); - mp = NULL; - goto done; - } - pvr2_context_set_notify(mp, !0); - done: - return mp; -} - - -static void pvr2_context_reset_input_limits(struct pvr2_context *mp) -{ - unsigned int tmsk,mmsk; - struct pvr2_channel *cp; - struct pvr2_hdw *hdw = mp->hdw; - mmsk = pvr2_hdw_get_input_available(hdw); - tmsk = mmsk; - for (cp = mp->mc_first; cp; cp = cp->mc_next) { - if (!cp->input_mask) continue; - tmsk &= cp->input_mask; - } - pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk); - pvr2_hdw_commit_ctl(hdw); -} - - -static void pvr2_context_enter(struct pvr2_context *mp) -{ - mutex_lock(&mp->mutex); -} - - -static void pvr2_context_exit(struct pvr2_context *mp) -{ - int destroy_flag = 0; - if (!(mp->mc_first || !mp->disconnect_flag)) { - destroy_flag = !0; - } - mutex_unlock(&mp->mutex); - if (destroy_flag) pvr2_context_notify(mp); -} - - -void pvr2_context_disconnect(struct pvr2_context *mp) -{ - pvr2_hdw_disconnect(mp->hdw); - mp->disconnect_flag = !0; - pvr2_context_notify(mp); -} - - -void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp) -{ - pvr2_context_enter(mp); - cp->hdw = mp->hdw; - cp->mc_head = mp; - cp->mc_next = NULL; - cp->mc_prev = mp->mc_last; - if (mp->mc_last) { - mp->mc_last->mc_next = cp; - } else { - mp->mc_first = cp; - } - mp->mc_last = cp; - pvr2_context_exit(mp); -} - - -static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp) -{ - if (!cp->stream) return; - pvr2_stream_kill(cp->stream->stream); - cp->stream->user = NULL; - cp->stream = NULL; -} - - -void pvr2_channel_done(struct pvr2_channel *cp) -{ - struct pvr2_context *mp = cp->mc_head; - pvr2_context_enter(mp); - cp->input_mask = 0; - pvr2_channel_disclaim_stream(cp); - pvr2_context_reset_input_limits(mp); - if (cp->mc_next) { - cp->mc_next->mc_prev = cp->mc_prev; - } else { - mp->mc_last = cp->mc_prev; - } - if (cp->mc_prev) { - cp->mc_prev->mc_next = cp->mc_next; - } else { - mp->mc_first = cp->mc_next; - } - cp->hdw = NULL; - pvr2_context_exit(mp); -} - - -int pvr2_channel_limit_inputs(struct pvr2_channel *cp,unsigned int cmsk) -{ - unsigned int tmsk,mmsk; - int ret = 0; - struct pvr2_channel *p2; - struct pvr2_hdw *hdw = cp->hdw; - - mmsk = pvr2_hdw_get_input_available(hdw); - cmsk &= mmsk; - if (cmsk == cp->input_mask) { - /* No change; nothing to do */ - return 0; - } - - pvr2_context_enter(cp->mc_head); - do { - if (!cmsk) { - cp->input_mask = 0; - pvr2_context_reset_input_limits(cp->mc_head); - break; - } - tmsk = mmsk; - for (p2 = cp->mc_head->mc_first; p2; p2 = p2->mc_next) { - if (p2 == cp) continue; - if (!p2->input_mask) continue; - tmsk &= p2->input_mask; - } - if (!(tmsk & cmsk)) { - ret = -EPERM; - break; - } - tmsk &= cmsk; - if ((ret = pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk)) != 0) { - /* Internal failure changing allowed list; probably - should not happen, but react if it does. */ - break; - } - cp->input_mask = cmsk; - pvr2_hdw_commit_ctl(hdw); - } while (0); - pvr2_context_exit(cp->mc_head); - return ret; -} - - -unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *cp) -{ - return cp->input_mask; -} - - -int pvr2_channel_claim_stream(struct pvr2_channel *cp, - struct pvr2_context_stream *sp) -{ - int code = 0; - pvr2_context_enter(cp->mc_head); do { - if (sp == cp->stream) break; - if (sp && sp->user) { - code = -EBUSY; - break; - } - pvr2_channel_disclaim_stream(cp); - if (!sp) break; - sp->user = cp; - cp->stream = sp; - } while (0); pvr2_context_exit(cp->mc_head); - return code; -} - - -// This is the marker for the real beginning of a legitimate mpeg2 stream. -static char stream_sync_key[] = { - 0x00, 0x00, 0x01, 0xba, -}; - -struct pvr2_ioread *pvr2_channel_create_mpeg_stream( - struct pvr2_context_stream *sp) -{ - struct pvr2_ioread *cp; - cp = pvr2_ioread_create(); - if (!cp) return NULL; - pvr2_ioread_setup(cp,sp->stream); - pvr2_ioread_set_sync_key(cp,stream_sync_key,sizeof(stream_sync_key)); - return cp; -} - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.h b/drivers/media/video/pvrusb2/pvrusb2-context.h deleted file mode 100644 index d657e53bbfa3..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-context.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __PVRUSB2_CONTEXT_H -#define __PVRUSB2_CONTEXT_H - -#include <linux/mutex.h> -#include <linux/usb.h> -#include <linux/workqueue.h> - -struct pvr2_hdw; /* hardware interface - defined elsewhere */ -struct pvr2_stream; /* stream interface - defined elsewhere */ - -struct pvr2_context; /* All central state */ -struct pvr2_channel; /* One I/O pathway to a user */ -struct pvr2_context_stream; /* Wrapper for a stream */ -struct pvr2_ioread; /* Low level stream structure */ - -struct pvr2_context_stream { - struct pvr2_channel *user; - struct pvr2_stream *stream; -}; - -struct pvr2_context { - struct pvr2_channel *mc_first; - struct pvr2_channel *mc_last; - struct pvr2_context *exist_next; - struct pvr2_context *exist_prev; - struct pvr2_context *notify_next; - struct pvr2_context *notify_prev; - struct pvr2_hdw *hdw; - struct pvr2_context_stream video_stream; - struct mutex mutex; - int notify_flag; - int initialized_flag; - int disconnect_flag; - - /* Called after pvr2_context initialization is complete */ - void (*setup_func)(struct pvr2_context *); - -}; - -struct pvr2_channel { - struct pvr2_context *mc_head; - struct pvr2_channel *mc_next; - struct pvr2_channel *mc_prev; - struct pvr2_context_stream *stream; - struct pvr2_hdw *hdw; - unsigned int input_mask; - void (*check_func)(struct pvr2_channel *); -}; - -struct pvr2_context *pvr2_context_create(struct usb_interface *intf, - const struct usb_device_id *devid, - void (*setup_func)(struct pvr2_context *)); -void pvr2_context_disconnect(struct pvr2_context *); - -void pvr2_channel_init(struct pvr2_channel *,struct pvr2_context *); -void pvr2_channel_done(struct pvr2_channel *); -int pvr2_channel_limit_inputs(struct pvr2_channel *,unsigned int); -unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *); -int pvr2_channel_claim_stream(struct pvr2_channel *, - struct pvr2_context_stream *); -struct pvr2_ioread *pvr2_channel_create_mpeg_stream( - struct pvr2_context_stream *); - -int pvr2_context_global_init(void); -void pvr2_context_global_done(void); - -#endif /* __PVRUSB2_CONTEXT_H */ -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c deleted file mode 100644 index 88320900dbd4..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* - - This source file is specifically designed to interface with the - v4l-dvb cs53l32a module. - -*/ - -#include "pvrusb2-cs53l32a.h" - - -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-debug.h" -#include <linux/videodev2.h> -#include <media/v4l2-common.h> -#include <linux/errno.h> - -struct routing_scheme { - const int *def; - unsigned int cnt; -}; - - -static const int routing_scheme1[] = { - [PVR2_CVAL_INPUT_TV] = 2, /* 1 or 2 seems to work here */ - [PVR2_CVAL_INPUT_RADIO] = 2, - [PVR2_CVAL_INPUT_COMPOSITE] = 0, - [PVR2_CVAL_INPUT_SVIDEO] = 0, -}; - -static const struct routing_scheme routing_def1 = { - .def = routing_scheme1, - .cnt = ARRAY_SIZE(routing_scheme1), -}; - -static const struct routing_scheme *routing_schemes[] = { - [PVR2_ROUTING_SCHEME_ONAIR] = &routing_def1, -}; - - -void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) -{ - if (hdw->input_dirty || hdw->force_dirty) { - const struct routing_scheme *sp; - unsigned int sid = hdw->hdw_desc->signal_routing_scheme; - u32 input; - pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", - hdw->input_val); - sp = (sid < ARRAY_SIZE(routing_schemes)) ? - routing_schemes[sid] : NULL; - if ((sp == NULL) || - (hdw->input_val < 0) || - (hdw->input_val >= sp->cnt)) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "*** WARNING *** subdev v4l2 set_input:" - " Invalid routing scheme (%u)" - " and/or input (%d)", - sid, hdw->input_val); - return; - } - input = sp->def[hdw->input_val]; - sd->ops->audio->s_routing(sd, input, 0, 0); - } -} - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h deleted file mode 100644 index 53ba548b72a7..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef __PVRUSB2_CS53L32A_H -#define __PVRUSB2_CS53L32A_H - -/* - - This module connects the pvrusb2 driver to the I2C chip level - driver which handles device video processing. This interface is - used internally by the driver; higher level code should only - interact through the interface provided by pvrusb2-hdw.h. - -*/ - - -#include "pvrusb2-hdw-internal.h" -void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); - -#endif /* __PVRUSB2_AUDIO_CS53L32A_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c deleted file mode 100644 index 7d5a7139a45a..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +++ /dev/null @@ -1,609 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "pvrusb2-ctrl.h" -#include "pvrusb2-hdw-internal.h" -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mutex.h> - - -static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val) -{ - if (cptr->info->check_value) { - if (!cptr->info->check_value(cptr,val)) return -ERANGE; - } else if (cptr->info->type == pvr2_ctl_enum) { - if (val < 0) return -ERANGE; - if (val >= cptr->info->def.type_enum.count) return -ERANGE; - } else { - int lim; - lim = cptr->info->def.type_int.min_value; - if (cptr->info->get_min_value) { - cptr->info->get_min_value(cptr,&lim); - } - if (val < lim) return -ERANGE; - lim = cptr->info->def.type_int.max_value; - if (cptr->info->get_max_value) { - cptr->info->get_max_value(cptr,&lim); - } - if (val > lim) return -ERANGE; - } - return 0; -} - - -/* Set the given control. */ -int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val) -{ - return pvr2_ctrl_set_mask_value(cptr,~0,val); -} - - -/* Set/clear specific bits of the given control. */ -int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val) -{ - int ret = 0; - if (!cptr) return -EINVAL; - LOCK_TAKE(cptr->hdw->big_lock); do { - if (cptr->info->set_value) { - if (cptr->info->type == pvr2_ctl_bitmask) { - mask &= cptr->info->def.type_bitmask.valid_bits; - } else if ((cptr->info->type == pvr2_ctl_int)|| - (cptr->info->type == pvr2_ctl_enum)) { - ret = pvr2_ctrl_range_check(cptr,val); - if (ret < 0) break; - } else if (cptr->info->type != pvr2_ctl_bool) { - break; - } - ret = cptr->info->set_value(cptr,mask,val); - } else { - ret = -EPERM; - } - } while(0); LOCK_GIVE(cptr->hdw->big_lock); - return ret; -} - - -/* Get the current value of the given control. */ -int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr) -{ - int ret = 0; - if (!cptr) return -EINVAL; - LOCK_TAKE(cptr->hdw->big_lock); do { - ret = cptr->info->get_value(cptr,valptr); - } while(0); LOCK_GIVE(cptr->hdw->big_lock); - return ret; -} - - -/* Retrieve control's type */ -enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr) -{ - if (!cptr) return pvr2_ctl_int; - return cptr->info->type; -} - - -/* Retrieve control's maximum value (int type) */ -int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr) -{ - int ret = 0; - if (!cptr) return 0; - LOCK_TAKE(cptr->hdw->big_lock); do { - if (cptr->info->get_max_value) { - cptr->info->get_max_value(cptr,&ret); - } else if (cptr->info->type == pvr2_ctl_int) { - ret = cptr->info->def.type_int.max_value; - } - } while(0); LOCK_GIVE(cptr->hdw->big_lock); - return ret; -} - - -/* Retrieve control's minimum value (int type) */ -int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr) -{ - int ret = 0; - if (!cptr) return 0; - LOCK_TAKE(cptr->hdw->big_lock); do { - if (cptr->info->get_min_value) { - cptr->info->get_min_value(cptr,&ret); - } else if (cptr->info->type == pvr2_ctl_int) { - ret = cptr->info->def.type_int.min_value; - } - } while(0); LOCK_GIVE(cptr->hdw->big_lock); - return ret; -} - - -/* Retrieve control's default value (any type) */ -int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr) -{ - int ret = 0; - if (!cptr) return -EINVAL; - LOCK_TAKE(cptr->hdw->big_lock); do { - if (cptr->info->get_def_value) { - ret = cptr->info->get_def_value(cptr, valptr); - } else { - *valptr = cptr->info->default_value; - } - } while(0); LOCK_GIVE(cptr->hdw->big_lock); - return ret; -} - - -/* Retrieve control's enumeration count (enum only) */ -int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr) -{ - int ret = 0; - if (!cptr) return 0; - LOCK_TAKE(cptr->hdw->big_lock); do { - if (cptr->info->type == pvr2_ctl_enum) { - ret = cptr->info->def.type_enum.count; - } - } while(0); LOCK_GIVE(cptr->hdw->big_lock); - return ret; -} - - -/* Retrieve control's valid mask bits (bit mask only) */ -int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr) -{ - int ret = 0; - if (!cptr) return 0; - LOCK_TAKE(cptr->hdw->big_lock); do { - if (cptr->info->type == pvr2_ctl_bitmask) { - ret = cptr->info->def.type_bitmask.valid_bits; - } - } while(0); LOCK_GIVE(cptr->hdw->big_lock); - return ret; -} - - -/* Retrieve the control's name */ -const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr) -{ - if (!cptr) return NULL; - return cptr->info->name; -} - - -/* Retrieve the control's desc */ -const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr) -{ - if (!cptr) return NULL; - return cptr->info->desc; -} - - -/* Retrieve a control enumeration or bit mask value */ -int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val, - char *bptr,unsigned int bmax, - unsigned int *blen) -{ - int ret = -EINVAL; - if (!cptr) return 0; - *blen = 0; - LOCK_TAKE(cptr->hdw->big_lock); do { - if (cptr->info->type == pvr2_ctl_enum) { - const char * const *names; - names = cptr->info->def.type_enum.value_names; - if (pvr2_ctrl_range_check(cptr,val) == 0) { - if (names[val]) { - *blen = scnprintf( - bptr,bmax,"%s", - names[val]); - } else { - *blen = 0; - } - ret = 0; - } - } else if (cptr->info->type == pvr2_ctl_bitmask) { - const char **names; - unsigned int idx; - int msk; - names = cptr->info->def.type_bitmask.bit_names; - val &= cptr->info->def.type_bitmask.valid_bits; - for (idx = 0, msk = 1; val; idx++, msk <<= 1) { - if (val & msk) { - *blen = scnprintf(bptr,bmax,"%s", - names[idx]); - ret = 0; - break; - } - } - } - } while(0); LOCK_GIVE(cptr->hdw->big_lock); - return ret; -} - - -/* Return V4L ID for this control or zero if none */ -int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr) -{ - if (!cptr) return 0; - return cptr->info->v4l_id; -} - - -unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr) -{ - unsigned int flags = 0; - - if (cptr->info->get_v4lflags) { - flags = cptr->info->get_v4lflags(cptr); - } - - if (cptr->info->set_value) { - flags &= ~V4L2_CTRL_FLAG_READ_ONLY; - } else { - flags |= V4L2_CTRL_FLAG_READ_ONLY; - } - - return flags; -} - - -/* Return true if control is writable */ -int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr) -{ - if (!cptr) return 0; - return cptr->info->set_value != NULL; -} - - -/* Return true if control has custom symbolic representation */ -int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr) -{ - if (!cptr) return 0; - if (!cptr->info->val_to_sym) return 0; - if (!cptr->info->sym_to_val) return 0; - return !0; -} - - -/* Convert a given mask/val to a custom symbolic value */ -int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr, - int mask,int val, - char *buf,unsigned int maxlen, - unsigned int *len) -{ - if (!cptr) return -EINVAL; - if (!cptr->info->val_to_sym) return -EINVAL; - return cptr->info->val_to_sym(cptr,mask,val,buf,maxlen,len); -} - - -/* Convert a symbolic value to a mask/value pair */ -int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *cptr, - const char *buf,unsigned int len, - int *maskptr,int *valptr) -{ - if (!cptr) return -EINVAL; - if (!cptr->info->sym_to_val) return -EINVAL; - return cptr->info->sym_to_val(cptr,buf,len,maskptr,valptr); -} - - -static unsigned int gen_bitmask_string(int msk,int val,int msk_only, - const char **names, - char *ptr,unsigned int len) -{ - unsigned int idx; - long sm,um; - int spcFl; - unsigned int uc,cnt; - const char *idStr; - - spcFl = 0; - uc = 0; - um = 0; - for (idx = 0, sm = 1; msk; idx++, sm <<= 1) { - if (sm & msk) { - msk &= ~sm; - idStr = names[idx]; - if (idStr) { - cnt = scnprintf(ptr,len,"%s%s%s", - (spcFl ? " " : ""), - (msk_only ? "" : - ((val & sm) ? "+" : "-")), - idStr); - ptr += cnt; len -= cnt; uc += cnt; - spcFl = !0; - } else { - um |= sm; - } - } - } - if (um) { - if (msk_only) { - cnt = scnprintf(ptr,len,"%s0x%lx", - (spcFl ? " " : ""), - um); - ptr += cnt; len -= cnt; uc += cnt; - spcFl = !0; - } else if (um & val) { - cnt = scnprintf(ptr,len,"%s+0x%lx", - (spcFl ? " " : ""), - um & val); - ptr += cnt; len -= cnt; uc += cnt; - spcFl = !0; - } else if (um & ~val) { - cnt = scnprintf(ptr,len,"%s+0x%lx", - (spcFl ? " " : ""), - um & ~val); - ptr += cnt; len -= cnt; uc += cnt; - spcFl = !0; - } - } - return uc; -} - - -static const char *boolNames[] = { - "false", - "true", - "no", - "yes", -}; - - -static int parse_token(const char *ptr,unsigned int len, - int *valptr, - const char * const *names, unsigned int namecnt) -{ - char buf[33]; - unsigned int slen; - unsigned int idx; - int negfl; - char *p2; - *valptr = 0; - if (!names) namecnt = 0; - for (idx = 0; idx < namecnt; idx++) { - if (!names[idx]) continue; - slen = strlen(names[idx]); - if (slen != len) continue; - if (memcmp(names[idx],ptr,slen)) continue; - *valptr = idx; - return 0; - } - negfl = 0; - if ((*ptr == '-') || (*ptr == '+')) { - negfl = (*ptr == '-'); - ptr++; len--; - } - if (len >= sizeof(buf)) return -EINVAL; - memcpy(buf,ptr,len); - buf[len] = 0; - *valptr = simple_strtol(buf,&p2,0); - if (negfl) *valptr = -(*valptr); - if (*p2) return -EINVAL; - return 1; -} - - -static int parse_mtoken(const char *ptr,unsigned int len, - int *valptr, - const char **names,int valid_bits) -{ - char buf[33]; - unsigned int slen; - unsigned int idx; - char *p2; - int msk; - *valptr = 0; - for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) { - if (!(msk & valid_bits)) continue; - valid_bits &= ~msk; - if (!names[idx]) continue; - slen = strlen(names[idx]); - if (slen != len) continue; - if (memcmp(names[idx],ptr,slen)) continue; - *valptr = msk; - return 0; - } - if (len >= sizeof(buf)) return -EINVAL; - memcpy(buf,ptr,len); - buf[len] = 0; - *valptr = simple_strtol(buf,&p2,0); - if (*p2) return -EINVAL; - return 0; -} - - -static int parse_tlist(const char *ptr,unsigned int len, - int *maskptr,int *valptr, - const char **names,int valid_bits) -{ - unsigned int cnt; - int mask,val,kv,mode,ret; - mask = 0; - val = 0; - ret = 0; - while (len) { - cnt = 0; - while ((cnt < len) && - ((ptr[cnt] <= 32) || - (ptr[cnt] >= 127))) cnt++; - ptr += cnt; - len -= cnt; - mode = 0; - if ((*ptr == '-') || (*ptr == '+')) { - mode = (*ptr == '-') ? -1 : 1; - ptr++; - len--; - } - cnt = 0; - while (cnt < len) { - if (ptr[cnt] <= 32) break; - if (ptr[cnt] >= 127) break; - cnt++; - } - if (!cnt) break; - if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) { - ret = -EINVAL; - break; - } - ptr += cnt; - len -= cnt; - switch (mode) { - case 0: - mask = valid_bits; - val |= kv; - break; - case -1: - mask |= kv; - val &= ~kv; - break; - case 1: - mask |= kv; - val |= kv; - break; - default: - break; - } - } - *maskptr = mask; - *valptr = val; - return ret; -} - - -/* Convert a symbolic value to a mask/value pair */ -int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr, - const char *ptr,unsigned int len, - int *maskptr,int *valptr) -{ - int ret = -EINVAL; - unsigned int cnt; - - *maskptr = 0; - *valptr = 0; - - cnt = 0; - while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++; - len -= cnt; ptr += cnt; - cnt = 0; - while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) || - (ptr[len-(cnt+1)] >= 127))) cnt++; - len -= cnt; - - if (!len) return -EINVAL; - - LOCK_TAKE(cptr->hdw->big_lock); do { - if (cptr->info->type == pvr2_ctl_int) { - ret = parse_token(ptr,len,valptr,NULL,0); - if (ret >= 0) { - ret = pvr2_ctrl_range_check(cptr,*valptr); - } - *maskptr = ~0; - } else if (cptr->info->type == pvr2_ctl_bool) { - ret = parse_token(ptr,len,valptr,boolNames, - ARRAY_SIZE(boolNames)); - if (ret == 1) { - *valptr = *valptr ? !0 : 0; - } else if (ret == 0) { - *valptr = (*valptr & 1) ? !0 : 0; - } - *maskptr = 1; - } else if (cptr->info->type == pvr2_ctl_enum) { - ret = parse_token( - ptr,len,valptr, - cptr->info->def.type_enum.value_names, - cptr->info->def.type_enum.count); - if (ret >= 0) { - ret = pvr2_ctrl_range_check(cptr,*valptr); - } - *maskptr = ~0; - } else if (cptr->info->type == pvr2_ctl_bitmask) { - ret = parse_tlist( - ptr,len,maskptr,valptr, - cptr->info->def.type_bitmask.bit_names, - cptr->info->def.type_bitmask.valid_bits); - } - } while(0); LOCK_GIVE(cptr->hdw->big_lock); - return ret; -} - - -/* Convert a given mask/val to a symbolic value */ -int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr, - int mask,int val, - char *buf,unsigned int maxlen, - unsigned int *len) -{ - int ret = -EINVAL; - - *len = 0; - if (cptr->info->type == pvr2_ctl_int) { - *len = scnprintf(buf,maxlen,"%d",val); - ret = 0; - } else if (cptr->info->type == pvr2_ctl_bool) { - *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false"); - ret = 0; - } else if (cptr->info->type == pvr2_ctl_enum) { - const char * const *names; - names = cptr->info->def.type_enum.value_names; - if ((val >= 0) && - (val < cptr->info->def.type_enum.count)) { - if (names[val]) { - *len = scnprintf( - buf,maxlen,"%s", - names[val]); - } else { - *len = 0; - } - ret = 0; - } - } else if (cptr->info->type == pvr2_ctl_bitmask) { - *len = gen_bitmask_string( - val & mask & cptr->info->def.type_bitmask.valid_bits, - ~0,!0, - cptr->info->def.type_bitmask.bit_names, - buf,maxlen); - } - return ret; -} - - -/* Convert a given mask/val to a symbolic value */ -int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr, - int mask,int val, - char *buf,unsigned int maxlen, - unsigned int *len) -{ - int ret; - LOCK_TAKE(cptr->hdw->big_lock); do { - ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val, - buf,maxlen,len); - } while(0); LOCK_GIVE(cptr->hdw->big_lock); - return ret; -} - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h deleted file mode 100644 index 794ff90121c7..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __PVRUSB2_CTRL_H -#define __PVRUSB2_CTRL_H - -struct pvr2_ctrl; - -enum pvr2_ctl_type { - pvr2_ctl_int = 0, - pvr2_ctl_enum = 1, - pvr2_ctl_bitmask = 2, - pvr2_ctl_bool = 3, -}; - - -/* Set the given control. */ -int pvr2_ctrl_set_value(struct pvr2_ctrl *,int val); - -/* Set/clear specific bits of the given control. */ -int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *,int mask,int val); - -/* Get the current value of the given control. */ -int pvr2_ctrl_get_value(struct pvr2_ctrl *,int *valptr); - -/* Retrieve control's type */ -enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *); - -/* Retrieve control's maximum value (int type) */ -int pvr2_ctrl_get_max(struct pvr2_ctrl *); - -/* Retrieve control's minimum value (int type) */ -int pvr2_ctrl_get_min(struct pvr2_ctrl *); - -/* Retrieve control's default value (any type) */ -int pvr2_ctrl_get_def(struct pvr2_ctrl *, int *valptr); - -/* Retrieve control's enumeration count (enum only) */ -int pvr2_ctrl_get_cnt(struct pvr2_ctrl *); - -/* Retrieve control's valid mask bits (bit mask only) */ -int pvr2_ctrl_get_mask(struct pvr2_ctrl *); - -/* Retrieve the control's name */ -const char *pvr2_ctrl_get_name(struct pvr2_ctrl *); - -/* Retrieve the control's desc */ -const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *); - -/* Retrieve a control enumeration or bit mask value */ -int pvr2_ctrl_get_valname(struct pvr2_ctrl *,int,char *,unsigned int, - unsigned int *); - -/* Return true if control is writable */ -int pvr2_ctrl_is_writable(struct pvr2_ctrl *); - -/* Return V4L flags value for control (or zero if there is no v4l control - actually under this control) */ -unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *); - -/* Return V4L ID for this control or zero if none */ -int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *); - -/* Return true if control has custom symbolic representation */ -int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *); - -/* Convert a given mask/val to a custom symbolic value */ -int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *, - int mask,int val, - char *buf,unsigned int maxlen, - unsigned int *len); - -/* Convert a symbolic value to a mask/value pair */ -int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *, - const char *buf,unsigned int len, - int *maskptr,int *valptr); - -/* Convert a given mask/val to a symbolic value */ -int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *, - int mask,int val, - char *buf,unsigned int maxlen, - unsigned int *len); - -/* Convert a symbolic value to a mask/value pair */ -int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *, - const char *buf,unsigned int len, - int *maskptr,int *valptr); - -/* Convert a given mask/val to a symbolic value - must already be - inside of critical region. */ -int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *, - int mask,int val, - char *buf,unsigned int maxlen, - unsigned int *len); - -#endif /* __PVRUSB2_CTRL_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c deleted file mode 100644 index c514d0b9ffdc..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* - - This source file is specifically designed to interface with the - cx2584x, in kernels 2.6.16 or newer. - -*/ - -#include "pvrusb2-cx2584x-v4l.h" -#include "pvrusb2-video-v4l.h" - - -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-debug.h" -#include <media/cx25840.h> -#include <linux/videodev2.h> -#include <media/v4l2-common.h> -#include <linux/errno.h> - - -struct routing_scheme_item { - int vid; - int aud; -}; - -struct routing_scheme { - const struct routing_scheme_item *def; - unsigned int cnt; -}; - -static const struct routing_scheme_item routing_scheme0[] = { - [PVR2_CVAL_INPUT_TV] = { - .vid = CX25840_COMPOSITE7, - .aud = CX25840_AUDIO8, - }, - [PVR2_CVAL_INPUT_RADIO] = { /* Treat the same as composite */ - .vid = CX25840_COMPOSITE3, - .aud = CX25840_AUDIO_SERIAL, - }, - [PVR2_CVAL_INPUT_COMPOSITE] = { - .vid = CX25840_COMPOSITE3, - .aud = CX25840_AUDIO_SERIAL, - }, - [PVR2_CVAL_INPUT_SVIDEO] = { - .vid = CX25840_SVIDEO1, - .aud = CX25840_AUDIO_SERIAL, - }, -}; - -static const struct routing_scheme routing_def0 = { - .def = routing_scheme0, - .cnt = ARRAY_SIZE(routing_scheme0), -}; - -/* Specific to gotview device */ -static const struct routing_scheme_item routing_schemegv[] = { - [PVR2_CVAL_INPUT_TV] = { - .vid = CX25840_COMPOSITE2, - .aud = CX25840_AUDIO5, - }, - [PVR2_CVAL_INPUT_RADIO] = { - /* line-in is used for radio and composite. A GPIO is - used to switch between the two choices. */ - .vid = CX25840_COMPOSITE1, - .aud = CX25840_AUDIO_SERIAL, - }, - [PVR2_CVAL_INPUT_COMPOSITE] = { - .vid = CX25840_COMPOSITE1, - .aud = CX25840_AUDIO_SERIAL, - }, - [PVR2_CVAL_INPUT_SVIDEO] = { - .vid = (CX25840_SVIDEO_LUMA3|CX25840_SVIDEO_CHROMA4), - .aud = CX25840_AUDIO_SERIAL, - }, -}; - -static const struct routing_scheme routing_defgv = { - .def = routing_schemegv, - .cnt = ARRAY_SIZE(routing_schemegv), -}; - -/* Specific to grabster av400 device */ -static const struct routing_scheme_item routing_schemeav400[] = { - [PVR2_CVAL_INPUT_COMPOSITE] = { - .vid = CX25840_COMPOSITE1, - .aud = CX25840_AUDIO_SERIAL, - }, - [PVR2_CVAL_INPUT_SVIDEO] = { - .vid = (CX25840_SVIDEO_LUMA2|CX25840_SVIDEO_CHROMA4), - .aud = CX25840_AUDIO_SERIAL, - }, -}; - -static const struct routing_scheme routing_defav400 = { - .def = routing_schemeav400, - .cnt = ARRAY_SIZE(routing_schemeav400), -}; - -static const struct routing_scheme *routing_schemes[] = { - [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0, - [PVR2_ROUTING_SCHEME_GOTVIEW] = &routing_defgv, - [PVR2_ROUTING_SCHEME_AV400] = &routing_defav400, -}; - -void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) -{ - pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x update..."); - if (hdw->input_dirty || hdw->force_dirty) { - enum cx25840_video_input vid_input; - enum cx25840_audio_input aud_input; - const struct routing_scheme *sp; - unsigned int sid = hdw->hdw_desc->signal_routing_scheme; - - sp = (sid < ARRAY_SIZE(routing_schemes)) ? - routing_schemes[sid] : NULL; - if ((sp == NULL) || - (hdw->input_val < 0) || - (hdw->input_val >= sp->cnt)) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "*** WARNING *** subdev cx2584x set_input:" - " Invalid routing scheme (%u)" - " and/or input (%d)", - sid, hdw->input_val); - return; - } - vid_input = sp->def[hdw->input_val].vid; - aud_input = sp->def[hdw->input_val].aud; - pvr2_trace(PVR2_TRACE_CHIPS, - "subdev cx2584x set_input vid=0x%x aud=0x%x", - vid_input, aud_input); - sd->ops->video->s_routing(sd, (u32)vid_input, 0, 0); - sd->ops->audio->s_routing(sd, (u32)aud_input, 0, 0); - } -} - - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h deleted file mode 100644 index e35c2322a08c..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef __PVRUSB2_CX2584X_V4L_H -#define __PVRUSB2_CX2584X_V4L_H - -/* - - This module connects the pvrusb2 driver to the I2C chip level - driver which handles combined device audio & video processing. - This interface is used internally by the driver; higher level code - should only interact through the interface provided by - pvrusb2-hdw.h. - -*/ - - - -#include "pvrusb2-hdw-internal.h" - -void pvr2_cx25840_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd); - - -#endif /* __PVRUSB2_CX2584X_V4L_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-debug.h b/drivers/media/video/pvrusb2/pvrusb2-debug.h deleted file mode 100644 index be79249f8628..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-debug.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __PVRUSB2_DEBUG_H -#define __PVRUSB2_DEBUG_H - -extern int pvrusb2_debug; - -#define pvr2_trace(msk, fmt, arg...) do {if(msk & pvrusb2_debug) printk(KERN_INFO "pvrusb2: " fmt "\n", ##arg); } while (0) - -/* These are listed in *rough* order of decreasing usefulness and - increasing noise level. */ -#define PVR2_TRACE_INFO (1 << 0) /* Normal messages */ -#define PVR2_TRACE_ERROR_LEGS (1 << 1) /* error messages */ -#define PVR2_TRACE_TOLERANCE (1 << 2) /* track tolerance-affected errors */ -#define PVR2_TRACE_TRAP (1 << 3) /* Trap & report app misbehavior */ -#define PVR2_TRACE_STD (1 << 4) /* Log video standard stuff */ -#define PVR2_TRACE_INIT (1 << 5) /* misc initialization steps */ -#define PVR2_TRACE_START_STOP (1 << 6) /* Streaming start / stop */ -#define PVR2_TRACE_CTL (1 << 7) /* commit of control changes */ -#define PVR2_TRACE_STATE (1 << 8) /* Device state changes */ -#define PVR2_TRACE_STBITS (1 << 9) /* Individual bit state changes */ -#define PVR2_TRACE_EEPROM (1 << 10) /* eeprom parsing / report */ -#define PVR2_TRACE_STRUCT (1 << 11) /* internal struct creation */ -#define PVR2_TRACE_OPEN_CLOSE (1 << 12) /* application open / close */ -#define PVR2_TRACE_CTXT (1 << 13) /* Main context tracking */ -#define PVR2_TRACE_SYSFS (1 << 14) /* Sysfs driven I/O */ -#define PVR2_TRACE_FIRMWARE (1 << 15) /* firmware upload actions */ -#define PVR2_TRACE_CHIPS (1 << 16) /* chip broadcast operation */ -#define PVR2_TRACE_I2C (1 << 17) /* I2C related stuff */ -#define PVR2_TRACE_I2C_CMD (1 << 18) /* Software commands to I2C modules */ -#define PVR2_TRACE_I2C_CORE (1 << 19) /* I2C core debugging */ -#define PVR2_TRACE_I2C_TRAF (1 << 20) /* I2C traffic through the adapter */ -#define PVR2_TRACE_V4LIOCTL (1 << 21) /* v4l ioctl details */ -#define PVR2_TRACE_ENCODER (1 << 22) /* mpeg2 encoder operation */ -#define PVR2_TRACE_BUF_POOL (1 << 23) /* Track buffer pool management */ -#define PVR2_TRACE_BUF_FLOW (1 << 24) /* Track buffer flow in system */ -#define PVR2_TRACE_DATA_FLOW (1 << 25) /* Track data flow */ -#define PVR2_TRACE_DEBUGIFC (1 << 26) /* Debug interface actions */ -#define PVR2_TRACE_GPIO (1 << 27) /* GPIO state bit changes */ -#define PVR2_TRACE_DVB_FEED (1 << 28) /* DVB transport feed debug */ - - -#endif /* __PVRUSB2_HDW_INTERNAL_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c deleted file mode 100644 index 4279ebb811a1..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/string.h> -#include "pvrusb2-debugifc.h" -#include "pvrusb2-hdw.h" -#include "pvrusb2-debug.h" - -struct debugifc_mask_item { - const char *name; - unsigned long msk; -}; - - -static unsigned int debugifc_count_whitespace(const char *buf, - unsigned int count) -{ - unsigned int scnt; - char ch; - - for (scnt = 0; scnt < count; scnt++) { - ch = buf[scnt]; - if (ch == ' ') continue; - if (ch == '\t') continue; - if (ch == '\n') continue; - break; - } - return scnt; -} - - -static unsigned int debugifc_count_nonwhitespace(const char *buf, - unsigned int count) -{ - unsigned int scnt; - char ch; - - for (scnt = 0; scnt < count; scnt++) { - ch = buf[scnt]; - if (ch == ' ') break; - if (ch == '\t') break; - if (ch == '\n') break; - } - return scnt; -} - - -static unsigned int debugifc_isolate_word(const char *buf,unsigned int count, - const char **wstrPtr, - unsigned int *wlenPtr) -{ - const char *wptr; - unsigned int consume_cnt = 0; - unsigned int wlen; - unsigned int scnt; - - wptr = NULL; - wlen = 0; - scnt = debugifc_count_whitespace(buf,count); - consume_cnt += scnt; count -= scnt; buf += scnt; - if (!count) goto done; - - scnt = debugifc_count_nonwhitespace(buf,count); - if (!scnt) goto done; - wptr = buf; - wlen = scnt; - consume_cnt += scnt; count -= scnt; buf += scnt; - - done: - *wstrPtr = wptr; - *wlenPtr = wlen; - return consume_cnt; -} - - -static int debugifc_parse_unsigned_number(const char *buf,unsigned int count, - u32 *num_ptr) -{ - u32 result = 0; - int radix = 10; - if ((count >= 2) && (buf[0] == '0') && - ((buf[1] == 'x') || (buf[1] == 'X'))) { - radix = 16; - count -= 2; - buf += 2; - } else if ((count >= 1) && (buf[0] == '0')) { - radix = 8; - } - - while (count--) { - int val = hex_to_bin(*buf++); - if (val < 0 || val >= radix) - return -EINVAL; - result *= radix; - result += val; - } - *num_ptr = result; - return 0; -} - - -static int debugifc_match_keyword(const char *buf,unsigned int count, - const char *keyword) -{ - unsigned int kl; - if (!keyword) return 0; - kl = strlen(keyword); - if (kl != count) return 0; - return !memcmp(buf,keyword,kl); -} - - -int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt) -{ - int bcnt = 0; - int ccnt; - ccnt = scnprintf(buf, acnt, "Driver hardware description: %s\n", - pvr2_hdw_get_desc(hdw)); - bcnt += ccnt; acnt -= ccnt; buf += ccnt; - ccnt = scnprintf(buf,acnt,"Driver state info:\n"); - bcnt += ccnt; acnt -= ccnt; buf += ccnt; - ccnt = pvr2_hdw_state_report(hdw,buf,acnt); - bcnt += ccnt; acnt -= ccnt; buf += ccnt; - - return bcnt; -} - - -int pvr2_debugifc_print_status(struct pvr2_hdw *hdw, - char *buf,unsigned int acnt) -{ - int bcnt = 0; - int ccnt; - int ret; - u32 gpio_dir,gpio_in,gpio_out; - struct pvr2_stream_stats stats; - struct pvr2_stream *sp; - - ret = pvr2_hdw_is_hsm(hdw); - ccnt = scnprintf(buf,acnt,"USB link speed: %s\n", - (ret < 0 ? "FAIL" : (ret ? "high" : "full"))); - bcnt += ccnt; acnt -= ccnt; buf += ccnt; - - gpio_dir = 0; gpio_in = 0; gpio_out = 0; - pvr2_hdw_gpio_get_dir(hdw,&gpio_dir); - pvr2_hdw_gpio_get_out(hdw,&gpio_out); - pvr2_hdw_gpio_get_in(hdw,&gpio_in); - ccnt = scnprintf(buf,acnt,"GPIO state: dir=0x%x in=0x%x out=0x%x\n", - gpio_dir,gpio_in,gpio_out); - bcnt += ccnt; acnt -= ccnt; buf += ccnt; - - ccnt = scnprintf(buf,acnt,"Streaming is %s\n", - pvr2_hdw_get_streaming(hdw) ? "on" : "off"); - bcnt += ccnt; acnt -= ccnt; buf += ccnt; - - - sp = pvr2_hdw_get_video_stream(hdw); - if (sp) { - pvr2_stream_get_stats(sp, &stats, 0); - ccnt = scnprintf( - buf,acnt, - "Bytes streamed=%u" - " URBs: queued=%u idle=%u ready=%u" - " processed=%u failed=%u\n", - stats.bytes_processed, - stats.buffers_in_queue, - stats.buffers_in_idle, - stats.buffers_in_ready, - stats.buffers_processed, - stats.buffers_failed); - bcnt += ccnt; acnt -= ccnt; buf += ccnt; - } - - return bcnt; -} - - -static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf, - unsigned int count) -{ - const char *wptr; - unsigned int wlen; - unsigned int scnt; - - scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); - if (!scnt) return 0; - count -= scnt; buf += scnt; - if (!wptr) return 0; - - pvr2_trace(PVR2_TRACE_DEBUGIFC,"debugifc cmd: \"%.*s\"",wlen,wptr); - if (debugifc_match_keyword(wptr,wlen,"reset")) { - scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); - if (!scnt) return -EINVAL; - count -= scnt; buf += scnt; - if (!wptr) return -EINVAL; - if (debugifc_match_keyword(wptr,wlen,"cpu")) { - pvr2_hdw_cpureset_assert(hdw,!0); - pvr2_hdw_cpureset_assert(hdw,0); - return 0; - } else if (debugifc_match_keyword(wptr,wlen,"bus")) { - pvr2_hdw_device_reset(hdw); - } else if (debugifc_match_keyword(wptr,wlen,"soft")) { - return pvr2_hdw_cmd_powerup(hdw); - } else if (debugifc_match_keyword(wptr,wlen,"deep")) { - return pvr2_hdw_cmd_deep_reset(hdw); - } else if (debugifc_match_keyword(wptr,wlen,"firmware")) { - return pvr2_upload_firmware2(hdw); - } else if (debugifc_match_keyword(wptr,wlen,"decoder")) { - return pvr2_hdw_cmd_decoder_reset(hdw); - } else if (debugifc_match_keyword(wptr,wlen,"worker")) { - return pvr2_hdw_untrip(hdw); - } else if (debugifc_match_keyword(wptr,wlen,"usbstats")) { - pvr2_stream_get_stats(pvr2_hdw_get_video_stream(hdw), - NULL, !0); - return 0; - } - return -EINVAL; - } else if (debugifc_match_keyword(wptr,wlen,"cpufw")) { - scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); - if (!scnt) return -EINVAL; - count -= scnt; buf += scnt; - if (!wptr) return -EINVAL; - if (debugifc_match_keyword(wptr,wlen,"fetch")) { - scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); - if (scnt && wptr) { - count -= scnt; buf += scnt; - if (debugifc_match_keyword(wptr, wlen, - "prom")) { - pvr2_hdw_cpufw_set_enabled(hdw, 2, !0); - } else if (debugifc_match_keyword(wptr, wlen, - "ram8k")) { - pvr2_hdw_cpufw_set_enabled(hdw, 0, !0); - } else if (debugifc_match_keyword(wptr, wlen, - "ram16k")) { - pvr2_hdw_cpufw_set_enabled(hdw, 1, !0); - } else { - return -EINVAL; - } - } - pvr2_hdw_cpufw_set_enabled(hdw,0,!0); - return 0; - } else if (debugifc_match_keyword(wptr,wlen,"done")) { - pvr2_hdw_cpufw_set_enabled(hdw,0,0); - return 0; - } else { - return -EINVAL; - } - } else if (debugifc_match_keyword(wptr,wlen,"gpio")) { - int dir_fl = 0; - int ret; - u32 msk,val; - scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); - if (!scnt) return -EINVAL; - count -= scnt; buf += scnt; - if (!wptr) return -EINVAL; - if (debugifc_match_keyword(wptr,wlen,"dir")) { - dir_fl = !0; - } else if (!debugifc_match_keyword(wptr,wlen,"out")) { - return -EINVAL; - } - scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); - if (!scnt) return -EINVAL; - count -= scnt; buf += scnt; - if (!wptr) return -EINVAL; - ret = debugifc_parse_unsigned_number(wptr,wlen,&msk); - if (ret) return ret; - scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); - if (wptr) { - ret = debugifc_parse_unsigned_number(wptr,wlen,&val); - if (ret) return ret; - } else { - val = msk; - msk = 0xffffffff; - } - if (dir_fl) { - ret = pvr2_hdw_gpio_chg_dir(hdw,msk,val); - } else { - ret = pvr2_hdw_gpio_chg_out(hdw,msk,val); - } - return ret; - } - pvr2_trace(PVR2_TRACE_DEBUGIFC, - "debugifc failed to recognize cmd: \"%.*s\"",wlen,wptr); - return -EINVAL; -} - - -int pvr2_debugifc_docmd(struct pvr2_hdw *hdw,const char *buf, - unsigned int count) -{ - unsigned int bcnt = 0; - int ret; - - while (count) { - for (bcnt = 0; bcnt < count; bcnt++) { - if (buf[bcnt] == '\n') break; - } - - ret = pvr2_debugifc_do1cmd(hdw,buf,bcnt); - if (ret < 0) return ret; - if (bcnt < count) bcnt++; - buf += bcnt; - count -= bcnt; - } - - return 0; -} - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.h b/drivers/media/video/pvrusb2/pvrusb2-debugifc.h deleted file mode 100644 index 2f8d46761cd0..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __PVRUSB2_DEBUGIFC_H -#define __PVRUSB2_DEBUGIFC_H - -struct pvr2_hdw; - -/* Print general status of driver. This will also trigger a probe of - the USB link. Unlike print_info(), this one synchronizes with the - driver so the information should be self-consistent (but it will - hang if the driver is wedged). */ -int pvr2_debugifc_print_info(struct pvr2_hdw *, - char *buf_ptr, unsigned int buf_size); - -/* Non-intrusively print some useful debugging info from inside the - driver. This should work even if the driver appears to be - wedged. */ -int pvr2_debugifc_print_status(struct pvr2_hdw *, - char *buf_ptr,unsigned int buf_size); - -/* Parse a string command into a driver action. */ -int pvr2_debugifc_docmd(struct pvr2_hdw *, - const char *buf_ptr,unsigned int buf_size); - -#endif /* __PVRUSB2_DEBUGIFC_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c deleted file mode 100644 index adc501d3c287..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ /dev/null @@ -1,576 +0,0 @@ -/* - * - * - * Copyright (C) 2007 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* - -This source file should encompass ALL per-device type information for the -driver. To define a new device, add elements to the pvr2_device_table and -pvr2_device_desc structures. - -*/ - -#include "pvrusb2-devattr.h" -#include <linux/usb.h> -#include <linux/module.h> -/* This is needed in order to pull in tuner type ids... */ -#include <linux/i2c.h> -#include <media/tuner.h> -#ifdef CONFIG_VIDEO_PVRUSB2_DVB -#include "pvrusb2-hdw-internal.h" -#include "lgdt330x.h" -#include "s5h1409.h" -#include "s5h1411.h" -#include "tda10048.h" -#include "tda18271.h" -#include "tda8290.h" -#include "tuner-simple.h" -#endif - - -/*------------------------------------------------------------------------*/ -/* Hauppauge PVR-USB2 Model 29xxx */ - -static const struct pvr2_device_client_desc pvr2_cli_29xxx[] = { - { .module_id = PVR2_CLIENT_ID_SAA7115 }, - { .module_id = PVR2_CLIENT_ID_MSP3400 }, - { .module_id = PVR2_CLIENT_ID_TUNER }, - { .module_id = PVR2_CLIENT_ID_DEMOD }, -}; - -#define PVR2_FIRMWARE_29xxx "v4l-pvrusb2-29xxx-01.fw" -static const char *pvr2_fw1_names_29xxx[] = { - PVR2_FIRMWARE_29xxx, -}; - -static const struct pvr2_device_desc pvr2_device_29xxx = { - .description = "WinTV PVR USB2 Model 29xxx", - .shortname = "29xxx", - .client_table.lst = pvr2_cli_29xxx, - .client_table.cnt = ARRAY_SIZE(pvr2_cli_29xxx), - .fx2_firmware.lst = pvr2_fw1_names_29xxx, - .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx), - .flag_has_hauppauge_rom = !0, - .flag_has_analogtuner = !0, - .flag_has_fmradio = !0, - .flag_has_composite = !0, - .flag_has_svideo = !0, - .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, - .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, - .ir_scheme = PVR2_IR_SCHEME_29XXX, -}; - - - -/*------------------------------------------------------------------------*/ -/* Hauppauge PVR-USB2 Model 24xxx */ - -static const struct pvr2_device_client_desc pvr2_cli_24xxx[] = { - { .module_id = PVR2_CLIENT_ID_CX25840 }, - { .module_id = PVR2_CLIENT_ID_TUNER }, - { .module_id = PVR2_CLIENT_ID_WM8775 }, - { .module_id = PVR2_CLIENT_ID_DEMOD }, -}; - -#define PVR2_FIRMWARE_24xxx "v4l-pvrusb2-24xxx-01.fw" -static const char *pvr2_fw1_names_24xxx[] = { - PVR2_FIRMWARE_24xxx, -}; - -static const struct pvr2_device_desc pvr2_device_24xxx = { - .description = "WinTV PVR USB2 Model 24xxx", - .shortname = "24xxx", - .client_table.lst = pvr2_cli_24xxx, - .client_table.cnt = ARRAY_SIZE(pvr2_cli_24xxx), - .fx2_firmware.lst = pvr2_fw1_names_24xxx, - .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_24xxx), - .flag_has_cx25840 = !0, - .flag_has_wm8775 = !0, - .flag_has_hauppauge_rom = !0, - .flag_has_analogtuner = !0, - .flag_has_fmradio = !0, - .flag_has_composite = !0, - .flag_has_svideo = !0, - .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, - .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, - .ir_scheme = PVR2_IR_SCHEME_24XXX, -}; - - - -/*------------------------------------------------------------------------*/ -/* GOTVIEW USB2.0 DVD2 */ - -static const struct pvr2_device_client_desc pvr2_cli_gotview_2[] = { - { .module_id = PVR2_CLIENT_ID_CX25840 }, - { .module_id = PVR2_CLIENT_ID_TUNER }, - { .module_id = PVR2_CLIENT_ID_DEMOD }, -}; - -static const struct pvr2_device_desc pvr2_device_gotview_2 = { - .description = "Gotview USB 2.0 DVD 2", - .shortname = "gv2", - .client_table.lst = pvr2_cli_gotview_2, - .client_table.cnt = ARRAY_SIZE(pvr2_cli_gotview_2), - .flag_has_cx25840 = !0, - .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .flag_has_analogtuner = !0, - .flag_has_fmradio = !0, - .flag_has_composite = !0, - .flag_has_svideo = !0, - .signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW, -}; - - - -/*------------------------------------------------------------------------*/ -/* GOTVIEW USB2.0 DVD Deluxe */ - -/* (same module list as gotview_2) */ - -static const struct pvr2_device_desc pvr2_device_gotview_2d = { - .description = "Gotview USB 2.0 DVD Deluxe", - .shortname = "gv2d", - .client_table.lst = pvr2_cli_gotview_2, - .client_table.cnt = ARRAY_SIZE(pvr2_cli_gotview_2), - .flag_has_cx25840 = !0, - .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .flag_has_analogtuner = !0, - .flag_has_composite = !0, - .flag_has_svideo = !0, - .signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW, -}; - - - -/*------------------------------------------------------------------------*/ -/* Terratec Grabster AV400 */ - -static const struct pvr2_device_client_desc pvr2_cli_av400[] = { - { .module_id = PVR2_CLIENT_ID_CX25840 }, -}; - -static const struct pvr2_device_desc pvr2_device_av400 = { - .description = "Terratec Grabster AV400", - .shortname = "av400", - .flag_is_experimental = 1, - .client_table.lst = pvr2_cli_av400, - .client_table.cnt = ARRAY_SIZE(pvr2_cli_av400), - .flag_has_cx25840 = !0, - .flag_has_analogtuner = 0, - .flag_has_composite = !0, - .flag_has_svideo = !0, - .signal_routing_scheme = PVR2_ROUTING_SCHEME_AV400, -}; - - - -/*------------------------------------------------------------------------*/ -/* OnAir Creator */ - -#ifdef CONFIG_VIDEO_PVRUSB2_DVB -static struct lgdt330x_config pvr2_lgdt3303_config = { - .demod_address = 0x0e, - .demod_chip = LGDT3303, - .clock_polarity_flip = 1, -}; - -static int pvr2_lgdt3303_attach(struct pvr2_dvb_adapter *adap) -{ - adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3303_config, - &adap->channel.hdw->i2c_adap); - if (adap->fe) - return 0; - - return -EIO; -} - -static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap) -{ - dvb_attach(simple_tuner_attach, adap->fe, - &adap->channel.hdw->i2c_adap, 0x61, - TUNER_LG_TDVS_H06XF); - - return 0; -} - -static const struct pvr2_dvb_props pvr2_onair_creator_fe_props = { - .frontend_attach = pvr2_lgdt3303_attach, - .tuner_attach = pvr2_lgh06xf_attach, -}; -#endif - -static const struct pvr2_device_client_desc pvr2_cli_onair_creator[] = { - { .module_id = PVR2_CLIENT_ID_SAA7115 }, - { .module_id = PVR2_CLIENT_ID_CS53L32A }, - { .module_id = PVR2_CLIENT_ID_TUNER }, -}; - -static const struct pvr2_device_desc pvr2_device_onair_creator = { - .description = "OnAir Creator Hybrid USB tuner", - .shortname = "oac", - .client_table.lst = pvr2_cli_onair_creator, - .client_table.cnt = ARRAY_SIZE(pvr2_cli_onair_creator), - .default_tuner_type = TUNER_LG_TDVS_H06XF, - .flag_has_analogtuner = !0, - .flag_has_composite = !0, - .flag_has_svideo = !0, - .flag_digital_requires_cx23416 = !0, - .signal_routing_scheme = PVR2_ROUTING_SCHEME_ONAIR, - .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, - .default_std_mask = V4L2_STD_NTSC_M, -#ifdef CONFIG_VIDEO_PVRUSB2_DVB - .dvb_props = &pvr2_onair_creator_fe_props, -#endif -}; - - - -/*------------------------------------------------------------------------*/ -/* OnAir USB 2.0 */ - -#ifdef CONFIG_VIDEO_PVRUSB2_DVB -static struct lgdt330x_config pvr2_lgdt3302_config = { - .demod_address = 0x0e, - .demod_chip = LGDT3302, -}; - -static int pvr2_lgdt3302_attach(struct pvr2_dvb_adapter *adap) -{ - adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3302_config, - &adap->channel.hdw->i2c_adap); - if (adap->fe) - return 0; - - return -EIO; -} - -static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap) -{ - dvb_attach(simple_tuner_attach, adap->fe, - &adap->channel.hdw->i2c_adap, 0x61, - TUNER_PHILIPS_FCV1236D); - - return 0; -} - -static const struct pvr2_dvb_props pvr2_onair_usb2_fe_props = { - .frontend_attach = pvr2_lgdt3302_attach, - .tuner_attach = pvr2_fcv1236d_attach, -}; -#endif - -static const struct pvr2_device_client_desc pvr2_cli_onair_usb2[] = { - { .module_id = PVR2_CLIENT_ID_SAA7115 }, - { .module_id = PVR2_CLIENT_ID_CS53L32A }, - { .module_id = PVR2_CLIENT_ID_TUNER }, -}; - -static const struct pvr2_device_desc pvr2_device_onair_usb2 = { - .description = "OnAir USB2 Hybrid USB tuner", - .shortname = "oa2", - .client_table.lst = pvr2_cli_onair_usb2, - .client_table.cnt = ARRAY_SIZE(pvr2_cli_onair_usb2), - .default_tuner_type = TUNER_PHILIPS_FCV1236D, - .flag_has_analogtuner = !0, - .flag_has_composite = !0, - .flag_has_svideo = !0, - .flag_digital_requires_cx23416 = !0, - .signal_routing_scheme = PVR2_ROUTING_SCHEME_ONAIR, - .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, - .default_std_mask = V4L2_STD_NTSC_M, -#ifdef CONFIG_VIDEO_PVRUSB2_DVB - .dvb_props = &pvr2_onair_usb2_fe_props, -#endif -}; - - - -/*------------------------------------------------------------------------*/ -/* Hauppauge PVR-USB2 Model 73xxx */ - -#ifdef CONFIG_VIDEO_PVRUSB2_DVB -static struct tda10048_config hauppauge_tda10048_config = { - .demod_address = 0x10 >> 1, - .output_mode = TDA10048_PARALLEL_OUTPUT, - .fwbulkwritelen = TDA10048_BULKWRITE_50, - .inversion = TDA10048_INVERSION_ON, - .dtv6_if_freq_khz = TDA10048_IF_3300, - .dtv7_if_freq_khz = TDA10048_IF_3800, - .dtv8_if_freq_khz = TDA10048_IF_4300, - .clk_freq_khz = TDA10048_CLK_16000, - .disable_gate_access = 1, -}; - -static struct tda829x_config tda829x_no_probe = { - .probe_tuner = TDA829X_DONT_PROBE, -}; - -static struct tda18271_std_map hauppauge_tda18271_dvbt_std_map = { - .dvbt_6 = { .if_freq = 3300, .agc_mode = 3, .std = 4, - .if_lvl = 1, .rfagc_top = 0x37, }, - .dvbt_7 = { .if_freq = 3800, .agc_mode = 3, .std = 5, - .if_lvl = 1, .rfagc_top = 0x37, }, - .dvbt_8 = { .if_freq = 4300, .agc_mode = 3, .std = 6, - .if_lvl = 1, .rfagc_top = 0x37, }, -}; - -static struct tda18271_config hauppauge_tda18271_dvb_config = { - .std_map = &hauppauge_tda18271_dvbt_std_map, - .gate = TDA18271_GATE_ANALOG, - .output_opt = TDA18271_OUTPUT_LT_OFF, -}; - -static int pvr2_tda10048_attach(struct pvr2_dvb_adapter *adap) -{ - adap->fe = dvb_attach(tda10048_attach, &hauppauge_tda10048_config, - &adap->channel.hdw->i2c_adap); - if (adap->fe) - return 0; - - return -EIO; -} - -static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap) -{ - dvb_attach(tda829x_attach, adap->fe, - &adap->channel.hdw->i2c_adap, 0x42, - &tda829x_no_probe); - dvb_attach(tda18271_attach, adap->fe, 0x60, - &adap->channel.hdw->i2c_adap, - &hauppauge_tda18271_dvb_config); - - return 0; -} - -static const struct pvr2_dvb_props pvr2_73xxx_dvb_props = { - .frontend_attach = pvr2_tda10048_attach, - .tuner_attach = pvr2_73xxx_tda18271_8295_attach, -}; -#endif - -static const struct pvr2_device_client_desc pvr2_cli_73xxx[] = { - { .module_id = PVR2_CLIENT_ID_CX25840 }, - { .module_id = PVR2_CLIENT_ID_TUNER, - .i2c_address_list = "\x42"}, -}; - -#define PVR2_FIRMWARE_73xxx "v4l-pvrusb2-73xxx-01.fw" -static const char *pvr2_fw1_names_73xxx[] = { - PVR2_FIRMWARE_73xxx, -}; - -static const struct pvr2_device_desc pvr2_device_73xxx = { - .description = "WinTV HVR-1900 Model 73xxx", - .shortname = "73xxx", - .client_table.lst = pvr2_cli_73xxx, - .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), - .fx2_firmware.lst = pvr2_fw1_names_73xxx, - .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_73xxx), - .flag_has_cx25840 = !0, - .flag_has_hauppauge_rom = !0, - .flag_has_analogtuner = !0, - .flag_has_composite = !0, - .flag_has_svideo = !0, - .flag_fx2_16kb = !0, - .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, - .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE, - .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, - .ir_scheme = PVR2_IR_SCHEME_ZILOG, -#ifdef CONFIG_VIDEO_PVRUSB2_DVB - .dvb_props = &pvr2_73xxx_dvb_props, -#endif -}; - - - -/*------------------------------------------------------------------------*/ -/* Hauppauge PVR-USB2 Model 75xxx */ - -#ifdef CONFIG_VIDEO_PVRUSB2_DVB -static struct s5h1409_config pvr2_s5h1409_config = { - .demod_address = 0x32 >> 1, - .output_mode = S5H1409_PARALLEL_OUTPUT, - .gpio = S5H1409_GPIO_OFF, - .qam_if = 4000, - .inversion = S5H1409_INVERSION_ON, - .status_mode = S5H1409_DEMODLOCKING, -}; - -static struct s5h1411_config pvr2_s5h1411_config = { - .output_mode = S5H1411_PARALLEL_OUTPUT, - .gpio = S5H1411_GPIO_OFF, - .vsb_if = S5H1411_IF_44000, - .qam_if = S5H1411_IF_4000, - .inversion = S5H1411_INVERSION_ON, - .status_mode = S5H1411_DEMODLOCKING, -}; - -static struct tda18271_std_map hauppauge_tda18271_std_map = { - .atsc_6 = { .if_freq = 5380, .agc_mode = 3, .std = 3, - .if_lvl = 6, .rfagc_top = 0x37, }, - .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 0, - .if_lvl = 6, .rfagc_top = 0x37, }, -}; - -static struct tda18271_config hauppauge_tda18271_config = { - .std_map = &hauppauge_tda18271_std_map, - .gate = TDA18271_GATE_ANALOG, - .output_opt = TDA18271_OUTPUT_LT_OFF, -}; - -static int pvr2_s5h1409_attach(struct pvr2_dvb_adapter *adap) -{ - adap->fe = dvb_attach(s5h1409_attach, &pvr2_s5h1409_config, - &adap->channel.hdw->i2c_adap); - if (adap->fe) - return 0; - - return -EIO; -} - -static int pvr2_s5h1411_attach(struct pvr2_dvb_adapter *adap) -{ - adap->fe = dvb_attach(s5h1411_attach, &pvr2_s5h1411_config, - &adap->channel.hdw->i2c_adap); - if (adap->fe) - return 0; - - return -EIO; -} - -static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap) -{ - dvb_attach(tda829x_attach, adap->fe, - &adap->channel.hdw->i2c_adap, 0x42, - &tda829x_no_probe); - dvb_attach(tda18271_attach, adap->fe, 0x60, - &adap->channel.hdw->i2c_adap, - &hauppauge_tda18271_config); - - return 0; -} - -static const struct pvr2_dvb_props pvr2_750xx_dvb_props = { - .frontend_attach = pvr2_s5h1409_attach, - .tuner_attach = pvr2_tda18271_8295_attach, -}; - -static const struct pvr2_dvb_props pvr2_751xx_dvb_props = { - .frontend_attach = pvr2_s5h1411_attach, - .tuner_attach = pvr2_tda18271_8295_attach, -}; -#endif - -#define PVR2_FIRMWARE_75xxx "v4l-pvrusb2-73xxx-01.fw" -static const char *pvr2_fw1_names_75xxx[] = { - PVR2_FIRMWARE_75xxx, -}; - -static const struct pvr2_device_desc pvr2_device_750xx = { - .description = "WinTV HVR-1950 Model 750xx", - .shortname = "750xx", - .client_table.lst = pvr2_cli_73xxx, - .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), - .fx2_firmware.lst = pvr2_fw1_names_75xxx, - .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx), - .flag_has_cx25840 = !0, - .flag_has_hauppauge_rom = !0, - .flag_has_analogtuner = !0, - .flag_has_composite = !0, - .flag_has_svideo = !0, - .flag_fx2_16kb = !0, - .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, - .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE, - .default_std_mask = V4L2_STD_NTSC_M, - .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, - .ir_scheme = PVR2_IR_SCHEME_ZILOG, -#ifdef CONFIG_VIDEO_PVRUSB2_DVB - .dvb_props = &pvr2_750xx_dvb_props, -#endif -}; - -static const struct pvr2_device_desc pvr2_device_751xx = { - .description = "WinTV HVR-1950 Model 751xx", - .shortname = "751xx", - .client_table.lst = pvr2_cli_73xxx, - .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), - .fx2_firmware.lst = pvr2_fw1_names_75xxx, - .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx), - .flag_has_cx25840 = !0, - .flag_has_hauppauge_rom = !0, - .flag_has_analogtuner = !0, - .flag_has_composite = !0, - .flag_has_svideo = !0, - .flag_fx2_16kb = !0, - .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, - .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE, - .default_std_mask = V4L2_STD_NTSC_M, - .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE, - .ir_scheme = PVR2_IR_SCHEME_ZILOG, -#ifdef CONFIG_VIDEO_PVRUSB2_DVB - .dvb_props = &pvr2_751xx_dvb_props, -#endif -}; - - - -/*------------------------------------------------------------------------*/ - -struct usb_device_id pvr2_device_table[] = { - { USB_DEVICE(0x2040, 0x2900), - .driver_info = (kernel_ulong_t)&pvr2_device_29xxx}, - { USB_DEVICE(0x2040, 0x2950), /* Logically identical to 2900 */ - .driver_info = (kernel_ulong_t)&pvr2_device_29xxx}, - { USB_DEVICE(0x2040, 0x2400), - .driver_info = (kernel_ulong_t)&pvr2_device_24xxx}, - { USB_DEVICE(0x1164, 0x0622), - .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2}, - { USB_DEVICE(0x1164, 0x0602), - .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2d}, - { USB_DEVICE(0x11ba, 0x1003), - .driver_info = (kernel_ulong_t)&pvr2_device_onair_creator}, - { USB_DEVICE(0x11ba, 0x1001), - .driver_info = (kernel_ulong_t)&pvr2_device_onair_usb2}, - { USB_DEVICE(0x2040, 0x7300), - .driver_info = (kernel_ulong_t)&pvr2_device_73xxx}, - { USB_DEVICE(0x2040, 0x7500), - .driver_info = (kernel_ulong_t)&pvr2_device_750xx}, - { USB_DEVICE(0x2040, 0x7501), - .driver_info = (kernel_ulong_t)&pvr2_device_751xx}, - { USB_DEVICE(0x0ccd, 0x0039), - .driver_info = (kernel_ulong_t)&pvr2_device_av400}, - { } -}; - -MODULE_DEVICE_TABLE(usb, pvr2_device_table); -MODULE_FIRMWARE(PVR2_FIRMWARE_29xxx); -MODULE_FIRMWARE(PVR2_FIRMWARE_24xxx); -MODULE_FIRMWARE(PVR2_FIRMWARE_73xxx); -MODULE_FIRMWARE(PVR2_FIRMWARE_75xxx); - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h deleted file mode 100644 index 273c8d4b3853..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __PVRUSB2_DEVATTR_H -#define __PVRUSB2_DEVATTR_H - -#include <linux/mod_devicetable.h> -#include <linux/videodev2.h> -#ifdef CONFIG_VIDEO_PVRUSB2_DVB -#include "pvrusb2-dvb.h" -#endif - -/* - - This header defines structures used to describe attributes of a device. - -*/ - - -#define PVR2_CLIENT_ID_NULL 0 -#define PVR2_CLIENT_ID_MSP3400 1 -#define PVR2_CLIENT_ID_CX25840 2 -#define PVR2_CLIENT_ID_SAA7115 3 -#define PVR2_CLIENT_ID_TUNER 4 -#define PVR2_CLIENT_ID_CS53L32A 5 -#define PVR2_CLIENT_ID_WM8775 6 -#define PVR2_CLIENT_ID_DEMOD 7 - -struct pvr2_device_client_desc { - /* One ovr PVR2_CLIENT_ID_xxxx */ - unsigned char module_id; - - /* Null-terminated array of I2C addresses to try in order - initialize the module. It's safe to make this null terminated - since we're never going to encounter an i2c device with an - address of zero. If this is a null pointer or zero-length, - then no I2C addresses have been specified, in which case we'll - try some compiled in defaults for now. */ - unsigned char *i2c_address_list; -}; - -struct pvr2_device_client_table { - const struct pvr2_device_client_desc *lst; - unsigned char cnt; -}; - - -struct pvr2_string_table { - const char **lst; - unsigned int cnt; -}; - -#define PVR2_ROUTING_SCHEME_HAUPPAUGE 0 -#define PVR2_ROUTING_SCHEME_GOTVIEW 1 -#define PVR2_ROUTING_SCHEME_ONAIR 2 -#define PVR2_ROUTING_SCHEME_AV400 3 - -#define PVR2_DIGITAL_SCHEME_NONE 0 -#define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1 -#define PVR2_DIGITAL_SCHEME_ONAIR 2 - -#define PVR2_LED_SCHEME_NONE 0 -#define PVR2_LED_SCHEME_HAUPPAUGE 1 - -#define PVR2_IR_SCHEME_NONE 0 -#define PVR2_IR_SCHEME_24XXX 1 /* FX2-controlled IR */ -#define PVR2_IR_SCHEME_ZILOG 2 /* HVR-1950 style (must be taken out of reset) */ -#define PVR2_IR_SCHEME_24XXX_MCE 3 /* 24xxx MCE device */ -#define PVR2_IR_SCHEME_29XXX 4 /* Original 29xxx device */ - -/* This describes a particular hardware type (except for the USB device ID - which must live in a separate structure due to environmental - constraints). See the top of pvrusb2-hdw.c for where this is - instantiated. */ -struct pvr2_device_desc { - /* Single line text description of hardware */ - const char *description; - - /* Single token identifier for hardware */ - const char *shortname; - - /* List of additional client modules we need to load */ - struct pvr2_string_table client_modules; - - /* List of defined client modules we need to load */ - struct pvr2_device_client_table client_table; - - /* List of FX2 firmware file names we should search; if empty then - FX2 firmware check / load is skipped and we assume the device - was initialized from internal ROM. */ - struct pvr2_string_table fx2_firmware; - -#ifdef CONFIG_VIDEO_PVRUSB2_DVB - /* callback functions to handle attachment of digital tuner & demod */ - const struct pvr2_dvb_props *dvb_props; - -#endif - /* Initial standard bits to use for this device, if not zero. - Anything set here is also implied as an available standard. - Note: This is ignored if overridden on the module load line via - the video_std module option. */ - v4l2_std_id default_std_mask; - - /* V4L tuner type ID to use with this device (only used if the - driver could not discover the type any other way). */ - int default_tuner_type; - - /* Signal routing scheme used by device, contains one of - PVR2_ROUTING_SCHEME_XXX. Schemes have to be defined as we - encounter them. This is an arbitrary integer scheme id; its - meaning is contained entirely within the driver and is - interpreted by logic which must send commands to the chip-level - drivers (search for things which touch this field). */ - unsigned char signal_routing_scheme; - - /* Indicates scheme for controlling device's LED (if any). The - driver will turn on the LED when streaming is underway. This - contains one of PVR2_LED_SCHEME_XXX. */ - unsigned char led_scheme; - - /* Control scheme to use if there is a digital tuner. This - contains one of PVR2_DIGITAL_SCHEME_XXX. This is an arbitrary - integer scheme id; its meaning is contained entirely within the - driver and is interpreted by logic which must control the - streaming pathway (search for things which touch this field). */ - unsigned char digital_control_scheme; - - /* If set, we don't bother trying to load cx23416 firmware. */ - unsigned int flag_skip_cx23416_firmware:1; - - /* If set, the encoder must be healthy in order for digital mode to - work (otherwise we assume that digital streaming will work even - if we fail to locate firmware for the encoder). If the device - doesn't support digital streaming then this flag has no - effect. */ - unsigned int flag_digital_requires_cx23416:1; - - /* Device has a hauppauge eeprom which we can interrogate. */ - unsigned int flag_has_hauppauge_rom:1; - - /* Device does not require a powerup command to be issued. */ - unsigned int flag_no_powerup:1; - - /* Device has a cx25840 - this enables special additional logic to - handle it. */ - unsigned int flag_has_cx25840:1; - - /* Device has a wm8775 - this enables special additional logic to - ensure that it is found. */ - unsigned int flag_has_wm8775:1; - - /* Indicate IR scheme of hardware. If not set, then it is assumed - that IR can work without any help from the driver. */ - unsigned int ir_scheme:3; - - /* These bits define which kinds of sources the device can handle. - Note: Digital tuner presence is inferred by the - digital_control_scheme enumeration. */ - unsigned int flag_has_fmradio:1; /* Has FM radio receiver */ - unsigned int flag_has_analogtuner:1; /* Has analog tuner */ - unsigned int flag_has_composite:1; /* Has composite input */ - unsigned int flag_has_svideo:1; /* Has s-video input */ - unsigned int flag_fx2_16kb:1; /* 16KB FX2 firmware OK here */ - - /* If this driver is considered experimental, i.e. not all aspects - are working correctly and/or it is untested, mark that fact - with this flag. */ - unsigned int flag_is_experimental:1; -}; - -extern struct usb_device_id pvr2_device_table[]; - -#endif /* __PVRUSB2_HDW_INTERNAL_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c deleted file mode 100644 index 8c95793433e7..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ /dev/null @@ -1,435 +0,0 @@ -/* - * pvrusb2-dvb.c - linux-dvb api interface to the pvrusb2 driver. - * - * Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/kthread.h> -#include <linux/freezer.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include "dvbdev.h" -#include "pvrusb2-debug.h" -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-hdw.h" -#include "pvrusb2-io.h" -#include "pvrusb2-dvb.h" - -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - -static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap) -{ - int ret; - unsigned int count; - struct pvr2_buffer *bp; - struct pvr2_stream *stream; - - pvr2_trace(PVR2_TRACE_DVB_FEED, "dvb feed thread started"); - set_freezable(); - - stream = adap->channel.stream->stream; - - for (;;) { - if (kthread_should_stop()) break; - - /* Not sure about this... */ - try_to_freeze(); - - bp = pvr2_stream_get_ready_buffer(stream); - if (bp != NULL) { - count = pvr2_buffer_get_count(bp); - if (count) { - dvb_dmx_swfilter( - &adap->demux, - adap->buffer_storage[ - pvr2_buffer_get_id(bp)], - count); - } else { - ret = pvr2_buffer_get_status(bp); - if (ret < 0) break; - } - ret = pvr2_buffer_queue(bp); - if (ret < 0) break; - - /* Since we know we did something to a buffer, - just go back and try again. No point in - blocking unless we really ran out of - buffers to process. */ - continue; - } - - - /* Wait until more buffers become available or we're - told not to wait any longer. */ - ret = wait_event_interruptible( - adap->buffer_wait_data, - (pvr2_stream_get_ready_count(stream) > 0) || - kthread_should_stop()); - if (ret < 0) break; - } - - /* If we get here and ret is < 0, then an error has occurred. - Probably would be a good idea to communicate that to DVB core... */ - - pvr2_trace(PVR2_TRACE_DVB_FEED, "dvb feed thread stopped"); - - return 0; -} - -static int pvr2_dvb_feed_thread(void *data) -{ - int stat = pvr2_dvb_feed_func(data); - /* from videobuf-dvb.c: */ - while (!kthread_should_stop()) { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - } - return stat; -} - -static void pvr2_dvb_notify(struct pvr2_dvb_adapter *adap) -{ - wake_up(&adap->buffer_wait_data); -} - -static void pvr2_dvb_stream_end(struct pvr2_dvb_adapter *adap) -{ - unsigned int idx; - struct pvr2_stream *stream; - - if (adap->thread) { - kthread_stop(adap->thread); - adap->thread = NULL; - } - - if (adap->channel.stream) { - stream = adap->channel.stream->stream; - } else { - stream = NULL; - } - if (stream) { - pvr2_hdw_set_streaming(adap->channel.hdw, 0); - pvr2_stream_set_callback(stream, NULL, NULL); - pvr2_stream_kill(stream); - pvr2_stream_set_buffer_count(stream, 0); - pvr2_channel_claim_stream(&adap->channel, NULL); - } - - if (adap->stream_run) { - for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) { - if (!(adap->buffer_storage[idx])) continue; - kfree(adap->buffer_storage[idx]); - adap->buffer_storage[idx] = NULL; - } - adap->stream_run = 0; - } -} - -static int pvr2_dvb_stream_do_start(struct pvr2_dvb_adapter *adap) -{ - struct pvr2_context *pvr = adap->channel.mc_head; - unsigned int idx; - int ret; - struct pvr2_buffer *bp; - struct pvr2_stream *stream = NULL; - - if (adap->stream_run) return -EIO; - - ret = pvr2_channel_claim_stream(&adap->channel, &pvr->video_stream); - /* somebody else already has the stream */ - if (ret < 0) return ret; - - stream = adap->channel.stream->stream; - - for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) { - adap->buffer_storage[idx] = kmalloc(PVR2_DVB_BUFFER_SIZE, - GFP_KERNEL); - if (!(adap->buffer_storage[idx])) return -ENOMEM; - } - - pvr2_stream_set_callback(pvr->video_stream.stream, - (pvr2_stream_callback) pvr2_dvb_notify, adap); - - ret = pvr2_stream_set_buffer_count(stream, PVR2_DVB_BUFFER_COUNT); - if (ret < 0) return ret; - - for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) { - bp = pvr2_stream_get_buffer(stream, idx); - pvr2_buffer_set_buffer(bp, - adap->buffer_storage[idx], - PVR2_DVB_BUFFER_SIZE); - } - - ret = pvr2_hdw_set_streaming(adap->channel.hdw, 1); - if (ret < 0) return ret; - - while ((bp = pvr2_stream_get_idle_buffer(stream)) != NULL) { - ret = pvr2_buffer_queue(bp); - if (ret < 0) return ret; - } - - adap->thread = kthread_run(pvr2_dvb_feed_thread, adap, "pvrusb2-dvb"); - - if (IS_ERR(adap->thread)) { - ret = PTR_ERR(adap->thread); - adap->thread = NULL; - return ret; - } - - adap->stream_run = !0; - - return 0; -} - -static int pvr2_dvb_stream_start(struct pvr2_dvb_adapter *adap) -{ - int ret = pvr2_dvb_stream_do_start(adap); - if (ret < 0) pvr2_dvb_stream_end(adap); - return ret; -} - -static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) -{ - struct pvr2_dvb_adapter *adap = dvbdmxfeed->demux->priv; - int ret = 0; - - if (adap == NULL) return -ENODEV; - - mutex_lock(&adap->lock); - do { - if (onoff) { - if (!adap->feedcount) { - pvr2_trace(PVR2_TRACE_DVB_FEED, - "start feeding demux"); - ret = pvr2_dvb_stream_start(adap); - if (ret < 0) break; - } - (adap->feedcount)++; - } else if (adap->feedcount > 0) { - (adap->feedcount)--; - if (!adap->feedcount) { - pvr2_trace(PVR2_TRACE_DVB_FEED, - "stop feeding demux"); - pvr2_dvb_stream_end(adap); - } - } - } while (0); - mutex_unlock(&adap->lock); - - return ret; -} - -static int pvr2_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) -{ - pvr2_trace(PVR2_TRACE_DVB_FEED, "start pid: 0x%04x", dvbdmxfeed->pid); - return pvr2_dvb_ctrl_feed(dvbdmxfeed, 1); -} - -static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) -{ - pvr2_trace(PVR2_TRACE_DVB_FEED, "stop pid: 0x%04x", dvbdmxfeed->pid); - return pvr2_dvb_ctrl_feed(dvbdmxfeed, 0); -} - -static int pvr2_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) -{ - struct pvr2_dvb_adapter *adap = fe->dvb->priv; - return pvr2_channel_limit_inputs( - &adap->channel, - (acquire ? (1 << PVR2_CVAL_INPUT_DTV) : 0)); -} - -static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap) -{ - int ret; - - ret = dvb_register_adapter(&adap->dvb_adap, "pvrusb2-dvb", - THIS_MODULE/*&hdw->usb_dev->owner*/, - &adap->channel.hdw->usb_dev->dev, - adapter_nr); - if (ret < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "dvb_register_adapter failed: error %d", ret); - goto err; - } - adap->dvb_adap.priv = adap; - - adap->demux.dmx.capabilities = DMX_TS_FILTERING | - DMX_SECTION_FILTERING | - DMX_MEMORY_BASED_FILTERING; - adap->demux.priv = adap; - adap->demux.filternum = 256; - adap->demux.feednum = 256; - adap->demux.start_feed = pvr2_dvb_start_feed; - adap->demux.stop_feed = pvr2_dvb_stop_feed; - adap->demux.write_to_decoder = NULL; - - ret = dvb_dmx_init(&adap->demux); - if (ret < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "dvb_dmx_init failed: error %d", ret); - goto err_dmx; - } - - adap->dmxdev.filternum = adap->demux.filternum; - adap->dmxdev.demux = &adap->demux.dmx; - adap->dmxdev.capabilities = 0; - - ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap); - if (ret < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "dvb_dmxdev_init failed: error %d", ret); - goto err_dmx_dev; - } - - dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx); - - return 0; - -err_dmx_dev: - dvb_dmx_release(&adap->demux); -err_dmx: - dvb_unregister_adapter(&adap->dvb_adap); -err: - return ret; -} - -static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap) -{ - pvr2_trace(PVR2_TRACE_INFO, "unregistering DVB devices"); - dvb_net_release(&adap->dvb_net); - adap->demux.dmx.close(&adap->demux.dmx); - dvb_dmxdev_release(&adap->dmxdev); - dvb_dmx_release(&adap->demux); - dvb_unregister_adapter(&adap->dvb_adap); - return 0; -} - -static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap) -{ - struct pvr2_hdw *hdw = adap->channel.hdw; - const struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props; - int ret = 0; - - if (dvb_props == NULL) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, "fe_props not defined!"); - return -EINVAL; - } - - ret = pvr2_channel_limit_inputs( - &adap->channel, - (1 << PVR2_CVAL_INPUT_DTV)); - if (ret) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "failed to grab control of dtv input (code=%d)", - ret); - return ret; - } - - if (dvb_props->frontend_attach == NULL) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "frontend_attach not defined!"); - ret = -EINVAL; - goto done; - } - - if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) { - - if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "frontend registration failed!"); - dvb_frontend_detach(adap->fe); - adap->fe = NULL; - ret = -ENODEV; - goto done; - } - - if (dvb_props->tuner_attach) - dvb_props->tuner_attach(adap); - - if (adap->fe->ops.analog_ops.standby) - adap->fe->ops.analog_ops.standby(adap->fe); - - /* Ensure all frontends negotiate bus access */ - adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl; - - } else { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "no frontend was attached!"); - ret = -ENODEV; - return ret; - } - - done: - pvr2_channel_limit_inputs(&adap->channel, 0); - return ret; -} - -static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap) -{ - if (adap->fe != NULL) { - dvb_unregister_frontend(adap->fe); - dvb_frontend_detach(adap->fe); - } - return 0; -} - -static void pvr2_dvb_destroy(struct pvr2_dvb_adapter *adap) -{ - pvr2_dvb_stream_end(adap); - pvr2_dvb_frontend_exit(adap); - pvr2_dvb_adapter_exit(adap); - pvr2_channel_done(&adap->channel); - kfree(adap); -} - -static void pvr2_dvb_internal_check(struct pvr2_channel *chp) -{ - struct pvr2_dvb_adapter *adap; - adap = container_of(chp, struct pvr2_dvb_adapter, channel); - if (!adap->channel.mc_head->disconnect_flag) return; - pvr2_dvb_destroy(adap); -} - -struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr) -{ - int ret = 0; - struct pvr2_dvb_adapter *adap; - if (!pvr->hdw->hdw_desc->dvb_props) { - /* Device lacks a digital interface so don't set up - the DVB side of the driver either. For now. */ - return NULL; - } - adap = kzalloc(sizeof(*adap), GFP_KERNEL); - if (!adap) return adap; - pvr2_channel_init(&adap->channel, pvr); - adap->channel.check_func = pvr2_dvb_internal_check; - init_waitqueue_head(&adap->buffer_wait_data); - mutex_init(&adap->lock); - ret = pvr2_dvb_adapter_init(adap); - if (ret < 0) goto fail1; - ret = pvr2_dvb_frontend_init(adap); - if (ret < 0) goto fail2; - return adap; - -fail2: - pvr2_dvb_adapter_exit(adap); -fail1: - pvr2_channel_done(&adap->channel); - return NULL; -} - diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.h b/drivers/media/video/pvrusb2/pvrusb2-dvb.h deleted file mode 100644 index 884ff916a352..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __PVRUSB2_DVB_H__ -#define __PVRUSB2_DVB_H__ - -#include "dvb_frontend.h" -#include "dvb_demux.h" -#include "dvb_net.h" -#include "dmxdev.h" -#include "pvrusb2-context.h" - -#define PVR2_DVB_BUFFER_COUNT 32 -#define PVR2_DVB_BUFFER_SIZE PAGE_ALIGN(0x4000) - -struct pvr2_dvb_adapter { - struct pvr2_channel channel; - - struct dvb_adapter dvb_adap; - struct dmxdev dmxdev; - struct dvb_demux demux; - struct dvb_net dvb_net; - struct dvb_frontend *fe; - - int feedcount; - int max_feed_count; - - struct task_struct *thread; - struct mutex lock; - - unsigned int stream_run:1; - - wait_queue_head_t buffer_wait_data; - char *buffer_storage[PVR2_DVB_BUFFER_COUNT]; -}; - -struct pvr2_dvb_props { - int (*frontend_attach) (struct pvr2_dvb_adapter *); - int (*tuner_attach) (struct pvr2_dvb_adapter *); -}; - -struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr); - -#endif /* __PVRUSB2_DVB_H__ */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-eeprom.c b/drivers/media/video/pvrusb2/pvrusb2-eeprom.c deleted file mode 100644 index 9515f3a68f8f..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-eeprom.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/slab.h> -#include "pvrusb2-eeprom.h" -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-debug.h" - -#define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__) - - - -/* - - Read and analyze data in the eeprom. Use tveeprom to figure out - the packet structure, since this is another Hauppauge device and - internally it has a family resemblance to ivtv-type devices - -*/ - -#include <media/tveeprom.h> - -/* We seem to only be interested in the last 128 bytes of the EEPROM */ -#define EEPROM_SIZE 128 - -/* Grab EEPROM contents, needed for direct method. */ -static u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw) -{ - struct i2c_msg msg[2]; - u8 *eeprom; - u8 iadd[2]; - u8 addr; - u16 eepromSize; - unsigned int offs; - int ret; - int mode16 = 0; - unsigned pcnt,tcnt; - eeprom = kmalloc(EEPROM_SIZE,GFP_KERNEL); - if (!eeprom) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Failed to allocate memory" - " required to read eeprom"); - return NULL; - } - - trace_eeprom("Value for eeprom addr from controller was 0x%x", - hdw->eeprom_addr); - addr = hdw->eeprom_addr; - /* Seems that if the high bit is set, then the *real* eeprom - address is shifted right now bit position (noticed this in - newer PVR USB2 hardware) */ - if (addr & 0x80) addr >>= 1; - - /* FX2 documentation states that a 16bit-addressed eeprom is - expected if the I2C address is an odd number (yeah, this is - strange but it's what they do) */ - mode16 = (addr & 1); - eepromSize = (mode16 ? 4096 : 256); - trace_eeprom("Examining %d byte eeprom at location 0x%x" - " using %d bit addressing",eepromSize,addr, - mode16 ? 16 : 8); - - msg[0].addr = addr; - msg[0].flags = 0; - msg[0].len = mode16 ? 2 : 1; - msg[0].buf = iadd; - msg[1].addr = addr; - msg[1].flags = I2C_M_RD; - - /* We have to do the actual eeprom data fetch ourselves, because - (1) we're only fetching part of the eeprom, and (2) if we were - getting the whole thing our I2C driver can't grab it in one - pass - which is what tveeprom is otherwise going to attempt */ - memset(eeprom,0,EEPROM_SIZE); - for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) { - pcnt = 16; - if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt; - offs = tcnt + (eepromSize - EEPROM_SIZE); - if (mode16) { - iadd[0] = offs >> 8; - iadd[1] = offs; - } else { - iadd[0] = offs; - } - msg[1].len = pcnt; - msg[1].buf = eeprom+tcnt; - if ((ret = i2c_transfer(&hdw->i2c_adap, - msg,ARRAY_SIZE(msg))) != 2) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "eeprom fetch set offs err=%d",ret); - kfree(eeprom); - return NULL; - } - } - return eeprom; -} - - -/* Directly call eeprom analysis function within tveeprom. */ -int pvr2_eeprom_analyze(struct pvr2_hdw *hdw) -{ - u8 *eeprom; - struct tveeprom tvdata; - - memset(&tvdata,0,sizeof(tvdata)); - - eeprom = pvr2_eeprom_fetch(hdw); - if (!eeprom) return -EINVAL; - - { - struct i2c_client fake_client; - /* Newer version expects a useless client interface */ - fake_client.addr = hdw->eeprom_addr; - fake_client.adapter = &hdw->i2c_adap; - tveeprom_hauppauge_analog(&fake_client,&tvdata,eeprom); - } - - trace_eeprom("eeprom assumed v4l tveeprom module"); - trace_eeprom("eeprom direct call results:"); - trace_eeprom("has_radio=%d",tvdata.has_radio); - trace_eeprom("tuner_type=%d",tvdata.tuner_type); - trace_eeprom("tuner_formats=0x%x",tvdata.tuner_formats); - trace_eeprom("audio_processor=%d",tvdata.audio_processor); - trace_eeprom("model=%d",tvdata.model); - trace_eeprom("revision=%d",tvdata.revision); - trace_eeprom("serial_number=%d",tvdata.serial_number); - trace_eeprom("rev_str=%s",tvdata.rev_str); - hdw->tuner_type = tvdata.tuner_type; - hdw->tuner_updated = !0; - hdw->serial_number = tvdata.serial_number; - hdw->std_mask_eeprom = tvdata.tuner_formats; - - kfree(eeprom); - - return 0; -} - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-eeprom.h b/drivers/media/video/pvrusb2/pvrusb2-eeprom.h deleted file mode 100644 index cca3216f94cc..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-eeprom.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef __PVRUSB2_EEPROM_H -#define __PVRUSB2_EEPROM_H - -struct pvr2_hdw; - -int pvr2_eeprom_analyze(struct pvr2_hdw *); - -#endif /* __PVRUSB2_EEPROM_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c deleted file mode 100644 index e046fdaec5ae..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/device.h> // for linux/firmware.h -#include <linux/firmware.h> -#include "pvrusb2-util.h" -#include "pvrusb2-encoder.h" -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-debug.h" -#include "pvrusb2-fx2-cmd.h" - - - -/* Firmware mailbox flags - definitions found from ivtv */ -#define IVTV_MBOX_FIRMWARE_DONE 0x00000004 -#define IVTV_MBOX_DRIVER_DONE 0x00000002 -#define IVTV_MBOX_DRIVER_BUSY 0x00000001 - -#define MBOX_BASE 0x44 - - -static int pvr2_encoder_write_words(struct pvr2_hdw *hdw, - unsigned int offs, - const u32 *data, unsigned int dlen) -{ - unsigned int idx,addr; - unsigned int bAddr; - int ret; - unsigned int chunkCnt; - - /* - - Format: First byte must be 0x01. Remaining 32 bit words are - spread out into chunks of 7 bytes each, with the first 4 bytes - being the data word (little endian), and the next 3 bytes - being the address where that data word is to be written (big - endian). Repeat request for additional words, with offset - adjusted accordingly. - - */ - while (dlen) { - chunkCnt = 8; - if (chunkCnt > dlen) chunkCnt = dlen; - memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer)); - bAddr = 0; - hdw->cmd_buffer[bAddr++] = FX2CMD_MEM_WRITE_DWORD; - for (idx = 0; idx < chunkCnt; idx++) { - addr = idx + offs; - hdw->cmd_buffer[bAddr+6] = (addr & 0xffu); - hdw->cmd_buffer[bAddr+5] = ((addr>>8) & 0xffu); - hdw->cmd_buffer[bAddr+4] = ((addr>>16) & 0xffu); - PVR2_DECOMPOSE_LE(hdw->cmd_buffer, bAddr,data[idx]); - bAddr += 7; - } - ret = pvr2_send_request(hdw, - hdw->cmd_buffer,1+(chunkCnt*7), - NULL,0); - if (ret) return ret; - data += chunkCnt; - dlen -= chunkCnt; - offs += chunkCnt; - } - - return 0; -} - - -static int pvr2_encoder_read_words(struct pvr2_hdw *hdw, - unsigned int offs, - u32 *data, unsigned int dlen) -{ - unsigned int idx; - int ret; - unsigned int chunkCnt; - - /* - - Format: First byte must be 0x02 (status check) or 0x28 (read - back block of 32 bit words). Next 6 bytes must be zero, - followed by a single byte of MBOX_BASE+offset for portion to - be read. Returned data is packed set of 32 bits words that - were read. - - */ - - while (dlen) { - chunkCnt = 16; - if (chunkCnt > dlen) chunkCnt = dlen; - if (chunkCnt < 16) chunkCnt = 1; - hdw->cmd_buffer[0] = - ((chunkCnt == 1) ? - FX2CMD_MEM_READ_DWORD : FX2CMD_MEM_READ_64BYTES); - hdw->cmd_buffer[1] = 0; - hdw->cmd_buffer[2] = 0; - hdw->cmd_buffer[3] = 0; - hdw->cmd_buffer[4] = 0; - hdw->cmd_buffer[5] = ((offs>>16) & 0xffu); - hdw->cmd_buffer[6] = ((offs>>8) & 0xffu); - hdw->cmd_buffer[7] = (offs & 0xffu); - ret = pvr2_send_request(hdw, - hdw->cmd_buffer,8, - hdw->cmd_buffer, - (chunkCnt == 1 ? 4 : 16 * 4)); - if (ret) return ret; - - for (idx = 0; idx < chunkCnt; idx++) { - data[idx] = PVR2_COMPOSE_LE(hdw->cmd_buffer,idx*4); - } - data += chunkCnt; - dlen -= chunkCnt; - offs += chunkCnt; - } - - return 0; -} - - -/* This prototype is set up to be compatible with the - cx2341x_mbox_func prototype in cx2341x.h, which should be in - kernels 2.6.18 or later. We do this so that we can enable - cx2341x.ko to write to our encoder (by handing it a pointer to this - function). For earlier kernels this doesn't really matter. */ -static int pvr2_encoder_cmd(void *ctxt, - u32 cmd, - int arg_cnt_send, - int arg_cnt_recv, - u32 *argp) -{ - unsigned int poll_count; - unsigned int try_count = 0; - int retry_flag; - int ret = 0; - unsigned int idx; - /* These sizes look to be limited by the FX2 firmware implementation */ - u32 wrData[16]; - u32 rdData[16]; - struct pvr2_hdw *hdw = (struct pvr2_hdw *)ctxt; - - - /* - - The encoder seems to speak entirely using blocks 32 bit words. - In ivtv driver terms, this is a mailbox at MBOX_BASE which we - populate with data and watch what the hardware does with it. - The first word is a set of flags used to control the - transaction, the second word is the command to execute, the - third byte is zero (ivtv driver suggests that this is some - kind of return value), and the fourth byte is a specified - timeout (windows driver always uses 0x00060000 except for one - case when it is zero). All successive words are the argument - words for the command. - - First, write out the entire set of words, with the first word - being zero. - - Next, write out just the first word again, but set it to - IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which - probably means "go"). - - Next, read back the return count words. Check the first word, - which should have IVTV_MBOX_FIRMWARE_DONE set. If however - that bit is not set, then the command isn't done so repeat the - read until it is set. - - Finally, write out just the first word again, but set it to - 0x0 this time (which probably means "idle"). - - */ - - if (arg_cnt_send > (ARRAY_SIZE(wrData) - 4)) { - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "Failed to write cx23416 command" - " - too many input arguments" - " (was given %u limit %lu)", - arg_cnt_send, (long unsigned) ARRAY_SIZE(wrData) - 4); - return -EINVAL; - } - - if (arg_cnt_recv > (ARRAY_SIZE(rdData) - 4)) { - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "Failed to write cx23416 command" - " - too many return arguments" - " (was given %u limit %lu)", - arg_cnt_recv, (long unsigned) ARRAY_SIZE(rdData) - 4); - return -EINVAL; - } - - - LOCK_TAKE(hdw->ctl_lock); do { - - if (!hdw->state_encoder_ok) { - ret = -EIO; - break; - } - - retry_flag = 0; - try_count++; - ret = 0; - wrData[0] = 0; - wrData[1] = cmd; - wrData[2] = 0; - wrData[3] = 0x00060000; - for (idx = 0; idx < arg_cnt_send; idx++) { - wrData[idx+4] = argp[idx]; - } - for (; idx < ARRAY_SIZE(wrData) - 4; idx++) { - wrData[idx+4] = 0; - } - - ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,idx); - if (ret) break; - wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY; - ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1); - if (ret) break; - poll_count = 0; - while (1) { - poll_count++; - ret = pvr2_encoder_read_words(hdw,MBOX_BASE,rdData, - arg_cnt_recv+4); - if (ret) { - break; - } - if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) { - break; - } - if (rdData[0] && (poll_count < 1000)) continue; - if (!rdData[0]) { - retry_flag = !0; - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "Encoder timed out waiting for us" - "; arranging to retry"); - } else { - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "***WARNING*** device's encoder" - " appears to be stuck" - " (status=0x%08x)",rdData[0]); - } - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "Encoder command: 0x%02x",cmd); - for (idx = 4; idx < arg_cnt_send; idx++) { - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "Encoder arg%d: 0x%08x", - idx-3,wrData[idx]); - } - ret = -EBUSY; - break; - } - if (retry_flag) { - if (try_count < 20) continue; - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "Too many retries..."); - ret = -EBUSY; - } - if (ret) { - del_timer_sync(&hdw->encoder_run_timer); - hdw->state_encoder_ok = 0; - pvr2_trace(PVR2_TRACE_STBITS, - "State bit %s <-- %s", - "state_encoder_ok", - (hdw->state_encoder_ok ? "true" : "false")); - if (hdw->state_encoder_runok) { - hdw->state_encoder_runok = 0; - pvr2_trace(PVR2_TRACE_STBITS, - "State bit %s <-- %s", - "state_encoder_runok", - (hdw->state_encoder_runok ? - "true" : "false")); - } - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "Giving up on command." - " This is normally recovered via a firmware" - " reload and re-initialization; concern" - " is only warranted if this happens repeatedly" - " and rapidly."); - break; - } - wrData[0] = 0x7; - for (idx = 0; idx < arg_cnt_recv; idx++) { - argp[idx] = rdData[idx+4]; - } - - wrData[0] = 0x0; - ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1); - if (ret) break; - - } while(0); LOCK_GIVE(hdw->ctl_lock); - - return ret; -} - - -static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd, - int args, ...) -{ - va_list vl; - unsigned int idx; - u32 data[12]; - - if (args > ARRAY_SIZE(data)) { - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "Failed to write cx23416 command" - " - too many arguments" - " (was given %u limit %lu)", - args, (long unsigned) ARRAY_SIZE(data)); - return -EINVAL; - } - - va_start(vl, args); - for (idx = 0; idx < args; idx++) { - data[idx] = va_arg(vl, u32); - } - va_end(vl); - - return pvr2_encoder_cmd(hdw,cmd,args,0,data); -} - - -/* This implements some extra setup for the encoder that seems to be - specific to the PVR USB2 hardware. */ -static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw) -{ - int ret = 0; - int encMisc3Arg = 0; - -#if 0 - /* This inexplicable bit happens in the Hauppauge windows - driver (for both 24xxx and 29xxx devices). However I - currently see no difference in behavior with or without - this stuff. Leave this here as a note of its existence, - but don't use it. */ - LOCK_TAKE(hdw->ctl_lock); do { - u32 dat[1]; - dat[0] = 0x80000640; - pvr2_encoder_write_words(hdw,0x01fe,dat,1); - pvr2_encoder_write_words(hdw,0x023e,dat,1); - } while(0); LOCK_GIVE(hdw->ctl_lock); -#endif - - /* Mike Isely <isely@pobox.com> 26-Jan-2006 The windows driver - sends the following list of ENC_MISC commands (for both - 24xxx and 29xxx devices). Meanings are not entirely clear, - however without the ENC_MISC(3,1) command then we risk - random perpetual video corruption whenever the video input - breaks up for a moment (like when switching channels). */ - - -#if 0 - /* This ENC_MISC(5,0) command seems to hurt 29xxx sync - performance on channel changes, but is not a problem on - 24xxx devices. */ - ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 5,0,0,0); -#endif - - /* This ENC_MISC(3,encMisc3Arg) command is critical - without - it there will eventually be video corruption. Also, the - saa7115 case is strange - the Windows driver is passing 1 - regardless of device type but if we have 1 for saa7115 - devices the video turns sluggish. */ - if (hdw->hdw_desc->flag_has_cx25840) { - encMisc3Arg = 1; - } else { - encMisc3Arg = 0; - } - ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3, - encMisc3Arg,0,0); - - ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0); - -#if 0 - /* This ENC_MISC(4,1) command is poisonous, so it is commented - out. But I'm leaving it here anyway to document its - existence in the Windows driver. The effect of this - command is that apps displaying the stream become sluggish - with stuttering video. */ - ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 4,1,0,0); -#endif - - ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0); - ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0); - - /* prevent the PTSs from slowly drifting away in the generated - MPEG stream */ - ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC, 2, 4, 1); - - return ret; -} - -int pvr2_encoder_adjust(struct pvr2_hdw *hdw) -{ - int ret; - ret = cx2341x_update(hdw,pvr2_encoder_cmd, - (hdw->enc_cur_valid ? &hdw->enc_cur_state : NULL), - &hdw->enc_ctl_state); - if (ret) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Error from cx2341x module code=%d",ret); - } else { - memcpy(&hdw->enc_cur_state,&hdw->enc_ctl_state, - sizeof(struct cx2341x_mpeg_params)); - hdw->enc_cur_valid = !0; - } - return ret; -} - - -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_525_60) ? - 0 : 1); - - ret = 0; - - ret |= pvr2_encoder_prep_config(hdw); - - /* saa7115: 0xf0 */ - val = 0xf0; - if (hdw->hdw_desc->flag_has_cx25840) { - /* ivtv cx25840: 0x140 */ - val = 0x140; - } - - if (!ret) ret = pvr2_encoder_vcmd( - hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, - val, val); - - /* setup firmware to notify us about some events (don't know why...) */ - if (!ret) ret = pvr2_encoder_vcmd( - hdw,CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, - 0, 0, 0x10000000, 0xffffffff); - - if (!ret) ret = pvr2_encoder_vcmd( - hdw,CX2341X_ENC_SET_VBI_LINE, 5, - 0xffffffff,0,0,0,0); - - if (ret) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Failed to configure cx23416"); - return ret; - } - - ret = pvr2_encoder_adjust(hdw); - if (ret) return ret; - - ret = pvr2_encoder_vcmd( - hdw, CX2341X_ENC_INITIALIZE_INPUT, 0); - - if (ret) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Failed to initialize cx23416 video input"); - return ret; - } - - return 0; -} - - -int pvr2_encoder_start(struct pvr2_hdw *hdw) -{ - int status; - - /* unmask some interrupts */ - pvr2_write_register(hdw, 0x0048, 0xbfffffff); - - pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1, - hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0); - - switch (hdw->active_stream_type) { - case pvr2_config_vbi: - status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, - 0x01,0x14); - break; - case pvr2_config_mpeg: - status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, - 0,0x13); - break; - default: /* Unhandled cases for now */ - status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, - 0,0x13); - break; - } - return status; -} - -int pvr2_encoder_stop(struct pvr2_hdw *hdw) -{ - int status; - - /* mask all interrupts */ - pvr2_write_register(hdw, 0x0048, 0xffffffff); - - switch (hdw->active_stream_type) { - case pvr2_config_vbi: - status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, - 0x01,0x01,0x14); - break; - case pvr2_config_mpeg: - status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, - 0x01,0,0x13); - break; - default: /* Unhandled cases for now */ - status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, - 0x01,0,0x13); - break; - } - - return status; -} - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.h b/drivers/media/video/pvrusb2/pvrusb2-encoder.h deleted file mode 100644 index 232fefbcd1ac..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef __PVRUSB2_ENCODER_H -#define __PVRUSB2_ENCODER_H - -struct pvr2_hdw; - -int pvr2_encoder_adjust(struct pvr2_hdw *); -int pvr2_encoder_configure(struct pvr2_hdw *); -int pvr2_encoder_start(struct pvr2_hdw *); -int pvr2_encoder_stop(struct pvr2_hdw *); - -#endif /* __PVRUSB2_ENCODER_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h deleted file mode 100644 index 614755ea2ea3..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * - * - * Copyright (C) 2007 Michael Krufky <mkrufky@linuxtv.org> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef _PVRUSB2_FX2_CMD_H_ -#define _PVRUSB2_FX2_CMD_H_ - -#define FX2CMD_MEM_WRITE_DWORD 0x01u -#define FX2CMD_MEM_READ_DWORD 0x02u - -#define FX2CMD_HCW_ZILOG_RESET 0x10u /* 1=reset 0=release */ - -#define FX2CMD_MEM_READ_64BYTES 0x28u - -#define FX2CMD_REG_WRITE 0x04u -#define FX2CMD_REG_READ 0x05u -#define FX2CMD_MEMSEL 0x06u - -#define FX2CMD_I2C_WRITE 0x08u -#define FX2CMD_I2C_READ 0x09u - -#define FX2CMD_GET_USB_SPEED 0x0bu - -#define FX2CMD_STREAMING_ON 0x36u -#define FX2CMD_STREAMING_OFF 0x37u - -#define FX2CMD_FWPOST1 0x52u - -#define FX2CMD_POWER_OFF 0xdcu -#define FX2CMD_POWER_ON 0xdeu - -#define FX2CMD_DEEP_RESET 0xddu - -#define FX2CMD_GET_EEPROM_ADDR 0xebu -#define FX2CMD_GET_IR_CODE 0xecu - -#define FX2CMD_HCW_DEMOD_RESETIN 0xf0u -#define FX2CMD_HCW_DTV_STREAMING_ON 0xf1u -#define FX2CMD_HCW_DTV_STREAMING_OFF 0xf2u - -#define FX2CMD_ONAIR_DTV_STREAMING_ON 0xa0u -#define FX2CMD_ONAIR_DTV_STREAMING_OFF 0xa1u -#define FX2CMD_ONAIR_DTV_POWER_ON 0xa2u -#define FX2CMD_ONAIR_DTV_POWER_OFF 0xa3u - -#endif /* _PVRUSB2_FX2_CMD_H_ */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h deleted file mode 100644 index 036952f2a3cb..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ /dev/null @@ -1,406 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __PVRUSB2_HDW_INTERNAL_H -#define __PVRUSB2_HDW_INTERNAL_H - -/* - - This header sets up all the internal structures and definitions needed to - track and coordinate the driver's interaction with the hardware. ONLY - source files which actually implement part of that whole circus should be - including this header. Higher levels, like the external layers to the - various public APIs (V4L, sysfs, etc) should NOT ever include this - private, internal header. This means that pvrusb2-hdw, pvrusb2-encoder, - etc will include this, but pvrusb2-v4l should not. - -*/ - -#include <linux/videodev2.h> -#include <linux/i2c.h> -#include <linux/workqueue.h> -#include <linux/mutex.h> -#include "pvrusb2-hdw.h" -#include "pvrusb2-io.h" -#include <media/v4l2-device.h> -#include <media/cx2341x.h> -#include <media/ir-kbd-i2c.h> -#include "pvrusb2-devattr.h" - -/* Legal values for PVR2_CID_HSM */ -#define PVR2_CVAL_HSM_FAIL 0 -#define PVR2_CVAL_HSM_FULL 1 -#define PVR2_CVAL_HSM_HIGH 2 - -#define PVR2_VID_ENDPOINT 0x84 -#define PVR2_UNK_ENDPOINT 0x86 /* maybe raw yuv ? */ -#define PVR2_VBI_ENDPOINT 0x88 - -#define PVR2_CTL_BUFFSIZE 64 - -#define FREQTABLE_SIZE 500 - -#define LOCK_TAKE(x) do { mutex_lock(&x##_mutex); x##_held = !0; } while (0) -#define LOCK_GIVE(x) do { x##_held = 0; mutex_unlock(&x##_mutex); } while (0) - -typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *); -typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *); -typedef int (*pvr2_ctlf_check_value)(struct pvr2_ctrl *,int); -typedef int (*pvr2_ctlf_get_value)(struct pvr2_ctrl *,int *); -typedef int (*pvr2_ctlf_set_value)(struct pvr2_ctrl *,int msk,int val); -typedef int (*pvr2_ctlf_val_to_sym)(struct pvr2_ctrl *,int msk,int val, - char *,unsigned int,unsigned int *); -typedef int (*pvr2_ctlf_sym_to_val)(struct pvr2_ctrl *, - const char *,unsigned int, - int *mskp,int *valp); -typedef unsigned int (*pvr2_ctlf_get_v4lflags)(struct pvr2_ctrl *); - -/* This structure describes a specific control. A table of these is set up - in pvrusb2-hdw.c. */ -struct pvr2_ctl_info { - /* Control's name suitable for use as an identifier */ - const char *name; - - /* Short description of control */ - const char *desc; - - /* Control's implementation */ - pvr2_ctlf_get_value get_value; /* Get its value */ - pvr2_ctlf_get_value get_def_value; /* Get its default value */ - pvr2_ctlf_get_value get_min_value; /* Get minimum allowed value */ - pvr2_ctlf_get_value get_max_value; /* Get maximum allowed value */ - pvr2_ctlf_set_value set_value; /* Set its value */ - pvr2_ctlf_check_value check_value; /* Check that value is valid */ - pvr2_ctlf_val_to_sym val_to_sym; /* Custom convert value->symbol */ - pvr2_ctlf_sym_to_val sym_to_val; /* Custom convert symbol->value */ - pvr2_ctlf_is_dirty is_dirty; /* Return true if dirty */ - pvr2_ctlf_clear_dirty clear_dirty; /* Clear dirty state */ - pvr2_ctlf_get_v4lflags get_v4lflags;/* Retrieve v4l flags */ - - /* Control's type (int, enum, bitmask) */ - enum pvr2_ctl_type type; - - /* Associated V4L control ID, if any */ - int v4l_id; - - /* Associated driver internal ID, if any */ - int internal_id; - - /* Don't implicitly initialize this control's value */ - int skip_init; - - /* Starting value for this control */ - int default_value; - - /* Type-specific control information */ - union { - struct { /* Integer control */ - long min_value; /* lower limit */ - long max_value; /* upper limit */ - } type_int; - struct { /* enumerated control */ - unsigned int count; /* enum value count */ - const char * const *value_names; /* symbol names */ - } type_enum; - struct { /* bitmask control */ - unsigned int valid_bits; /* bits in use */ - const char **bit_names; /* symbol name/bit */ - } type_bitmask; - } def; -}; - - -/* Same as pvr2_ctl_info, but includes storage for the control description */ -#define PVR2_CTLD_INFO_DESC_SIZE 32 -struct pvr2_ctld_info { - struct pvr2_ctl_info info; - char desc[PVR2_CTLD_INFO_DESC_SIZE]; -}; - -struct pvr2_ctrl { - const struct pvr2_ctl_info *info; - struct pvr2_hdw *hdw; -}; - - - -/* Disposition of firmware1 loading situation */ -#define FW1_STATE_UNKNOWN 0 -#define FW1_STATE_MISSING 1 -#define FW1_STATE_FAILED 2 -#define FW1_STATE_RELOAD 3 -#define FW1_STATE_OK 4 - -/* What state the device is in if it is a hybrid */ -#define PVR2_PATHWAY_UNKNOWN 0 -#define PVR2_PATHWAY_ANALOG 1 -#define PVR2_PATHWAY_DIGITAL 2 - -typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16); -#define PVR2_I2C_FUNC_CNT 128 - -/* This structure contains all state data directly needed to - manipulate the hardware (as opposed to complying with a kernel - interface) */ -struct pvr2_hdw { - /* Underlying USB device handle */ - struct usb_device *usb_dev; - struct usb_interface *usb_intf; - - /* Our handle into the v4l2 sub-device architecture */ - struct v4l2_device v4l2_dev; - /* Device description, anything that must adjust behavior based on - device specific info will use information held here. */ - const struct pvr2_device_desc *hdw_desc; - - /* Kernel worker thread handling */ - struct workqueue_struct *workqueue; - struct work_struct workpoll; /* Update driver state */ - - /* Video spigot */ - struct pvr2_stream *vid_stream; - - /* Mutex for all hardware state control */ - struct mutex big_lock_mutex; - int big_lock_held; /* For debugging */ - - /* This is a simple string which identifies the instance of this - driver. It is unique within the set of existing devices, but - there is no attempt to keep the name consistent with the same - physical device each time. */ - char name[32]; - - /* This is a simple string which identifies the physical device - instance itself - if possible. (If not possible, then it is - based on the specific driver instance, similar to name above.) - The idea here is that userspace might hopefully be able to use - this recognize specific tuners. It will encode a serial number, - if available. */ - char identifier[32]; - - /* I2C stuff */ - struct i2c_adapter i2c_adap; - struct i2c_algorithm i2c_algo; - pvr2_i2c_func i2c_func[PVR2_I2C_FUNC_CNT]; - int i2c_cx25840_hack_state; - int i2c_linked; - - /* IR related */ - unsigned int ir_scheme_active; /* IR scheme as seen from the outside */ - struct IR_i2c_init_data ir_init_data; /* params passed to IR modules */ - - /* Frequency table */ - unsigned int freqTable[FREQTABLE_SIZE]; - unsigned int freqProgSlot; - - /* Stuff for handling low level control interaction with device */ - struct mutex ctl_lock_mutex; - int ctl_lock_held; /* For debugging */ - struct urb *ctl_write_urb; - struct urb *ctl_read_urb; - unsigned char *ctl_write_buffer; - unsigned char *ctl_read_buffer; - int ctl_write_pend_flag; - int ctl_read_pend_flag; - int ctl_timeout_flag; - struct completion ctl_done; - unsigned char cmd_buffer[PVR2_CTL_BUFFSIZE]; - int cmd_debug_state; // Low level command debugging info - unsigned char cmd_debug_code; // - unsigned int cmd_debug_write_len; // - unsigned int cmd_debug_read_len; // - - /* Bits of state that describe what is going on with various parts - of the driver. */ - int state_pathway_ok; /* Pathway config is ok */ - int state_encoder_ok; /* Encoder is operational */ - int state_encoder_run; /* Encoder is running */ - int state_encoder_config; /* Encoder is configured */ - int state_encoder_waitok; /* Encoder pre-wait done */ - int state_encoder_runok; /* Encoder has run for >= .25 sec */ - int state_decoder_run; /* Decoder is running */ - int state_decoder_ready; /* Decoder is stabilized & streamable */ - int state_usbstream_run; /* FX2 is streaming */ - int state_decoder_quiescent; /* Decoder idle for minimal interval */ - int state_pipeline_config; /* Pipeline is configured */ - int state_pipeline_req; /* Somebody wants to stream */ - int state_pipeline_pause; /* Pipeline must be paused */ - int state_pipeline_idle; /* Pipeline not running */ - - /* This is the master state of the driver. It is the combined - result of other bits of state. Examining this will indicate the - overall state of the driver. Values here are one of - PVR2_STATE_xxxx */ - unsigned int master_state; - - /* True if device led is currently on */ - int led_on; - - /* True if states must be re-evaluated */ - int state_stale; - - void (*state_func)(void *); - void *state_data; - - /* Timer for measuring required decoder settling time before we're - allowed to fire it up again. */ - struct timer_list quiescent_timer; - - /* Timer for measuring decoder stabilization time, which is the - amount of time we need to let the decoder run before we can - trust its output (otherwise the encoder might see garbage and - then fail to start correctly). */ - struct timer_list decoder_stabilization_timer; - - /* Timer for measuring encoder pre-wait time */ - struct timer_list encoder_wait_timer; - - /* Timer for measuring encoder minimum run time */ - struct timer_list encoder_run_timer; - - /* Place to block while waiting for state changes */ - wait_queue_head_t state_wait_data; - - - int force_dirty; /* consider all controls dirty if true */ - int flag_ok; /* device in known good state */ - int flag_modulefail; /* true if at least one module failed to load */ - int flag_disconnected; /* flag_ok == 0 due to disconnect */ - int flag_init_ok; /* true if structure is fully initialized */ - int fw1_state; /* current situation with fw1 */ - int pathway_state; /* one of PVR2_PATHWAY_xxx */ - int flag_decoder_missed;/* We've noticed missing decoder */ - int flag_tripped; /* Indicates overall failure to start */ - - unsigned int decoder_client_id; - - // CPU firmware info (used to help find / save firmware data) - char *fw_buffer; - unsigned int fw_size; - int fw_cpu_flag; /* True if we are dealing with the CPU */ - - /* Tuner / frequency control stuff */ - unsigned int tuner_type; - int tuner_updated; - unsigned int freqValTelevision; /* Current freq for tv mode */ - unsigned int freqValRadio; /* Current freq for radio mode */ - unsigned int freqSlotTelevision; /* Current slot for tv mode */ - unsigned int freqSlotRadio; /* Current slot for radio mode */ - unsigned int freqSelector; /* 0=radio 1=television */ - int freqDirty; - - /* Current tuner info - this information is polled from the I2C bus */ - struct v4l2_tuner tuner_signal_info; - int tuner_signal_stale; - - /* Cropping capability info */ - struct v4l2_cropcap cropcap_info; - int cropcap_stale; - - /* Video standard handling */ - v4l2_std_id std_mask_eeprom; // Hardware supported selections - v4l2_std_id std_mask_avail; // Which standards we may select from - v4l2_std_id std_mask_cur; // Currently selected standard(s) - int std_enum_cur; // selected standard enumeration value - int std_dirty; // True if std_mask_cur has changed - struct pvr2_ctl_info std_info_enum; - struct pvr2_ctl_info std_info_avail; - struct pvr2_ctl_info std_info_cur; - struct pvr2_ctl_info std_info_detect; - - // Generated string names, one per actual V4L2 standard - const char *std_mask_ptrs[32]; - char std_mask_names[32][16]; - - 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; - int v4l_minor_number_vbi; - int v4l_minor_number_radio; - - /* Bit mask of PVR2_CVAL_INPUT choices which are valid for the hardware */ - unsigned int input_avail_mask; - /* Bit mask of PVR2_CVAL_INPUT choices which are currently allowed */ - unsigned int input_allowed_mask; - - /* Location of eeprom or a negative number if none */ - int eeprom_addr; - - enum pvr2_config active_stream_type; - enum pvr2_config desired_stream_type; - - /* Control state needed for cx2341x module */ - struct cx2341x_mpeg_params enc_cur_state; - struct cx2341x_mpeg_params enc_ctl_state; - /* True if an encoder attribute has changed */ - int enc_stale; - /* True if an unsafe encoder attribute has changed */ - int enc_unsafe_stale; - /* True if enc_cur_state is valid */ - int enc_cur_valid; - - /* Control state */ -#define VCREATE_DATA(lab) int lab##_val; int lab##_dirty - VCREATE_DATA(brightness); - VCREATE_DATA(contrast); - VCREATE_DATA(saturation); - VCREATE_DATA(hue); - VCREATE_DATA(volume); - VCREATE_DATA(balance); - VCREATE_DATA(bass); - VCREATE_DATA(treble); - VCREATE_DATA(mute); - VCREATE_DATA(cropl); - VCREATE_DATA(cropt); - VCREATE_DATA(cropw); - VCREATE_DATA(croph); - VCREATE_DATA(input); - VCREATE_DATA(audiomode); - VCREATE_DATA(res_hor); - VCREATE_DATA(res_ver); - VCREATE_DATA(srate); -#undef VCREATE_DATA - - struct pvr2_ctld_info *mpeg_ctrl_info; - - struct pvr2_ctrl *controls; - unsigned int control_cnt; -}; - -/* This function gets the current frequency */ -unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *); - -void pvr2_hdw_status_poll(struct pvr2_hdw *); - -#endif /* __PVRUSB2_HDW_INTERNAL_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c deleted file mode 100644 index fb828ba1dbbe..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ /dev/null @@ -1,5202 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/firmware.h> -#include <linux/videodev2.h> -#include <media/v4l2-common.h> -#include <media/tuner.h> -#include "pvrusb2.h" -#include "pvrusb2-std.h" -#include "pvrusb2-util.h" -#include "pvrusb2-hdw.h" -#include "pvrusb2-i2c-core.h" -#include "pvrusb2-eeprom.h" -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-encoder.h" -#include "pvrusb2-debug.h" -#include "pvrusb2-fx2-cmd.h" -#include "pvrusb2-wm8775.h" -#include "pvrusb2-video-v4l.h" -#include "pvrusb2-cx2584x-v4l.h" -#include "pvrusb2-cs53l32a.h" -#include "pvrusb2-audio.h" - -#define TV_MIN_FREQ 55250000L -#define TV_MAX_FREQ 850000000L - -/* This defines a minimum interval that the decoder must remain quiet - before we are allowed to start it running. */ -#define TIME_MSEC_DECODER_WAIT 50 - -/* This defines a minimum interval that the decoder must be allowed to run - before we can safely begin using its streaming output. */ -#define TIME_MSEC_DECODER_STABILIZATION_WAIT 300 - -/* This defines a minimum interval that the encoder must remain quiet - before we are allowed to configure it. */ -#define TIME_MSEC_ENCODER_WAIT 50 - -/* This defines the minimum interval that the encoder must successfully run - before we consider that the encoder has run at least once since its - firmware has been loaded. This measurement is in important for cases - where we can't do something until we know that the encoder has been run - at least once. */ -#define TIME_MSEC_ENCODER_OK 250 - -static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL}; -static DEFINE_MUTEX(pvr2_unit_mtx); - -static int ctlchg; -static int procreload; -static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 }; -static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 }; -static int video_std[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 }; -static int init_pause_msec; - -module_param(ctlchg, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value"); -module_param(init_pause_msec, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(init_pause_msec, "hardware initialization settling delay"); -module_param(procreload, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(procreload, - "Attempt init failure recovery with firmware reload"); -module_param_array(tuner, int, NULL, 0444); -MODULE_PARM_DESC(tuner,"specify installed tuner type"); -module_param_array(video_std, int, NULL, 0444); -MODULE_PARM_DESC(video_std,"specify initial video standard"); -module_param_array(tolerance, int, NULL, 0444); -MODULE_PARM_DESC(tolerance,"specify stream error tolerance"); - -/* US Broadcast channel 3 (61.25 MHz), to help with testing */ -static int default_tv_freq = 61250000L; -/* 104.3 MHz, a usable FM station for my area */ -static int default_radio_freq = 104300000L; - -module_param_named(tv_freq, default_tv_freq, int, 0444); -MODULE_PARM_DESC(tv_freq, "specify initial television frequency"); -module_param_named(radio_freq, default_radio_freq, int, 0444); -MODULE_PARM_DESC(radio_freq, "specify initial radio frequency"); - -#define PVR2_CTL_WRITE_ENDPOINT 0x01 -#define PVR2_CTL_READ_ENDPOINT 0x81 - -#define PVR2_GPIO_IN 0x9008 -#define PVR2_GPIO_OUT 0x900c -#define PVR2_GPIO_DIR 0x9020 - -#define trace_firmware(...) pvr2_trace(PVR2_TRACE_FIRMWARE,__VA_ARGS__) - -#define PVR2_FIRMWARE_ENDPOINT 0x02 - -/* size of a firmware chunk */ -#define FIRMWARE_CHUNK_SIZE 0x2000 - -typedef void (*pvr2_subdev_update_func)(struct pvr2_hdw *, - struct v4l2_subdev *); - -static const pvr2_subdev_update_func pvr2_module_update_functions[] = { - [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_subdev_update, - [PVR2_CLIENT_ID_SAA7115] = pvr2_saa7115_subdev_update, - [PVR2_CLIENT_ID_MSP3400] = pvr2_msp3400_subdev_update, - [PVR2_CLIENT_ID_CX25840] = pvr2_cx25840_subdev_update, - [PVR2_CLIENT_ID_CS53L32A] = pvr2_cs53l32a_subdev_update, -}; - -static const char *module_names[] = { - [PVR2_CLIENT_ID_MSP3400] = "msp3400", - [PVR2_CLIENT_ID_CX25840] = "cx25840", - [PVR2_CLIENT_ID_SAA7115] = "saa7115", - [PVR2_CLIENT_ID_TUNER] = "tuner", - [PVR2_CLIENT_ID_DEMOD] = "tuner", - [PVR2_CLIENT_ID_CS53L32A] = "cs53l32a", - [PVR2_CLIENT_ID_WM8775] = "wm8775", -}; - - -static const unsigned char *module_i2c_addresses[] = { - [PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63", - [PVR2_CLIENT_ID_DEMOD] = "\x43", - [PVR2_CLIENT_ID_MSP3400] = "\x40", - [PVR2_CLIENT_ID_SAA7115] = "\x21", - [PVR2_CLIENT_ID_WM8775] = "\x1b", - [PVR2_CLIENT_ID_CX25840] = "\x44", - [PVR2_CLIENT_ID_CS53L32A] = "\x11", -}; - - -static const char *ir_scheme_names[] = { - [PVR2_IR_SCHEME_NONE] = "none", - [PVR2_IR_SCHEME_29XXX] = "29xxx", - [PVR2_IR_SCHEME_24XXX] = "24xxx (29xxx emulation)", - [PVR2_IR_SCHEME_24XXX_MCE] = "24xxx (MCE device)", - [PVR2_IR_SCHEME_ZILOG] = "Zilog", -}; - - -/* Define the list of additional controls we'll dynamically construct based - on query of the cx2341x module. */ -struct pvr2_mpeg_ids { - const char *strid; - int id; -}; -static const struct pvr2_mpeg_ids mpeg_ids[] = { - { - .strid = "audio_layer", - .id = V4L2_CID_MPEG_AUDIO_ENCODING, - },{ - .strid = "audio_bitrate", - .id = V4L2_CID_MPEG_AUDIO_L2_BITRATE, - },{ - /* Already using audio_mode elsewhere :-( */ - .strid = "mpeg_audio_mode", - .id = V4L2_CID_MPEG_AUDIO_MODE, - },{ - .strid = "mpeg_audio_mode_extension", - .id = V4L2_CID_MPEG_AUDIO_MODE_EXTENSION, - },{ - .strid = "audio_emphasis", - .id = V4L2_CID_MPEG_AUDIO_EMPHASIS, - },{ - .strid = "audio_crc", - .id = V4L2_CID_MPEG_AUDIO_CRC, - },{ - .strid = "video_aspect", - .id = V4L2_CID_MPEG_VIDEO_ASPECT, - },{ - .strid = "video_b_frames", - .id = V4L2_CID_MPEG_VIDEO_B_FRAMES, - },{ - .strid = "video_gop_size", - .id = V4L2_CID_MPEG_VIDEO_GOP_SIZE, - },{ - .strid = "video_gop_closure", - .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, - },{ - .strid = "video_bitrate_mode", - .id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE, - },{ - .strid = "video_bitrate", - .id = V4L2_CID_MPEG_VIDEO_BITRATE, - },{ - .strid = "video_bitrate_peak", - .id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, - },{ - .strid = "video_temporal_decimation", - .id = V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, - },{ - .strid = "stream_type", - .id = V4L2_CID_MPEG_STREAM_TYPE, - },{ - .strid = "video_spatial_filter_mode", - .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE, - },{ - .strid = "video_spatial_filter", - .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER, - },{ - .strid = "video_luma_spatial_filter_type", - .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE, - },{ - .strid = "video_chroma_spatial_filter_type", - .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE, - },{ - .strid = "video_temporal_filter_mode", - .id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE, - },{ - .strid = "video_temporal_filter", - .id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER, - },{ - .strid = "video_median_filter_type", - .id = V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE, - },{ - .strid = "video_luma_median_filter_top", - .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP, - },{ - .strid = "video_luma_median_filter_bottom", - .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM, - },{ - .strid = "video_chroma_median_filter_top", - .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP, - },{ - .strid = "video_chroma_median_filter_bottom", - .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM, - } -}; -#define MPEGDEF_COUNT ARRAY_SIZE(mpeg_ids) - - -static const char *control_values_srate[] = { - [V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100] = "44.1 kHz", - [V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000] = "48 kHz", - [V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000] = "32 kHz", -}; - - - -static const char *control_values_input[] = { - [PVR2_CVAL_INPUT_TV] = "television", /*xawtv needs this name*/ - [PVR2_CVAL_INPUT_DTV] = "dtv", - [PVR2_CVAL_INPUT_RADIO] = "radio", - [PVR2_CVAL_INPUT_SVIDEO] = "s-video", - [PVR2_CVAL_INPUT_COMPOSITE] = "composite", -}; - - -static const char *control_values_audiomode[] = { - [V4L2_TUNER_MODE_MONO] = "Mono", - [V4L2_TUNER_MODE_STEREO] = "Stereo", - [V4L2_TUNER_MODE_LANG1] = "Lang1", - [V4L2_TUNER_MODE_LANG2] = "Lang2", - [V4L2_TUNER_MODE_LANG1_LANG2] = "Lang1+Lang2", -}; - - -static const char *control_values_hsm[] = { - [PVR2_CVAL_HSM_FAIL] = "Fail", - [PVR2_CVAL_HSM_HIGH] = "High", - [PVR2_CVAL_HSM_FULL] = "Full", -}; - - -static const char *pvr2_state_names[] = { - [PVR2_STATE_NONE] = "none", - [PVR2_STATE_DEAD] = "dead", - [PVR2_STATE_COLD] = "cold", - [PVR2_STATE_WARM] = "warm", - [PVR2_STATE_ERROR] = "error", - [PVR2_STATE_READY] = "ready", - [PVR2_STATE_RUN] = "run", -}; - - -struct pvr2_fx2cmd_descdef { - unsigned char id; - unsigned char *desc; -}; - -static const struct pvr2_fx2cmd_descdef pvr2_fx2cmd_desc[] = { - {FX2CMD_MEM_WRITE_DWORD, "write encoder dword"}, - {FX2CMD_MEM_READ_DWORD, "read encoder dword"}, - {FX2CMD_HCW_ZILOG_RESET, "zilog IR reset control"}, - {FX2CMD_MEM_READ_64BYTES, "read encoder 64bytes"}, - {FX2CMD_REG_WRITE, "write encoder register"}, - {FX2CMD_REG_READ, "read encoder register"}, - {FX2CMD_MEMSEL, "encoder memsel"}, - {FX2CMD_I2C_WRITE, "i2c write"}, - {FX2CMD_I2C_READ, "i2c read"}, - {FX2CMD_GET_USB_SPEED, "get USB speed"}, - {FX2CMD_STREAMING_ON, "stream on"}, - {FX2CMD_STREAMING_OFF, "stream off"}, - {FX2CMD_FWPOST1, "fwpost1"}, - {FX2CMD_POWER_OFF, "power off"}, - {FX2CMD_POWER_ON, "power on"}, - {FX2CMD_DEEP_RESET, "deep reset"}, - {FX2CMD_GET_EEPROM_ADDR, "get rom addr"}, - {FX2CMD_GET_IR_CODE, "get IR code"}, - {FX2CMD_HCW_DEMOD_RESETIN, "hcw demod resetin"}, - {FX2CMD_HCW_DTV_STREAMING_ON, "hcw dtv stream on"}, - {FX2CMD_HCW_DTV_STREAMING_OFF, "hcw dtv stream off"}, - {FX2CMD_ONAIR_DTV_STREAMING_ON, "onair dtv stream on"}, - {FX2CMD_ONAIR_DTV_STREAMING_OFF, "onair dtv stream off"}, - {FX2CMD_ONAIR_DTV_POWER_ON, "onair dtv power on"}, - {FX2CMD_ONAIR_DTV_POWER_OFF, "onair dtv power off"}, -}; - - -static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v); -static void pvr2_hdw_state_sched(struct pvr2_hdw *); -static int pvr2_hdw_state_eval(struct pvr2_hdw *); -static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long); -static void pvr2_hdw_worker_poll(struct work_struct *work); -static int pvr2_hdw_wait(struct pvr2_hdw *,int state); -static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *); -static void pvr2_hdw_state_log_state(struct pvr2_hdw *); -static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl); -static int pvr2_hdw_commit_setup(struct pvr2_hdw *hdw); -static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw); -static void pvr2_hdw_quiescent_timeout(unsigned long); -static void pvr2_hdw_decoder_stabilization_timeout(unsigned long); -static void pvr2_hdw_encoder_wait_timeout(unsigned long); -static void pvr2_hdw_encoder_run_timeout(unsigned long); -static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32); -static int pvr2_send_request_ex(struct pvr2_hdw *hdw, - unsigned int timeout,int probe_fl, - void *write_data,unsigned int write_len, - void *read_data,unsigned int read_len); -static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw); -static v4l2_std_id pvr2_hdw_get_detected_std(struct pvr2_hdw *hdw); - -static void trace_stbit(const char *name,int val) -{ - pvr2_trace(PVR2_TRACE_STBITS, - "State bit %s <-- %s", - name,(val ? "true" : "false")); -} - -static int ctrl_channelfreq_get(struct pvr2_ctrl *cptr,int *vp) -{ - struct pvr2_hdw *hdw = cptr->hdw; - if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) { - *vp = hdw->freqTable[hdw->freqProgSlot-1]; - } else { - *vp = 0; - } - return 0; -} - -static int ctrl_channelfreq_set(struct pvr2_ctrl *cptr,int m,int v) -{ - struct pvr2_hdw *hdw = cptr->hdw; - unsigned int slotId = hdw->freqProgSlot; - if ((slotId > 0) && (slotId <= FREQTABLE_SIZE)) { - hdw->freqTable[slotId-1] = v; - /* Handle side effects correctly - if we're tuned to this - slot, then forgot the slot id relation since the stored - frequency has been changed. */ - if (hdw->freqSelector) { - if (hdw->freqSlotRadio == slotId) { - hdw->freqSlotRadio = 0; - } - } else { - if (hdw->freqSlotTelevision == slotId) { - hdw->freqSlotTelevision = 0; - } - } - } - return 0; -} - -static int ctrl_channelprog_get(struct pvr2_ctrl *cptr,int *vp) -{ - *vp = cptr->hdw->freqProgSlot; - return 0; -} - -static int ctrl_channelprog_set(struct pvr2_ctrl *cptr,int m,int v) -{ - struct pvr2_hdw *hdw = cptr->hdw; - if ((v >= 0) && (v <= FREQTABLE_SIZE)) { - hdw->freqProgSlot = v; - } - return 0; -} - -static int ctrl_channel_get(struct pvr2_ctrl *cptr,int *vp) -{ - struct pvr2_hdw *hdw = cptr->hdw; - *vp = hdw->freqSelector ? hdw->freqSlotRadio : hdw->freqSlotTelevision; - return 0; -} - -static int ctrl_channel_set(struct pvr2_ctrl *cptr,int m,int slotId) -{ - unsigned freq = 0; - struct pvr2_hdw *hdw = cptr->hdw; - if ((slotId < 0) || (slotId > FREQTABLE_SIZE)) return 0; - if (slotId > 0) { - freq = hdw->freqTable[slotId-1]; - if (!freq) return 0; - pvr2_hdw_set_cur_freq(hdw,freq); - } - if (hdw->freqSelector) { - hdw->freqSlotRadio = slotId; - } else { - hdw->freqSlotTelevision = slotId; - } - return 0; -} - -static int ctrl_freq_get(struct pvr2_ctrl *cptr,int *vp) -{ - *vp = pvr2_hdw_get_cur_freq(cptr->hdw); - return 0; -} - -static int ctrl_freq_is_dirty(struct pvr2_ctrl *cptr) -{ - return cptr->hdw->freqDirty != 0; -} - -static void ctrl_freq_clear_dirty(struct pvr2_ctrl *cptr) -{ - cptr->hdw->freqDirty = 0; -} - -static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v) -{ - pvr2_hdw_set_cur_freq(cptr->hdw,v); - return 0; -} - -static int ctrl_cropl_min_get(struct pvr2_ctrl *cptr, int *left) -{ - struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; - int stat = pvr2_hdw_check_cropcap(cptr->hdw); - if (stat != 0) { - return stat; - } - *left = cap->bounds.left; - return 0; -} - -static int ctrl_cropl_max_get(struct pvr2_ctrl *cptr, int *left) -{ - struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; - int stat = pvr2_hdw_check_cropcap(cptr->hdw); - if (stat != 0) { - return stat; - } - *left = cap->bounds.left; - if (cap->bounds.width > cptr->hdw->cropw_val) { - *left += cap->bounds.width - cptr->hdw->cropw_val; - } - return 0; -} - -static int ctrl_cropt_min_get(struct pvr2_ctrl *cptr, int *top) -{ - struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; - int stat = pvr2_hdw_check_cropcap(cptr->hdw); - if (stat != 0) { - return stat; - } - *top = cap->bounds.top; - return 0; -} - -static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top) -{ - struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; - int stat = pvr2_hdw_check_cropcap(cptr->hdw); - if (stat != 0) { - return stat; - } - *top = cap->bounds.top; - if (cap->bounds.height > cptr->hdw->croph_val) { - *top += cap->bounds.height - cptr->hdw->croph_val; - } - return 0; -} - -static int ctrl_cropw_max_get(struct pvr2_ctrl *cptr, int *width) -{ - struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; - int stat, bleftend, cleft; - - stat = pvr2_hdw_check_cropcap(cptr->hdw); - if (stat != 0) { - return stat; - } - bleftend = cap->bounds.left+cap->bounds.width; - cleft = cptr->hdw->cropl_val; - - *width = cleft < bleftend ? bleftend-cleft : 0; - return 0; -} - -static int ctrl_croph_max_get(struct pvr2_ctrl *cptr, int *height) -{ - struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; - int stat, btopend, ctop; - - stat = pvr2_hdw_check_cropcap(cptr->hdw); - if (stat != 0) { - return stat; - } - btopend = cap->bounds.top+cap->bounds.height; - ctop = cptr->hdw->cropt_val; - - *height = ctop < btopend ? btopend-ctop : 0; - return 0; -} - -static int ctrl_get_cropcapbl(struct pvr2_ctrl *cptr, int *val) -{ - struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; - int stat = pvr2_hdw_check_cropcap(cptr->hdw); - if (stat != 0) { - return stat; - } - *val = cap->bounds.left; - return 0; -} - -static int ctrl_get_cropcapbt(struct pvr2_ctrl *cptr, int *val) -{ - struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; - int stat = pvr2_hdw_check_cropcap(cptr->hdw); - if (stat != 0) { - return stat; - } - *val = cap->bounds.top; - return 0; -} - -static int ctrl_get_cropcapbw(struct pvr2_ctrl *cptr, int *val) -{ - struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; - int stat = pvr2_hdw_check_cropcap(cptr->hdw); - if (stat != 0) { - return stat; - } - *val = cap->bounds.width; - return 0; -} - -static int ctrl_get_cropcapbh(struct pvr2_ctrl *cptr, int *val) -{ - struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; - int stat = pvr2_hdw_check_cropcap(cptr->hdw); - if (stat != 0) { - return stat; - } - *val = cap->bounds.height; - return 0; -} - -static int ctrl_get_cropcapdl(struct pvr2_ctrl *cptr, int *val) -{ - struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; - int stat = pvr2_hdw_check_cropcap(cptr->hdw); - if (stat != 0) { - return stat; - } - *val = cap->defrect.left; - return 0; -} - -static int ctrl_get_cropcapdt(struct pvr2_ctrl *cptr, int *val) -{ - struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; - int stat = pvr2_hdw_check_cropcap(cptr->hdw); - if (stat != 0) { - return stat; - } - *val = cap->defrect.top; - return 0; -} - -static int ctrl_get_cropcapdw(struct pvr2_ctrl *cptr, int *val) -{ - struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; - int stat = pvr2_hdw_check_cropcap(cptr->hdw); - if (stat != 0) { - return stat; - } - *val = cap->defrect.width; - return 0; -} - -static int ctrl_get_cropcapdh(struct pvr2_ctrl *cptr, int *val) -{ - struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; - int stat = pvr2_hdw_check_cropcap(cptr->hdw); - if (stat != 0) { - return stat; - } - *val = cap->defrect.height; - return 0; -} - -static int ctrl_get_cropcappan(struct pvr2_ctrl *cptr, int *val) -{ - struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; - int stat = pvr2_hdw_check_cropcap(cptr->hdw); - if (stat != 0) { - return stat; - } - *val = cap->pixelaspect.numerator; - return 0; -} - -static int ctrl_get_cropcappad(struct pvr2_ctrl *cptr, int *val) -{ - struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; - int stat = pvr2_hdw_check_cropcap(cptr->hdw); - if (stat != 0) { - return stat; - } - *val = cap->pixelaspect.denominator; - return 0; -} - -static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) -{ - /* Actual maximum depends on the video standard in effect. */ - if (cptr->hdw->std_mask_cur & V4L2_STD_525_60) { - *vp = 480; - } else { - *vp = 576; - } - return 0; -} - -static int ctrl_vres_min_get(struct pvr2_ctrl *cptr,int *vp) -{ - /* Actual minimum depends on device digitizer type. */ - if (cptr->hdw->hdw_desc->flag_has_cx25840) { - *vp = 75; - } else { - *vp = 17; - } - return 0; -} - -static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp) -{ - *vp = cptr->hdw->input_val; - return 0; -} - -static int ctrl_check_input(struct pvr2_ctrl *cptr,int v) -{ - return ((1 << v) & cptr->hdw->input_allowed_mask) != 0; -} - -static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v) -{ - return pvr2_hdw_set_input(cptr->hdw,v); -} - -static int ctrl_isdirty_input(struct pvr2_ctrl *cptr) -{ - return cptr->hdw->input_dirty != 0; -} - -static void ctrl_cleardirty_input(struct pvr2_ctrl *cptr) -{ - cptr->hdw->input_dirty = 0; -} - - -static int ctrl_freq_max_get(struct pvr2_ctrl *cptr, int *vp) -{ - unsigned long fv; - struct pvr2_hdw *hdw = cptr->hdw; - if (hdw->tuner_signal_stale) { - pvr2_hdw_status_poll(hdw); - } - fv = hdw->tuner_signal_info.rangehigh; - if (!fv) { - /* Safety fallback */ - *vp = TV_MAX_FREQ; - return 0; - } - if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) { - fv = (fv * 125) / 2; - } else { - fv = fv * 62500; - } - *vp = fv; - return 0; -} - -static int ctrl_freq_min_get(struct pvr2_ctrl *cptr, int *vp) -{ - unsigned long fv; - struct pvr2_hdw *hdw = cptr->hdw; - if (hdw->tuner_signal_stale) { - pvr2_hdw_status_poll(hdw); - } - fv = hdw->tuner_signal_info.rangelow; - if (!fv) { - /* Safety fallback */ - *vp = TV_MIN_FREQ; - return 0; - } - if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) { - fv = (fv * 125) / 2; - } else { - fv = fv * 62500; - } - *vp = fv; - return 0; -} - -static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr) -{ - return cptr->hdw->enc_stale != 0; -} - -static void ctrl_cx2341x_clear_dirty(struct pvr2_ctrl *cptr) -{ - cptr->hdw->enc_stale = 0; - cptr->hdw->enc_unsafe_stale = 0; -} - -static int ctrl_cx2341x_get(struct pvr2_ctrl *cptr,int *vp) -{ - int ret; - struct v4l2_ext_controls cs; - struct v4l2_ext_control c1; - memset(&cs,0,sizeof(cs)); - memset(&c1,0,sizeof(c1)); - cs.controls = &c1; - cs.count = 1; - c1.id = cptr->info->v4l_id; - ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state, 0, &cs, - VIDIOC_G_EXT_CTRLS); - if (ret) return ret; - *vp = c1.value; - return 0; -} - -static int ctrl_cx2341x_set(struct pvr2_ctrl *cptr,int m,int v) -{ - int ret; - struct pvr2_hdw *hdw = cptr->hdw; - struct v4l2_ext_controls cs; - struct v4l2_ext_control c1; - memset(&cs,0,sizeof(cs)); - memset(&c1,0,sizeof(c1)); - cs.controls = &c1; - cs.count = 1; - c1.id = cptr->info->v4l_id; - c1.value = v; - ret = cx2341x_ext_ctrls(&hdw->enc_ctl_state, - hdw->state_encoder_run, &cs, - VIDIOC_S_EXT_CTRLS); - if (ret == -EBUSY) { - /* Oops. cx2341x is telling us it's not safe to change - this control while we're capturing. Make a note of this - fact so that the pipeline will be stopped the next time - controls are committed. Then go on ahead and store this - change anyway. */ - ret = cx2341x_ext_ctrls(&hdw->enc_ctl_state, - 0, &cs, - VIDIOC_S_EXT_CTRLS); - if (!ret) hdw->enc_unsafe_stale = !0; - } - if (ret) return ret; - hdw->enc_stale = !0; - return 0; -} - -static unsigned int ctrl_cx2341x_getv4lflags(struct pvr2_ctrl *cptr) -{ - struct v4l2_queryctrl qctrl; - struct pvr2_ctl_info *info; - qctrl.id = cptr->info->v4l_id; - cx2341x_ctrl_query(&cptr->hdw->enc_ctl_state,&qctrl); - /* Strip out the const so we can adjust a function pointer. It's - OK to do this here because we know this is a dynamically created - control, so the underlying storage for the info pointer is (a) - private to us, and (b) not in read-only storage. Either we do - this or we significantly complicate the underlying control - implementation. */ - info = (struct pvr2_ctl_info *)(cptr->info); - if (qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) { - if (info->set_value) { - info->set_value = NULL; - } - } else { - if (!(info->set_value)) { - info->set_value = ctrl_cx2341x_set; - } - } - return qctrl.flags; -} - -static int ctrl_streamingenabled_get(struct pvr2_ctrl *cptr,int *vp) -{ - *vp = cptr->hdw->state_pipeline_req; - return 0; -} - -static int ctrl_masterstate_get(struct pvr2_ctrl *cptr,int *vp) -{ - *vp = cptr->hdw->master_state; - return 0; -} - -static int ctrl_hsm_get(struct pvr2_ctrl *cptr,int *vp) -{ - int result = pvr2_hdw_is_hsm(cptr->hdw); - *vp = PVR2_CVAL_HSM_FULL; - if (result < 0) *vp = PVR2_CVAL_HSM_FAIL; - if (result) *vp = PVR2_CVAL_HSM_HIGH; - return 0; -} - -static int ctrl_stddetect_get(struct pvr2_ctrl *cptr, int *vp) -{ - *vp = pvr2_hdw_get_detected_std(cptr->hdw); - return 0; -} - -static int ctrl_stdavail_get(struct pvr2_ctrl *cptr,int *vp) -{ - *vp = cptr->hdw->std_mask_avail; - return 0; -} - -static int ctrl_stdavail_set(struct pvr2_ctrl *cptr,int m,int v) -{ - struct pvr2_hdw *hdw = cptr->hdw; - v4l2_std_id ns; - ns = hdw->std_mask_avail; - ns = (ns & ~m) | (v & m); - if (ns == hdw->std_mask_avail) return 0; - hdw->std_mask_avail = ns; - hdw->std_info_cur.def.type_bitmask.valid_bits = hdw->std_mask_avail; - return 0; -} - -static int ctrl_std_val_to_sym(struct pvr2_ctrl *cptr,int msk,int val, - char *bufPtr,unsigned int bufSize, - unsigned int *len) -{ - *len = pvr2_std_id_to_str(bufPtr,bufSize,msk & val); - return 0; -} - -static int ctrl_std_sym_to_val(struct pvr2_ctrl *cptr, - const char *bufPtr,unsigned int bufSize, - int *mskp,int *valp) -{ - int ret; - v4l2_std_id id; - ret = pvr2_std_str_to_id(&id,bufPtr,bufSize); - if (ret < 0) return ret; - if (mskp) *mskp = id; - if (valp) *valp = id; - return 0; -} - -static int ctrl_stdcur_get(struct pvr2_ctrl *cptr,int *vp) -{ - *vp = cptr->hdw->std_mask_cur; - return 0; -} - -static int ctrl_stdcur_set(struct pvr2_ctrl *cptr,int m,int v) -{ - struct pvr2_hdw *hdw = cptr->hdw; - v4l2_std_id ns; - ns = hdw->std_mask_cur; - ns = (ns & ~m) | (v & m); - if (ns == hdw->std_mask_cur) return 0; - hdw->std_mask_cur = ns; - hdw->std_dirty = !0; - return 0; -} - -static int ctrl_stdcur_is_dirty(struct pvr2_ctrl *cptr) -{ - return cptr->hdw->std_dirty != 0; -} - -static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr) -{ - cptr->hdw->std_dirty = 0; -} - -static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp) -{ - struct pvr2_hdw *hdw = cptr->hdw; - pvr2_hdw_status_poll(hdw); - *vp = hdw->tuner_signal_info.signal; - return 0; -} - -static int ctrl_audio_modes_present_get(struct pvr2_ctrl *cptr,int *vp) -{ - int val = 0; - unsigned int subchan; - struct pvr2_hdw *hdw = cptr->hdw; - pvr2_hdw_status_poll(hdw); - subchan = hdw->tuner_signal_info.rxsubchans; - if (subchan & V4L2_TUNER_SUB_MONO) { - val |= (1 << V4L2_TUNER_MODE_MONO); - } - if (subchan & V4L2_TUNER_SUB_STEREO) { - val |= (1 << V4L2_TUNER_MODE_STEREO); - } - if (subchan & V4L2_TUNER_SUB_LANG1) { - val |= (1 << V4L2_TUNER_MODE_LANG1); - } - if (subchan & V4L2_TUNER_SUB_LANG2) { - val |= (1 << V4L2_TUNER_MODE_LANG2); - } - *vp = val; - return 0; -} - - -#define DEFINT(vmin,vmax) \ - .type = pvr2_ctl_int, \ - .def.type_int.min_value = vmin, \ - .def.type_int.max_value = vmax - -#define DEFENUM(tab) \ - .type = pvr2_ctl_enum, \ - .def.type_enum.count = ARRAY_SIZE(tab), \ - .def.type_enum.value_names = tab - -#define DEFBOOL \ - .type = pvr2_ctl_bool - -#define DEFMASK(msk,tab) \ - .type = pvr2_ctl_bitmask, \ - .def.type_bitmask.valid_bits = msk, \ - .def.type_bitmask.bit_names = tab - -#define DEFREF(vname) \ - .set_value = ctrl_set_##vname, \ - .get_value = ctrl_get_##vname, \ - .is_dirty = ctrl_isdirty_##vname, \ - .clear_dirty = ctrl_cleardirty_##vname - - -#define VCREATE_FUNCS(vname) \ -static int ctrl_get_##vname(struct pvr2_ctrl *cptr,int *vp) \ -{*vp = cptr->hdw->vname##_val; return 0;} \ -static int ctrl_set_##vname(struct pvr2_ctrl *cptr,int m,int v) \ -{cptr->hdw->vname##_val = v; cptr->hdw->vname##_dirty = !0; return 0;} \ -static int ctrl_isdirty_##vname(struct pvr2_ctrl *cptr) \ -{return cptr->hdw->vname##_dirty != 0;} \ -static void ctrl_cleardirty_##vname(struct pvr2_ctrl *cptr) \ -{cptr->hdw->vname##_dirty = 0;} - -VCREATE_FUNCS(brightness) -VCREATE_FUNCS(contrast) -VCREATE_FUNCS(saturation) -VCREATE_FUNCS(hue) -VCREATE_FUNCS(volume) -VCREATE_FUNCS(balance) -VCREATE_FUNCS(bass) -VCREATE_FUNCS(treble) -VCREATE_FUNCS(mute) -VCREATE_FUNCS(cropl) -VCREATE_FUNCS(cropt) -VCREATE_FUNCS(cropw) -VCREATE_FUNCS(croph) -VCREATE_FUNCS(audiomode) -VCREATE_FUNCS(res_hor) -VCREATE_FUNCS(res_ver) -VCREATE_FUNCS(srate) - -/* Table definition of all controls which can be manipulated */ -static const struct pvr2_ctl_info control_defs[] = { - { - .v4l_id = V4L2_CID_BRIGHTNESS, - .desc = "Brightness", - .name = "brightness", - .default_value = 128, - DEFREF(brightness), - DEFINT(0,255), - },{ - .v4l_id = V4L2_CID_CONTRAST, - .desc = "Contrast", - .name = "contrast", - .default_value = 68, - DEFREF(contrast), - DEFINT(0,127), - },{ - .v4l_id = V4L2_CID_SATURATION, - .desc = "Saturation", - .name = "saturation", - .default_value = 64, - DEFREF(saturation), - DEFINT(0,127), - },{ - .v4l_id = V4L2_CID_HUE, - .desc = "Hue", - .name = "hue", - .default_value = 0, - DEFREF(hue), - DEFINT(-128,127), - },{ - .v4l_id = V4L2_CID_AUDIO_VOLUME, - .desc = "Volume", - .name = "volume", - .default_value = 62000, - DEFREF(volume), - DEFINT(0,65535), - },{ - .v4l_id = V4L2_CID_AUDIO_BALANCE, - .desc = "Balance", - .name = "balance", - .default_value = 0, - DEFREF(balance), - DEFINT(-32768,32767), - },{ - .v4l_id = V4L2_CID_AUDIO_BASS, - .desc = "Bass", - .name = "bass", - .default_value = 0, - DEFREF(bass), - DEFINT(-32768,32767), - },{ - .v4l_id = V4L2_CID_AUDIO_TREBLE, - .desc = "Treble", - .name = "treble", - .default_value = 0, - DEFREF(treble), - DEFINT(-32768,32767), - },{ - .v4l_id = V4L2_CID_AUDIO_MUTE, - .desc = "Mute", - .name = "mute", - .default_value = 0, - DEFREF(mute), - DEFBOOL, - }, { - .desc = "Capture crop left margin", - .name = "crop_left", - .internal_id = PVR2_CID_CROPL, - .default_value = 0, - DEFREF(cropl), - DEFINT(-129, 340), - .get_min_value = ctrl_cropl_min_get, - .get_max_value = ctrl_cropl_max_get, - .get_def_value = ctrl_get_cropcapdl, - }, { - .desc = "Capture crop top margin", - .name = "crop_top", - .internal_id = PVR2_CID_CROPT, - .default_value = 0, - DEFREF(cropt), - DEFINT(-35, 544), - .get_min_value = ctrl_cropt_min_get, - .get_max_value = ctrl_cropt_max_get, - .get_def_value = ctrl_get_cropcapdt, - }, { - .desc = "Capture crop width", - .name = "crop_width", - .internal_id = PVR2_CID_CROPW, - .default_value = 720, - DEFREF(cropw), - DEFINT(0, 864), - .get_max_value = ctrl_cropw_max_get, - .get_def_value = ctrl_get_cropcapdw, - }, { - .desc = "Capture crop height", - .name = "crop_height", - .internal_id = PVR2_CID_CROPH, - .default_value = 480, - DEFREF(croph), - DEFINT(0, 576), - .get_max_value = ctrl_croph_max_get, - .get_def_value = ctrl_get_cropcapdh, - }, { - .desc = "Capture capability pixel aspect numerator", - .name = "cropcap_pixel_numerator", - .internal_id = PVR2_CID_CROPCAPPAN, - .get_value = ctrl_get_cropcappan, - }, { - .desc = "Capture capability pixel aspect denominator", - .name = "cropcap_pixel_denominator", - .internal_id = PVR2_CID_CROPCAPPAD, - .get_value = ctrl_get_cropcappad, - }, { - .desc = "Capture capability bounds top", - .name = "cropcap_bounds_top", - .internal_id = PVR2_CID_CROPCAPBT, - .get_value = ctrl_get_cropcapbt, - }, { - .desc = "Capture capability bounds left", - .name = "cropcap_bounds_left", - .internal_id = PVR2_CID_CROPCAPBL, - .get_value = ctrl_get_cropcapbl, - }, { - .desc = "Capture capability bounds width", - .name = "cropcap_bounds_width", - .internal_id = PVR2_CID_CROPCAPBW, - .get_value = ctrl_get_cropcapbw, - }, { - .desc = "Capture capability bounds height", - .name = "cropcap_bounds_height", - .internal_id = PVR2_CID_CROPCAPBH, - .get_value = ctrl_get_cropcapbh, - },{ - .desc = "Video Source", - .name = "input", - .internal_id = PVR2_CID_INPUT, - .default_value = PVR2_CVAL_INPUT_TV, - .check_value = ctrl_check_input, - DEFREF(input), - DEFENUM(control_values_input), - },{ - .desc = "Audio Mode", - .name = "audio_mode", - .internal_id = PVR2_CID_AUDIOMODE, - .default_value = V4L2_TUNER_MODE_STEREO, - DEFREF(audiomode), - DEFENUM(control_values_audiomode), - },{ - .desc = "Horizontal capture resolution", - .name = "resolution_hor", - .internal_id = PVR2_CID_HRES, - .default_value = 720, - DEFREF(res_hor), - DEFINT(19,720), - },{ - .desc = "Vertical capture resolution", - .name = "resolution_ver", - .internal_id = PVR2_CID_VRES, - .default_value = 480, - DEFREF(res_ver), - DEFINT(17,576), - /* Hook in check for video standard and adjust maximum - depending on the standard. */ - .get_max_value = ctrl_vres_max_get, - .get_min_value = ctrl_vres_min_get, - },{ - .v4l_id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, - .default_value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, - .desc = "Audio Sampling Frequency", - .name = "srate", - DEFREF(srate), - DEFENUM(control_values_srate), - },{ - .desc = "Tuner Frequency (Hz)", - .name = "frequency", - .internal_id = PVR2_CID_FREQUENCY, - .default_value = 0, - .set_value = ctrl_freq_set, - .get_value = ctrl_freq_get, - .is_dirty = ctrl_freq_is_dirty, - .clear_dirty = ctrl_freq_clear_dirty, - DEFINT(0,0), - /* Hook in check for input value (tv/radio) and adjust - max/min values accordingly */ - .get_max_value = ctrl_freq_max_get, - .get_min_value = ctrl_freq_min_get, - },{ - .desc = "Channel", - .name = "channel", - .set_value = ctrl_channel_set, - .get_value = ctrl_channel_get, - DEFINT(0,FREQTABLE_SIZE), - },{ - .desc = "Channel Program Frequency", - .name = "freq_table_value", - .set_value = ctrl_channelfreq_set, - .get_value = ctrl_channelfreq_get, - DEFINT(0,0), - /* Hook in check for input value (tv/radio) and adjust - max/min values accordingly */ - .get_max_value = ctrl_freq_max_get, - .get_min_value = ctrl_freq_min_get, - },{ - .desc = "Channel Program ID", - .name = "freq_table_channel", - .set_value = ctrl_channelprog_set, - .get_value = ctrl_channelprog_get, - DEFINT(0,FREQTABLE_SIZE), - },{ - .desc = "Streaming Enabled", - .name = "streaming_enabled", - .get_value = ctrl_streamingenabled_get, - DEFBOOL, - },{ - .desc = "USB Speed", - .name = "usb_speed", - .get_value = ctrl_hsm_get, - DEFENUM(control_values_hsm), - },{ - .desc = "Master State", - .name = "master_state", - .get_value = ctrl_masterstate_get, - DEFENUM(pvr2_state_names), - },{ - .desc = "Signal Present", - .name = "signal_present", - .get_value = ctrl_signal_get, - DEFINT(0,65535), - },{ - .desc = "Audio Modes Present", - .name = "audio_modes_present", - .get_value = ctrl_audio_modes_present_get, - /* For this type we "borrow" the V4L2_TUNER_MODE enum from - v4l. Nothing outside of this module cares about this, - but I reuse it in order to also reuse the - control_values_audiomode string table. */ - DEFMASK(((1 << V4L2_TUNER_MODE_MONO)| - (1 << V4L2_TUNER_MODE_STEREO)| - (1 << V4L2_TUNER_MODE_LANG1)| - (1 << V4L2_TUNER_MODE_LANG2)), - control_values_audiomode), - },{ - .desc = "Video Standards Available Mask", - .name = "video_standard_mask_available", - .internal_id = PVR2_CID_STDAVAIL, - .skip_init = !0, - .get_value = ctrl_stdavail_get, - .set_value = ctrl_stdavail_set, - .val_to_sym = ctrl_std_val_to_sym, - .sym_to_val = ctrl_std_sym_to_val, - .type = pvr2_ctl_bitmask, - },{ - .desc = "Video Standards In Use Mask", - .name = "video_standard_mask_active", - .internal_id = PVR2_CID_STDCUR, - .skip_init = !0, - .get_value = ctrl_stdcur_get, - .set_value = ctrl_stdcur_set, - .is_dirty = ctrl_stdcur_is_dirty, - .clear_dirty = ctrl_stdcur_clear_dirty, - .val_to_sym = ctrl_std_val_to_sym, - .sym_to_val = ctrl_std_sym_to_val, - .type = pvr2_ctl_bitmask, - },{ - .desc = "Video Standards Detected Mask", - .name = "video_standard_mask_detected", - .internal_id = PVR2_CID_STDDETECT, - .skip_init = !0, - .get_value = ctrl_stddetect_get, - .val_to_sym = ctrl_std_val_to_sym, - .sym_to_val = ctrl_std_sym_to_val, - .type = pvr2_ctl_bitmask, - } -}; - -#define CTRLDEF_COUNT ARRAY_SIZE(control_defs) - - -const char *pvr2_config_get_name(enum pvr2_config cfg) -{ - switch (cfg) { - case pvr2_config_empty: return "empty"; - case pvr2_config_mpeg: return "mpeg"; - case pvr2_config_vbi: return "vbi"; - case pvr2_config_pcm: return "pcm"; - case pvr2_config_rawvideo: return "raw video"; - } - return "<unknown>"; -} - - -struct usb_device *pvr2_hdw_get_dev(struct pvr2_hdw *hdw) -{ - return hdw->usb_dev; -} - - -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; -} - - -const char *pvr2_hdw_get_device_identifier(struct pvr2_hdw *hdw) -{ - return hdw->identifier; -} - - -unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw) -{ - return hdw->freqSelector ? hdw->freqValTelevision : hdw->freqValRadio; -} - -/* Set the currently tuned frequency and account for all possible - driver-core side effects of this action. */ -static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val) -{ - if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { - if (hdw->freqSelector) { - /* Swing over to radio frequency selection */ - hdw->freqSelector = 0; - hdw->freqDirty = !0; - } - if (hdw->freqValRadio != val) { - hdw->freqValRadio = val; - hdw->freqSlotRadio = 0; - hdw->freqDirty = !0; - } - } else { - if (!(hdw->freqSelector)) { - /* Swing over to television frequency selection */ - hdw->freqSelector = 1; - hdw->freqDirty = !0; - } - if (hdw->freqValTelevision != val) { - hdw->freqValTelevision = val; - hdw->freqSlotTelevision = 0; - hdw->freqDirty = !0; - } - } -} - -int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw) -{ - return hdw->unit_number; -} - - -/* Attempt to locate one of the given set of files. Messages are logged - appropriate to what has been found. The return value will be 0 or - greater on success (it will be the index of the file name found) and - fw_entry will be filled in. Otherwise a negative error is returned on - failure. If the return value is -ENOENT then no viable firmware file - could be located. */ -static int pvr2_locate_firmware(struct pvr2_hdw *hdw, - const struct firmware **fw_entry, - const char *fwtypename, - unsigned int fwcount, - const char *fwnames[]) -{ - unsigned int idx; - int ret = -EINVAL; - for (idx = 0; idx < fwcount; idx++) { - ret = request_firmware(fw_entry, - fwnames[idx], - &hdw->usb_dev->dev); - if (!ret) { - trace_firmware("Located %s firmware: %s;" - " uploading...", - fwtypename, - fwnames[idx]); - return idx; - } - if (ret == -ENOENT) continue; - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "request_firmware fatal error with code=%d",ret); - return ret; - } - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "***WARNING***" - " Device %s firmware" - " seems to be missing.", - fwtypename); - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Did you install the pvrusb2 firmware files" - " in their proper location?"); - if (fwcount == 1) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "request_firmware unable to locate %s file %s", - fwtypename,fwnames[0]); - } else { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "request_firmware unable to locate" - " one of the following %s files:", - fwtypename); - for (idx = 0; idx < fwcount; idx++) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "request_firmware: Failed to find %s", - fwnames[idx]); - } - } - return ret; -} - - -/* - * pvr2_upload_firmware1(). - * - * Send the 8051 firmware to the device. After the upload, arrange for - * device to re-enumerate. - * - * NOTE : the pointer to the firmware data given by request_firmware() - * is not suitable for an usb transaction. - * - */ -static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) -{ - const struct firmware *fw_entry = NULL; - void *fw_ptr; - unsigned int pipe; - unsigned int fwsize; - int ret; - u16 address; - - if (!hdw->hdw_desc->fx2_firmware.cnt) { - hdw->fw1_state = FW1_STATE_OK; - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Connected device type defines" - " no firmware to upload; ignoring firmware"); - return -ENOTTY; - } - - hdw->fw1_state = FW1_STATE_FAILED; // default result - - trace_firmware("pvr2_upload_firmware1"); - - ret = pvr2_locate_firmware(hdw,&fw_entry,"fx2 controller", - hdw->hdw_desc->fx2_firmware.cnt, - hdw->hdw_desc->fx2_firmware.lst); - if (ret < 0) { - if (ret == -ENOENT) hdw->fw1_state = FW1_STATE_MISSING; - return ret; - } - - usb_clear_halt(hdw->usb_dev, usb_sndbulkpipe(hdw->usb_dev, 0 & 0x7f)); - - pipe = usb_sndctrlpipe(hdw->usb_dev, 0); - fwsize = fw_entry->size; - - if ((fwsize != 0x2000) && - (!(hdw->hdw_desc->flag_fx2_16kb && (fwsize == 0x4000)))) { - if (hdw->hdw_desc->flag_fx2_16kb) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Wrong fx2 firmware size" - " (expected 8192 or 16384, got %u)", - fwsize); - } else { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Wrong fx2 firmware size" - " (expected 8192, got %u)", - fwsize); - } - release_firmware(fw_entry); - return -ENOMEM; - } - - fw_ptr = kmalloc(0x800, GFP_KERNEL); - if (fw_ptr == NULL){ - release_firmware(fw_entry); - return -ENOMEM; - } - - /* We have to hold the CPU during firmware upload. */ - pvr2_hdw_cpureset_assert(hdw,1); - - /* upload the firmware to address 0000-1fff in 2048 (=0x800) bytes - chunk. */ - - ret = 0; - for (address = 0; address < fwsize; address += 0x800) { - memcpy(fw_ptr, fw_entry->data + address, 0x800); - ret += usb_control_msg(hdw->usb_dev, pipe, 0xa0, 0x40, address, - 0, fw_ptr, 0x800, HZ); - } - - trace_firmware("Upload done, releasing device's CPU"); - - /* Now release the CPU. It will disconnect and reconnect later. */ - pvr2_hdw_cpureset_assert(hdw,0); - - kfree(fw_ptr); - release_firmware(fw_entry); - - trace_firmware("Upload done (%d bytes sent)",ret); - - /* We should have written fwsize bytes */ - if (ret == fwsize) { - hdw->fw1_state = FW1_STATE_RELOAD; - return 0; - } - - return -EIO; -} - - -/* - * pvr2_upload_firmware2() - * - * This uploads encoder firmware on endpoint 2. - * - */ - -int pvr2_upload_firmware2(struct pvr2_hdw *hdw) -{ - const struct firmware *fw_entry = NULL; - void *fw_ptr; - unsigned int pipe, fw_len, fw_done, bcnt, icnt; - int actual_length; - int ret = 0; - int fwidx; - static const char *fw_files[] = { - CX2341X_FIRM_ENC_FILENAME, - }; - - if (hdw->hdw_desc->flag_skip_cx23416_firmware) { - return 0; - } - - trace_firmware("pvr2_upload_firmware2"); - - ret = pvr2_locate_firmware(hdw,&fw_entry,"encoder", - ARRAY_SIZE(fw_files), fw_files); - if (ret < 0) return ret; - fwidx = ret; - ret = 0; - /* Since we're about to completely reinitialize the encoder, - invalidate our cached copy of its configuration state. Next - time we configure the encoder, then we'll fully configure it. */ - hdw->enc_cur_valid = 0; - - /* Encoder is about to be reset so note that as far as we're - concerned now, the encoder has never been run. */ - del_timer_sync(&hdw->encoder_run_timer); - if (hdw->state_encoder_runok) { - hdw->state_encoder_runok = 0; - trace_stbit("state_encoder_runok",hdw->state_encoder_runok); - } - - /* First prepare firmware loading */ - ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/ - ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000088); /*gpio dir*/ - ret |= pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000008); /*gpio output state*/ - ret |= pvr2_hdw_cmd_deep_reset(hdw); - ret |= pvr2_write_register(hdw, 0xa064, 0x00000000); /*APU command*/ - ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000408); /*gpio dir*/ - ret |= pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000008); /*gpio output state*/ - ret |= pvr2_write_register(hdw, 0x9058, 0xffffffed); /*VPU ctrl*/ - ret |= pvr2_write_register(hdw, 0x9054, 0xfffffffd); /*reset hw blocks*/ - ret |= pvr2_write_register(hdw, 0x07f8, 0x80000800); /*encoder SDRAM refresh*/ - ret |= pvr2_write_register(hdw, 0x07fc, 0x0000001a); /*encoder SDRAM pre-charge*/ - ret |= pvr2_write_register(hdw, 0x0700, 0x00000000); /*I2C clock*/ - ret |= pvr2_write_register(hdw, 0xaa00, 0x00000000); /*unknown*/ - ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/ - ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/ - ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/ - ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_FWPOST1); - ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16)); - - if (ret) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "firmware2 upload prep failed, ret=%d",ret); - release_firmware(fw_entry); - goto done; - } - - /* Now send firmware */ - - fw_len = fw_entry->size; - - if (fw_len % sizeof(u32)) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "size of %s firmware" - " must be a multiple of %zu bytes", - fw_files[fwidx],sizeof(u32)); - release_firmware(fw_entry); - ret = -EINVAL; - goto done; - } - - fw_ptr = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL); - if (fw_ptr == NULL){ - release_firmware(fw_entry); - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "failed to allocate memory for firmware2 upload"); - ret = -ENOMEM; - goto done; - } - - pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT); - - fw_done = 0; - for (fw_done = 0; fw_done < fw_len;) { - bcnt = fw_len - fw_done; - if (bcnt > FIRMWARE_CHUNK_SIZE) bcnt = FIRMWARE_CHUNK_SIZE; - memcpy(fw_ptr, fw_entry->data + fw_done, bcnt); - /* Usbsnoop log shows that we must swap bytes... */ - /* Some background info: The data being swapped here is a - firmware image destined for the mpeg encoder chip that - lives at the other end of a USB endpoint. The encoder - chip always talks in 32 bit chunks and its storage is - organized into 32 bit words. However from the file - system to the encoder chip everything is purely a byte - stream. The firmware file's contents are always 32 bit - swapped from what the encoder expects. Thus the need - always exists to swap the bytes regardless of the endian - type of the host processor and therefore swab32() makes - the most sense. */ - for (icnt = 0; icnt < bcnt/4 ; icnt++) - ((u32 *)fw_ptr)[icnt] = swab32(((u32 *)fw_ptr)[icnt]); - - ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt, - &actual_length, HZ); - ret |= (actual_length != bcnt); - if (ret) break; - fw_done += bcnt; - } - - trace_firmware("upload of %s : %i / %i ", - fw_files[fwidx],fw_done,fw_len); - - kfree(fw_ptr); - release_firmware(fw_entry); - - if (ret) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "firmware2 upload transfer failure"); - goto done; - } - - /* Finish upload */ - - ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/ - ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/ - ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16)); - - if (ret) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "firmware2 upload post-proc failure"); - } - - done: - if (hdw->hdw_desc->signal_routing_scheme == - PVR2_ROUTING_SCHEME_GOTVIEW) { - /* Ensure that GPIO 11 is set to output for GOTVIEW - hardware. */ - pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0); - } - return ret; -} - - -static const char *pvr2_get_state_name(unsigned int st) -{ - if (st < ARRAY_SIZE(pvr2_state_names)) { - return pvr2_state_names[st]; - } - return "???"; -} - -static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl) -{ - /* Even though we really only care about the video decoder chip at - this point, we'll broadcast stream on/off to all sub-devices - anyway, just in case somebody else wants to hear the - command... */ - pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 stream=%s", - (enablefl ? "on" : "off")); - v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_stream, enablefl); - v4l2_device_call_all(&hdw->v4l2_dev, 0, audio, s_stream, enablefl); - if (hdw->decoder_client_id) { - /* We get here if the encoder has been noticed. Otherwise - we'll issue a warning to the user (which should - normally never happen). */ - return 0; - } - if (!hdw->flag_decoder_missed) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "WARNING: No decoder present"); - hdw->flag_decoder_missed = !0; - trace_stbit("flag_decoder_missed", - hdw->flag_decoder_missed); - } - return -EIO; -} - - -int pvr2_hdw_get_state(struct pvr2_hdw *hdw) -{ - return hdw->master_state; -} - - -static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *hdw) -{ - if (!hdw->flag_tripped) return 0; - hdw->flag_tripped = 0; - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Clearing driver error statuss"); - return !0; -} - - -int pvr2_hdw_untrip(struct pvr2_hdw *hdw) -{ - int fl; - LOCK_TAKE(hdw->big_lock); do { - fl = pvr2_hdw_untrip_unlocked(hdw); - } while (0); LOCK_GIVE(hdw->big_lock); - if (fl) pvr2_hdw_state_sched(hdw); - return 0; -} - - - - -int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw) -{ - return hdw->state_pipeline_req != 0; -} - - -int pvr2_hdw_set_streaming(struct pvr2_hdw *hdw,int enable_flag) -{ - int ret,st; - LOCK_TAKE(hdw->big_lock); do { - pvr2_hdw_untrip_unlocked(hdw); - if ((!enable_flag) != !(hdw->state_pipeline_req)) { - hdw->state_pipeline_req = enable_flag != 0; - pvr2_trace(PVR2_TRACE_START_STOP, - "/*--TRACE_STREAM--*/ %s", - enable_flag ? "enable" : "disable"); - } - pvr2_hdw_state_sched(hdw); - } while (0); LOCK_GIVE(hdw->big_lock); - if ((ret = pvr2_hdw_wait(hdw,0)) < 0) return ret; - if (enable_flag) { - while ((st = hdw->master_state) != PVR2_STATE_RUN) { - if (st != PVR2_STATE_READY) return -EIO; - if ((ret = pvr2_hdw_wait(hdw,st)) < 0) return ret; - } - } - return 0; -} - - -int pvr2_hdw_set_stream_type(struct pvr2_hdw *hdw,enum pvr2_config config) -{ - int fl; - LOCK_TAKE(hdw->big_lock); - if ((fl = (hdw->desired_stream_type != config)) != 0) { - hdw->desired_stream_type = config; - hdw->state_pipeline_config = 0; - trace_stbit("state_pipeline_config", - hdw->state_pipeline_config); - pvr2_hdw_state_sched(hdw); - } - LOCK_GIVE(hdw->big_lock); - if (fl) return 0; - return pvr2_hdw_wait(hdw,0); -} - - -static int get_default_tuner_type(struct pvr2_hdw *hdw) -{ - int unit_number = hdw->unit_number; - int tp = -1; - if ((unit_number >= 0) && (unit_number < PVR_NUM)) { - tp = tuner[unit_number]; - } - if (tp < 0) return -EINVAL; - hdw->tuner_type = tp; - hdw->tuner_updated = !0; - return 0; -} - - -static v4l2_std_id get_default_standard(struct pvr2_hdw *hdw) -{ - int unit_number = hdw->unit_number; - int tp = 0; - if ((unit_number >= 0) && (unit_number < PVR_NUM)) { - tp = video_std[unit_number]; - if (tp) return tp; - } - return 0; -} - - -static unsigned int get_default_error_tolerance(struct pvr2_hdw *hdw) -{ - int unit_number = hdw->unit_number; - int tp = 0; - if ((unit_number >= 0) && (unit_number < PVR_NUM)) { - tp = tolerance[unit_number]; - } - return tp; -} - - -static int pvr2_hdw_check_firmware(struct pvr2_hdw *hdw) -{ - /* Try a harmless request to fetch the eeprom's address over - endpoint 1. See what happens. Only the full FX2 image can - respond to this. If this probe fails then likely the FX2 - firmware needs be loaded. */ - int result; - LOCK_TAKE(hdw->ctl_lock); do { - hdw->cmd_buffer[0] = FX2CMD_GET_EEPROM_ADDR; - result = pvr2_send_request_ex(hdw,HZ*1,!0, - hdw->cmd_buffer,1, - hdw->cmd_buffer,1); - if (result < 0) break; - } while(0); LOCK_GIVE(hdw->ctl_lock); - if (result) { - pvr2_trace(PVR2_TRACE_INIT, - "Probe of device endpoint 1 result status %d", - result); - } else { - pvr2_trace(PVR2_TRACE_INIT, - "Probe of device endpoint 1 succeeded"); - } - return result == 0; -} - -struct pvr2_std_hack { - v4l2_std_id pat; /* Pattern to match */ - v4l2_std_id msk; /* Which bits we care about */ - v4l2_std_id std; /* What additional standards or default to set */ -}; - -/* This data structure labels specific combinations of standards from - tveeprom that we'll try to recognize. If we recognize one, then assume - a specified default standard to use. This is here because tveeprom only - tells us about available standards not the intended default standard (if - any) for the device in question. We guess the default based on what has - been reported as available. Note that this is only for guessing a - default - which can always be overridden explicitly - and if the user - has otherwise named a default then that default will always be used in - place of this table. */ -static const struct pvr2_std_hack std_eeprom_maps[] = { - { /* PAL(B/G) */ - .pat = V4L2_STD_B|V4L2_STD_GH, - .std = V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_PAL_G, - }, - { /* NTSC(M) */ - .pat = V4L2_STD_MN, - .std = V4L2_STD_NTSC_M, - }, - { /* PAL(I) */ - .pat = V4L2_STD_PAL_I, - .std = V4L2_STD_PAL_I, - }, - { /* SECAM(L/L') */ - .pat = V4L2_STD_SECAM_L|V4L2_STD_SECAM_LC, - .std = V4L2_STD_SECAM_L|V4L2_STD_SECAM_LC, - }, - { /* PAL(D/D1/K) */ - .pat = V4L2_STD_DK, - .std = V4L2_STD_PAL_D|V4L2_STD_PAL_D1|V4L2_STD_PAL_K, - }, -}; - -static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw) -{ - char buf[40]; - unsigned int bcnt; - v4l2_std_id std1,std2,std3; - - std1 = get_default_standard(hdw); - std3 = std1 ? 0 : hdw->hdw_desc->default_std_mask; - - bcnt = pvr2_std_id_to_str(buf,sizeof(buf),hdw->std_mask_eeprom); - pvr2_trace(PVR2_TRACE_STD, - "Supported video standard(s) reported available" - " in hardware: %.*s", - bcnt,buf); - - hdw->std_mask_avail = hdw->std_mask_eeprom; - - std2 = (std1|std3) & ~hdw->std_mask_avail; - if (std2) { - bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std2); - pvr2_trace(PVR2_TRACE_STD, - "Expanding supported video standards" - " to include: %.*s", - bcnt,buf); - hdw->std_mask_avail |= std2; - } - - hdw->std_info_cur.def.type_bitmask.valid_bits = hdw->std_mask_avail; - - if (std1) { - bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std1); - pvr2_trace(PVR2_TRACE_STD, - "Initial video standard forced to %.*s", - bcnt,buf); - hdw->std_mask_cur = std1; - hdw->std_dirty = !0; - return; - } - if (std3) { - bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std3); - pvr2_trace(PVR2_TRACE_STD, - "Initial video standard" - " (determined by device type): %.*s",bcnt,buf); - hdw->std_mask_cur = std3; - hdw->std_dirty = !0; - return; - } - - { - unsigned int idx; - for (idx = 0; idx < ARRAY_SIZE(std_eeprom_maps); idx++) { - if (std_eeprom_maps[idx].msk ? - ((std_eeprom_maps[idx].pat ^ - hdw->std_mask_eeprom) & - std_eeprom_maps[idx].msk) : - (std_eeprom_maps[idx].pat != - hdw->std_mask_eeprom)) continue; - bcnt = pvr2_std_id_to_str(buf,sizeof(buf), - std_eeprom_maps[idx].std); - pvr2_trace(PVR2_TRACE_STD, - "Initial video standard guessed as %.*s", - bcnt,buf); - hdw->std_mask_cur = std_eeprom_maps[idx].std; - hdw->std_dirty = !0; - return; - } - } - -} - - -static unsigned int pvr2_copy_i2c_addr_list( - unsigned short *dst, const unsigned char *src, - unsigned int dst_max) -{ - unsigned int cnt = 0; - if (!src) return 0; - while (src[cnt] && (cnt + 1) < dst_max) { - dst[cnt] = src[cnt]; - cnt++; - } - dst[cnt] = I2C_CLIENT_END; - return cnt; -} - - -static void pvr2_hdw_cx25840_vbi_hack(struct pvr2_hdw *hdw) -{ - /* - Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit of nuttiness - for cx25840 causes that module to correctly set up its video - scaling. This is really a problem in the cx25840 module itself, - but we work around it here. The problem has not been seen in - ivtv because there VBI is supported and set up. We don't do VBI - here (at least not yet) and thus we never attempted to even set - it up. - */ - struct v4l2_format fmt; - if (hdw->decoder_client_id != PVR2_CLIENT_ID_CX25840) { - /* We're not using a cx25840 so don't enable the hack */ - return; - } - - pvr2_trace(PVR2_TRACE_INIT, - "Module ID %u:" - " Executing cx25840 VBI hack", - hdw->decoder_client_id); - memset(&fmt, 0, sizeof(fmt)); - fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; - fmt.fmt.sliced.service_lines[0][21] = V4L2_SLICED_CAPTION_525; - fmt.fmt.sliced.service_lines[1][21] = V4L2_SLICED_CAPTION_525; - v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id, - vbi, s_sliced_fmt, &fmt.fmt.sliced); -} - - -static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, - const struct pvr2_device_client_desc *cd) -{ - const char *fname; - unsigned char mid; - struct v4l2_subdev *sd; - unsigned int i2ccnt; - const unsigned char *p; - /* Arbitrary count - max # i2c addresses we will probe */ - unsigned short i2caddr[25]; - - mid = cd->module_id; - fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL; - if (!fname) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Module ID %u for device %s has no name?" - " The driver might have a configuration problem.", - mid, - hdw->hdw_desc->description); - return -EINVAL; - } - pvr2_trace(PVR2_TRACE_INIT, - "Module ID %u (%s) for device %s being loaded...", - mid, fname, - hdw->hdw_desc->description); - - i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, cd->i2c_address_list, - ARRAY_SIZE(i2caddr)); - if (!i2ccnt && ((p = (mid < ARRAY_SIZE(module_i2c_addresses)) ? - module_i2c_addresses[mid] : NULL) != NULL)) { - /* Second chance: Try default i2c address list */ - i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, p, - ARRAY_SIZE(i2caddr)); - if (i2ccnt) { - pvr2_trace(PVR2_TRACE_INIT, - "Module ID %u:" - " Using default i2c address list", - mid); - } - } - - if (!i2ccnt) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Module ID %u (%s) for device %s:" - " No i2c addresses." - " The driver might have a configuration problem.", - mid, fname, hdw->hdw_desc->description); - return -EINVAL; - } - - if (i2ccnt == 1) { - pvr2_trace(PVR2_TRACE_INIT, - "Module ID %u:" - " Setting up with specified i2c address 0x%x", - mid, i2caddr[0]); - sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap, - fname, i2caddr[0], NULL); - } else { - pvr2_trace(PVR2_TRACE_INIT, - "Module ID %u:" - " Setting up with address probe list", - mid); - sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap, - fname, 0, i2caddr); - } - - if (!sd) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Module ID %u (%s) for device %s failed to load." - " Possible missing sub-device kernel module or" - " initialization failure within module.", - mid, fname, hdw->hdw_desc->description); - return -EIO; - } - - /* Tag this sub-device instance with the module ID we know about. - In other places we'll use that tag to determine if the instance - requires special handling. */ - sd->grp_id = mid; - - pvr2_trace(PVR2_TRACE_INFO, "Attached sub-driver %s", fname); - - - /* client-specific setup... */ - switch (mid) { - case PVR2_CLIENT_ID_CX25840: - case PVR2_CLIENT_ID_SAA7115: - hdw->decoder_client_id = mid; - break; - default: break; - } - - return 0; -} - - -static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw) -{ - unsigned int idx; - const struct pvr2_string_table *cm; - const struct pvr2_device_client_table *ct; - int okFl = !0; - - cm = &hdw->hdw_desc->client_modules; - for (idx = 0; idx < cm->cnt; idx++) { - request_module(cm->lst[idx]); - } - - ct = &hdw->hdw_desc->client_table; - for (idx = 0; idx < ct->cnt; idx++) { - if (pvr2_hdw_load_subdev(hdw, &ct->lst[idx]) < 0) okFl = 0; - } - if (!okFl) { - hdw->flag_modulefail = !0; - pvr2_hdw_render_useless(hdw); - } -} - - -static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) -{ - int ret; - unsigned int idx; - struct pvr2_ctrl *cptr; - int reloadFl = 0; - if (hdw->hdw_desc->fx2_firmware.cnt) { - if (!reloadFl) { - reloadFl = - (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints - == 0); - if (reloadFl) { - pvr2_trace(PVR2_TRACE_INIT, - "USB endpoint config looks strange" - "; possibly firmware needs to be" - " loaded"); - } - } - if (!reloadFl) { - reloadFl = !pvr2_hdw_check_firmware(hdw); - if (reloadFl) { - pvr2_trace(PVR2_TRACE_INIT, - "Check for FX2 firmware failed" - "; possibly firmware needs to be" - " loaded"); - } - } - if (reloadFl) { - if (pvr2_upload_firmware1(hdw) != 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Failure uploading firmware1"); - } - return; - } - } - hdw->fw1_state = FW1_STATE_OK; - - if (!pvr2_hdw_dev_ok(hdw)) return; - - hdw->force_dirty = !0; - - if (!hdw->hdw_desc->flag_no_powerup) { - pvr2_hdw_cmd_powerup(hdw); - if (!pvr2_hdw_dev_ok(hdw)) return; - } - - /* Take the IR chip out of reset, if appropriate */ - if (hdw->ir_scheme_active == PVR2_IR_SCHEME_ZILOG) { - pvr2_issue_simple_cmd(hdw, - FX2CMD_HCW_ZILOG_RESET | - (1 << 8) | - ((0) << 16)); - } - - // This step MUST happen after the earlier powerup step. - pvr2_i2c_core_init(hdw); - if (!pvr2_hdw_dev_ok(hdw)) return; - - pvr2_hdw_load_modules(hdw); - if (!pvr2_hdw_dev_ok(hdw)) return; - - v4l2_device_call_all(&hdw->v4l2_dev, 0, core, load_fw); - - for (idx = 0; idx < CTRLDEF_COUNT; idx++) { - cptr = hdw->controls + idx; - if (cptr->info->skip_init) continue; - if (!cptr->info->set_value) continue; - cptr->info->set_value(cptr,~0,cptr->info->default_value); - } - - pvr2_hdw_cx25840_vbi_hack(hdw); - - /* Set up special default values for the television and radio - frequencies here. It's not really important what these defaults - are, but I set them to something usable in the Chicago area just - to make driver testing a little easier. */ - - hdw->freqValTelevision = default_tv_freq; - hdw->freqValRadio = default_radio_freq; - - // Do not use pvr2_reset_ctl_endpoints() here. It is not - // thread-safe against the normal pvr2_send_request() mechanism. - // (We should make it thread safe). - - if (hdw->hdw_desc->flag_has_hauppauge_rom) { - ret = pvr2_hdw_get_eeprom_addr(hdw); - if (!pvr2_hdw_dev_ok(hdw)) return; - if (ret < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Unable to determine location of eeprom," - " skipping"); - } else { - hdw->eeprom_addr = ret; - pvr2_eeprom_analyze(hdw); - if (!pvr2_hdw_dev_ok(hdw)) return; - } - } else { - hdw->tuner_type = hdw->hdw_desc->default_tuner_type; - hdw->tuner_updated = !0; - hdw->std_mask_eeprom = V4L2_STD_ALL; - } - - if (hdw->serial_number) { - idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1, - "sn-%lu", hdw->serial_number); - } else if (hdw->unit_number >= 0) { - idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1, - "unit-%c", - hdw->unit_number + 'a'); - } else { - idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1, - "unit-??"); - } - hdw->identifier[idx] = 0; - - pvr2_hdw_setup_std(hdw); - - if (!get_default_tuner_type(hdw)) { - pvr2_trace(PVR2_TRACE_INIT, - "pvr2_hdw_setup: Tuner type overridden to %d", - hdw->tuner_type); - } - - - if (!pvr2_hdw_dev_ok(hdw)) return; - - if (hdw->hdw_desc->signal_routing_scheme == - PVR2_ROUTING_SCHEME_GOTVIEW) { - /* Ensure that GPIO 11 is set to output for GOTVIEW - hardware. */ - pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0); - } - - pvr2_hdw_commit_setup(hdw); - - hdw->vid_stream = pvr2_stream_create(); - if (!pvr2_hdw_dev_ok(hdw)) return; - pvr2_trace(PVR2_TRACE_INIT, - "pvr2_hdw_setup: video stream is %p",hdw->vid_stream); - if (hdw->vid_stream) { - idx = get_default_error_tolerance(hdw); - if (idx) { - pvr2_trace(PVR2_TRACE_INIT, - "pvr2_hdw_setup: video stream %p" - " setting tolerance %u", - hdw->vid_stream,idx); - } - pvr2_stream_setup(hdw->vid_stream,hdw->usb_dev, - PVR2_VID_ENDPOINT,idx); - } - - if (!pvr2_hdw_dev_ok(hdw)) return; - - hdw->flag_init_ok = !0; - - pvr2_hdw_state_sched(hdw); -} - - -/* Set up the structure and attempt to put the device into a usable state. - This can be a time-consuming operation, which is why it is not done - internally as part of the create() step. */ -static void pvr2_hdw_setup(struct pvr2_hdw *hdw) -{ - pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) begin",hdw); - do { - pvr2_hdw_setup_low(hdw); - pvr2_trace(PVR2_TRACE_INIT, - "pvr2_hdw_setup(hdw=%p) done, ok=%d init_ok=%d", - hdw,pvr2_hdw_dev_ok(hdw),hdw->flag_init_ok); - if (pvr2_hdw_dev_ok(hdw)) { - if (hdw->flag_init_ok) { - pvr2_trace( - PVR2_TRACE_INFO, - "Device initialization" - " completed successfully."); - break; - } - if (hdw->fw1_state == FW1_STATE_RELOAD) { - pvr2_trace( - PVR2_TRACE_INFO, - "Device microcontroller firmware" - " (re)loaded; it should now reset" - " and reconnect."); - break; - } - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "Device initialization was not successful."); - if (hdw->fw1_state == FW1_STATE_MISSING) { - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "Giving up since device" - " microcontroller firmware" - " appears to be missing."); - break; - } - } - if (hdw->flag_modulefail) { - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "***WARNING*** pvrusb2 driver initialization" - " failed due to the failure of one or more" - " sub-device kernel modules."); - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "You need to resolve the failing condition" - " before this driver can function. There" - " should be some earlier messages giving more" - " information about the problem."); - break; - } - if (procreload) { - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "Attempting pvrusb2 recovery by reloading" - " primary firmware."); - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "If this works, device should disconnect" - " and reconnect in a sane state."); - hdw->fw1_state = FW1_STATE_UNKNOWN; - pvr2_upload_firmware1(hdw); - } else { - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "***WARNING*** pvrusb2 device hardware" - " appears to be jammed" - " and I can't clear it."); - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "You might need to power cycle" - " the pvrusb2 device" - " in order to recover."); - } - } while (0); - pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) end",hdw); -} - - -/* Perform second stage initialization. Set callback pointer first so that - we can avoid a possible initialization race (if the kernel thread runs - before the callback has been set). */ -int pvr2_hdw_initialize(struct pvr2_hdw *hdw, - void (*callback_func)(void *), - void *callback_data) -{ - LOCK_TAKE(hdw->big_lock); do { - if (hdw->flag_disconnected) { - /* Handle a race here: If we're already - disconnected by this point, then give up. If we - get past this then we'll remain connected for - the duration of initialization since the entire - initialization sequence is now protected by the - big_lock. */ - break; - } - hdw->state_data = callback_data; - hdw->state_func = callback_func; - pvr2_hdw_setup(hdw); - } while (0); LOCK_GIVE(hdw->big_lock); - return hdw->flag_init_ok; -} - - -/* Create, set up, and return a structure for interacting with the - underlying hardware. */ -struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, - const struct usb_device_id *devid) -{ - unsigned int idx,cnt1,cnt2,m; - struct pvr2_hdw *hdw = NULL; - int valid_std_mask; - struct pvr2_ctrl *cptr; - struct usb_device *usb_dev; - const struct pvr2_device_desc *hdw_desc; - __u8 ifnum; - struct v4l2_queryctrl qctrl; - struct pvr2_ctl_info *ciptr; - - usb_dev = interface_to_usbdev(intf); - - hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info); - - if (hdw_desc == NULL) { - pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_create:" - " No device description pointer," - " unable to continue."); - pvr2_trace(PVR2_TRACE_INIT, "If you have a new device type," - " please contact Mike Isely <isely@pobox.com>" - " to get it included in the driver\n"); - goto fail; - } - - hdw = kzalloc(sizeof(*hdw),GFP_KERNEL); - pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"", - hdw,hdw_desc->description); - pvr2_trace(PVR2_TRACE_INFO, "Hardware description: %s", - hdw_desc->description); - if (hdw_desc->flag_is_experimental) { - pvr2_trace(PVR2_TRACE_INFO, "**********"); - pvr2_trace(PVR2_TRACE_INFO, - "WARNING: Support for this device (%s) is" - " experimental.", hdw_desc->description); - pvr2_trace(PVR2_TRACE_INFO, - "Important functionality might not be" - " entirely working."); - pvr2_trace(PVR2_TRACE_INFO, - "Please consider contacting the driver author to" - " help with further stabilization of the driver."); - pvr2_trace(PVR2_TRACE_INFO, "**********"); - } - if (!hdw) goto fail; - - init_timer(&hdw->quiescent_timer); - hdw->quiescent_timer.data = (unsigned long)hdw; - hdw->quiescent_timer.function = pvr2_hdw_quiescent_timeout; - - init_timer(&hdw->decoder_stabilization_timer); - hdw->decoder_stabilization_timer.data = (unsigned long)hdw; - hdw->decoder_stabilization_timer.function = - pvr2_hdw_decoder_stabilization_timeout; - - init_timer(&hdw->encoder_wait_timer); - hdw->encoder_wait_timer.data = (unsigned long)hdw; - hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout; - - init_timer(&hdw->encoder_run_timer); - hdw->encoder_run_timer.data = (unsigned long)hdw; - hdw->encoder_run_timer.function = pvr2_hdw_encoder_run_timeout; - - hdw->master_state = PVR2_STATE_DEAD; - - init_waitqueue_head(&hdw->state_wait_data); - - hdw->tuner_signal_stale = !0; - cx2341x_fill_defaults(&hdw->enc_ctl_state); - - /* Calculate which inputs are OK */ - m = 0; - if (hdw_desc->flag_has_analogtuner) m |= 1 << PVR2_CVAL_INPUT_TV; - if (hdw_desc->digital_control_scheme != PVR2_DIGITAL_SCHEME_NONE) { - m |= 1 << PVR2_CVAL_INPUT_DTV; - } - if (hdw_desc->flag_has_svideo) m |= 1 << PVR2_CVAL_INPUT_SVIDEO; - if (hdw_desc->flag_has_composite) m |= 1 << PVR2_CVAL_INPUT_COMPOSITE; - if (hdw_desc->flag_has_fmradio) m |= 1 << PVR2_CVAL_INPUT_RADIO; - hdw->input_avail_mask = m; - hdw->input_allowed_mask = hdw->input_avail_mask; - - /* If not a hybrid device, pathway_state never changes. So - initialize it here to what it should forever be. */ - if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_DTV))) { - hdw->pathway_state = PVR2_PATHWAY_ANALOG; - } else if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_TV))) { - hdw->pathway_state = PVR2_PATHWAY_DIGITAL; - } - - hdw->control_cnt = CTRLDEF_COUNT; - hdw->control_cnt += MPEGDEF_COUNT; - hdw->controls = kzalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt, - GFP_KERNEL); - if (!hdw->controls) goto fail; - hdw->hdw_desc = hdw_desc; - hdw->ir_scheme_active = hdw->hdw_desc->ir_scheme; - for (idx = 0; idx < hdw->control_cnt; idx++) { - cptr = hdw->controls + idx; - cptr->hdw = hdw; - } - for (idx = 0; idx < 32; idx++) { - hdw->std_mask_ptrs[idx] = hdw->std_mask_names[idx]; - } - for (idx = 0; idx < CTRLDEF_COUNT; idx++) { - cptr = hdw->controls + idx; - cptr->info = control_defs+idx; - } - - /* Ensure that default input choice is a valid one. */ - m = hdw->input_avail_mask; - if (m) for (idx = 0; idx < (sizeof(m) << 3); idx++) { - if (!((1 << idx) & m)) continue; - hdw->input_val = idx; - break; - } - - /* Define and configure additional controls from cx2341x module. */ - hdw->mpeg_ctrl_info = kcalloc(MPEGDEF_COUNT, - sizeof(*(hdw->mpeg_ctrl_info)), - GFP_KERNEL); - if (!hdw->mpeg_ctrl_info) goto fail; - for (idx = 0; idx < MPEGDEF_COUNT; idx++) { - cptr = hdw->controls + idx + CTRLDEF_COUNT; - ciptr = &(hdw->mpeg_ctrl_info[idx].info); - ciptr->desc = hdw->mpeg_ctrl_info[idx].desc; - ciptr->name = mpeg_ids[idx].strid; - ciptr->v4l_id = mpeg_ids[idx].id; - ciptr->skip_init = !0; - ciptr->get_value = ctrl_cx2341x_get; - ciptr->get_v4lflags = ctrl_cx2341x_getv4lflags; - ciptr->is_dirty = ctrl_cx2341x_is_dirty; - if (!idx) ciptr->clear_dirty = ctrl_cx2341x_clear_dirty; - qctrl.id = ciptr->v4l_id; - cx2341x_ctrl_query(&hdw->enc_ctl_state,&qctrl); - if (!(qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY)) { - ciptr->set_value = ctrl_cx2341x_set; - } - strncpy(hdw->mpeg_ctrl_info[idx].desc,qctrl.name, - PVR2_CTLD_INFO_DESC_SIZE); - hdw->mpeg_ctrl_info[idx].desc[PVR2_CTLD_INFO_DESC_SIZE-1] = 0; - ciptr->default_value = qctrl.default_value; - switch (qctrl.type) { - default: - case V4L2_CTRL_TYPE_INTEGER: - ciptr->type = pvr2_ctl_int; - ciptr->def.type_int.min_value = qctrl.minimum; - ciptr->def.type_int.max_value = qctrl.maximum; - break; - case V4L2_CTRL_TYPE_BOOLEAN: - ciptr->type = pvr2_ctl_bool; - break; - case V4L2_CTRL_TYPE_MENU: - ciptr->type = pvr2_ctl_enum; - ciptr->def.type_enum.value_names = - cx2341x_ctrl_get_menu(&hdw->enc_ctl_state, - ciptr->v4l_id); - for (cnt1 = 0; - ciptr->def.type_enum.value_names[cnt1] != NULL; - cnt1++) { } - ciptr->def.type_enum.count = cnt1; - break; - } - cptr->info = ciptr; - } - - // Initialize control data regarding video standard masks - valid_std_mask = pvr2_std_get_usable(); - for (idx = 0; idx < 32; idx++) { - if (!(valid_std_mask & (1 << idx))) continue; - cnt1 = pvr2_std_id_to_str( - hdw->std_mask_names[idx], - sizeof(hdw->std_mask_names[idx])-1, - 1 << idx); - hdw->std_mask_names[idx][cnt1] = 0; - } - cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDAVAIL); - if (cptr) { - memcpy(&hdw->std_info_avail,cptr->info, - sizeof(hdw->std_info_avail)); - cptr->info = &hdw->std_info_avail; - hdw->std_info_avail.def.type_bitmask.bit_names = - hdw->std_mask_ptrs; - hdw->std_info_avail.def.type_bitmask.valid_bits = - valid_std_mask; - } - cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR); - if (cptr) { - memcpy(&hdw->std_info_cur,cptr->info, - sizeof(hdw->std_info_cur)); - cptr->info = &hdw->std_info_cur; - hdw->std_info_cur.def.type_bitmask.bit_names = - hdw->std_mask_ptrs; - hdw->std_info_cur.def.type_bitmask.valid_bits = - valid_std_mask; - } - cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDDETECT); - if (cptr) { - memcpy(&hdw->std_info_detect,cptr->info, - sizeof(hdw->std_info_detect)); - cptr->info = &hdw->std_info_detect; - hdw->std_info_detect.def.type_bitmask.bit_names = - hdw->std_mask_ptrs; - hdw->std_info_detect.def.type_bitmask.valid_bits = - valid_std_mask; - } - - hdw->cropcap_stale = !0; - hdw->eeprom_addr = -1; - hdw->unit_number = -1; - hdw->v4l_minor_number_video = -1; - hdw->v4l_minor_number_vbi = -1; - hdw->v4l_minor_number_radio = -1; - hdw->ctl_write_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL); - if (!hdw->ctl_write_buffer) goto fail; - hdw->ctl_read_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL); - if (!hdw->ctl_read_buffer) goto fail; - hdw->ctl_write_urb = usb_alloc_urb(0,GFP_KERNEL); - if (!hdw->ctl_write_urb) goto fail; - hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL); - if (!hdw->ctl_read_urb) goto fail; - - if (v4l2_device_register(&intf->dev, &hdw->v4l2_dev) != 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Error registering with v4l core, giving up"); - goto fail; - } - 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); mutex_unlock(&pvr2_unit_mtx); - - cnt1 = 0; - cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2"); - cnt1 += cnt2; - if (hdw->unit_number >= 0) { - cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"_%c", - ('a' + hdw->unit_number)); - cnt1 += cnt2; - } - if (cnt1 >= sizeof(hdw->name)) cnt1 = sizeof(hdw->name)-1; - hdw->name[cnt1] = 0; - - hdw->workqueue = create_singlethread_workqueue(hdw->name); - INIT_WORK(&hdw->workpoll,pvr2_hdw_worker_poll); - - pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s", - hdw->unit_number,hdw->name); - - hdw->tuner_type = -1; - hdw->flag_ok = !0; - - hdw->usb_intf = intf; - hdw->usb_dev = usb_dev; - - usb_make_path(hdw->usb_dev, hdw->bus_info, sizeof(hdw->bus_info)); - - ifnum = hdw->usb_intf->cur_altsetting->desc.bInterfaceNumber; - usb_set_interface(hdw->usb_dev,ifnum,0); - - mutex_init(&hdw->ctl_lock_mutex); - mutex_init(&hdw->big_lock_mutex); - - return hdw; - fail: - if (hdw) { - del_timer_sync(&hdw->quiescent_timer); - del_timer_sync(&hdw->decoder_stabilization_timer); - del_timer_sync(&hdw->encoder_run_timer); - del_timer_sync(&hdw->encoder_wait_timer); - if (hdw->workqueue) { - flush_workqueue(hdw->workqueue); - destroy_workqueue(hdw->workqueue); - hdw->workqueue = NULL; - } - usb_free_urb(hdw->ctl_read_urb); - usb_free_urb(hdw->ctl_write_urb); - kfree(hdw->ctl_read_buffer); - kfree(hdw->ctl_write_buffer); - kfree(hdw->controls); - kfree(hdw->mpeg_ctrl_info); - kfree(hdw); - } - return NULL; -} - - -/* Remove _all_ associations between this driver and the underlying USB - layer. */ -static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw) -{ - if (hdw->flag_disconnected) return; - pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_remove_usb_stuff: hdw=%p",hdw); - if (hdw->ctl_read_urb) { - usb_kill_urb(hdw->ctl_read_urb); - usb_free_urb(hdw->ctl_read_urb); - hdw->ctl_read_urb = NULL; - } - if (hdw->ctl_write_urb) { - usb_kill_urb(hdw->ctl_write_urb); - usb_free_urb(hdw->ctl_write_urb); - hdw->ctl_write_urb = NULL; - } - if (hdw->ctl_read_buffer) { - kfree(hdw->ctl_read_buffer); - hdw->ctl_read_buffer = NULL; - } - if (hdw->ctl_write_buffer) { - kfree(hdw->ctl_write_buffer); - hdw->ctl_write_buffer = NULL; - } - hdw->flag_disconnected = !0; - /* If we don't do this, then there will be a dangling struct device - reference to our disappearing device persisting inside the V4L - core... */ - v4l2_device_disconnect(&hdw->v4l2_dev); - hdw->usb_dev = NULL; - hdw->usb_intf = NULL; - pvr2_hdw_render_useless(hdw); -} - - -/* Destroy hardware interaction structure */ -void pvr2_hdw_destroy(struct pvr2_hdw *hdw) -{ - if (!hdw) return; - pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw); - if (hdw->workqueue) { - flush_workqueue(hdw->workqueue); - destroy_workqueue(hdw->workqueue); - hdw->workqueue = NULL; - } - del_timer_sync(&hdw->quiescent_timer); - del_timer_sync(&hdw->decoder_stabilization_timer); - del_timer_sync(&hdw->encoder_run_timer); - del_timer_sync(&hdw->encoder_wait_timer); - if (hdw->fw_buffer) { - kfree(hdw->fw_buffer); - hdw->fw_buffer = NULL; - } - if (hdw->vid_stream) { - pvr2_stream_destroy(hdw->vid_stream); - hdw->vid_stream = NULL; - } - pvr2_i2c_core_done(hdw); - v4l2_device_unregister(&hdw->v4l2_dev); - pvr2_hdw_remove_usb_stuff(hdw); - 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); mutex_unlock(&pvr2_unit_mtx); - kfree(hdw->controls); - kfree(hdw->mpeg_ctrl_info); - kfree(hdw); -} - - -int pvr2_hdw_dev_ok(struct pvr2_hdw *hdw) -{ - return (hdw && hdw->flag_ok); -} - - -/* Called when hardware has been unplugged */ -void pvr2_hdw_disconnect(struct pvr2_hdw *hdw) -{ - pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_disconnect(hdw=%p)",hdw); - LOCK_TAKE(hdw->big_lock); - LOCK_TAKE(hdw->ctl_lock); - pvr2_hdw_remove_usb_stuff(hdw); - LOCK_GIVE(hdw->ctl_lock); - LOCK_GIVE(hdw->big_lock); -} - - -/* Get the number of defined controls */ -unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw) -{ - return hdw->control_cnt; -} - - -/* Retrieve a control handle given its index (0..count-1) */ -struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *hdw, - unsigned int idx) -{ - if (idx >= hdw->control_cnt) return NULL; - return hdw->controls + idx; -} - - -/* Retrieve a control handle given its index (0..count-1) */ -struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *hdw, - unsigned int ctl_id) -{ - struct pvr2_ctrl *cptr; - unsigned int idx; - int i; - - /* This could be made a lot more efficient, but for now... */ - for (idx = 0; idx < hdw->control_cnt; idx++) { - cptr = hdw->controls + idx; - i = cptr->info->internal_id; - if (i && (i == ctl_id)) return cptr; - } - return NULL; -} - - -/* Given a V4L ID, retrieve the control structure associated with it. */ -struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *hdw,unsigned int ctl_id) -{ - struct pvr2_ctrl *cptr; - unsigned int idx; - int i; - - /* This could be made a lot more efficient, but for now... */ - for (idx = 0; idx < hdw->control_cnt; idx++) { - cptr = hdw->controls + idx; - i = cptr->info->v4l_id; - if (i && (i == ctl_id)) return cptr; - } - return NULL; -} - - -/* Given a V4L ID for its immediate predecessor, retrieve the control - structure associated with it. */ -struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *hdw, - unsigned int ctl_id) -{ - struct pvr2_ctrl *cptr,*cp2; - unsigned int idx; - int i; - - /* This could be made a lot more efficient, but for now... */ - cp2 = NULL; - for (idx = 0; idx < hdw->control_cnt; idx++) { - cptr = hdw->controls + idx; - i = cptr->info->v4l_id; - if (!i) continue; - if (i <= ctl_id) continue; - if (cp2 && (cp2->info->v4l_id < i)) continue; - cp2 = cptr; - } - return cp2; - return NULL; -} - - -static const char *get_ctrl_typename(enum pvr2_ctl_type tp) -{ - switch (tp) { - case pvr2_ctl_int: return "integer"; - case pvr2_ctl_enum: return "enum"; - case pvr2_ctl_bool: return "boolean"; - case pvr2_ctl_bitmask: return "bitmask"; - } - return ""; -} - - -static void pvr2_subdev_set_control(struct pvr2_hdw *hdw, int id, - const char *name, int val) -{ - struct v4l2_control ctrl; - pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 %s=%d", name, val); - memset(&ctrl, 0, sizeof(ctrl)); - ctrl.id = id; - ctrl.value = val; - v4l2_device_call_all(&hdw->v4l2_dev, 0, core, s_ctrl, &ctrl); -} - -#define PVR2_SUBDEV_SET_CONTROL(hdw, id, lab) \ - if ((hdw)->lab##_dirty || (hdw)->force_dirty) { \ - pvr2_subdev_set_control(hdw, id, #lab, (hdw)->lab##_val); \ - } - -v4l2_std_id pvr2_hdw_get_detected_std(struct pvr2_hdw *hdw) -{ - v4l2_std_id std; - std = (v4l2_std_id)hdw->std_mask_avail; - v4l2_device_call_all(&hdw->v4l2_dev, 0, - video, querystd, &std); - return std; -} - -/* Execute whatever commands are required to update the state of all the - sub-devices so that they match our current control values. */ -static void pvr2_subdev_update(struct pvr2_hdw *hdw) -{ - struct v4l2_subdev *sd; - unsigned int id; - pvr2_subdev_update_func fp; - - pvr2_trace(PVR2_TRACE_CHIPS, "subdev update..."); - - if (hdw->tuner_updated || hdw->force_dirty) { - struct tuner_setup setup; - pvr2_trace(PVR2_TRACE_CHIPS, "subdev tuner set_type(%d)", - hdw->tuner_type); - if (((int)(hdw->tuner_type)) >= 0) { - memset(&setup, 0, sizeof(setup)); - setup.addr = ADDR_UNSET; - setup.type = hdw->tuner_type; - setup.mode_mask = T_RADIO | T_ANALOG_TV; - v4l2_device_call_all(&hdw->v4l2_dev, 0, - tuner, s_type_addr, &setup); - } - } - - if (hdw->input_dirty || hdw->std_dirty || hdw->force_dirty) { - pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_standard"); - if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { - v4l2_device_call_all(&hdw->v4l2_dev, 0, - tuner, s_radio); - } else { - v4l2_std_id vs; - vs = hdw->std_mask_cur; - v4l2_device_call_all(&hdw->v4l2_dev, 0, - core, s_std, vs); - pvr2_hdw_cx25840_vbi_hack(hdw); - } - hdw->tuner_signal_stale = !0; - hdw->cropcap_stale = !0; - } - - PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_BRIGHTNESS, brightness); - PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_CONTRAST, contrast); - PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_SATURATION, saturation); - PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_HUE, hue); - PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_MUTE, mute); - PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_VOLUME, volume); - PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BALANCE, balance); - PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BASS, bass); - PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_TREBLE, treble); - - if (hdw->input_dirty || hdw->audiomode_dirty || hdw->force_dirty) { - struct v4l2_tuner vt; - memset(&vt, 0, sizeof(vt)); - vt.type = (hdw->input_val == PVR2_CVAL_INPUT_RADIO) ? - V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - vt.audmode = hdw->audiomode_val; - v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, s_tuner, &vt); - } - - if (hdw->freqDirty || hdw->force_dirty) { - unsigned long fv; - struct v4l2_frequency freq; - fv = pvr2_hdw_get_cur_freq(hdw); - pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_freq(%lu)", fv); - if (hdw->tuner_signal_stale) pvr2_hdw_status_poll(hdw); - memset(&freq, 0, sizeof(freq)); - if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) { - /* ((fv * 1000) / 62500) */ - freq.frequency = (fv * 2) / 125; - } else { - freq.frequency = fv / 62500; - } - /* tuner-core currently doesn't seem to care about this, but - let's set it anyway for completeness. */ - if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { - freq.type = V4L2_TUNER_RADIO; - } else { - freq.type = V4L2_TUNER_ANALOG_TV; - } - freq.tuner = 0; - v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, - s_frequency, &freq); - } - - if (hdw->res_hor_dirty || hdw->res_ver_dirty || hdw->force_dirty) { - struct v4l2_mbus_framefmt fmt; - memset(&fmt, 0, sizeof(fmt)); - fmt.width = hdw->res_hor_val; - fmt.height = hdw->res_ver_val; - fmt.code = V4L2_MBUS_FMT_FIXED; - pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_size(%dx%d)", - fmt.width, fmt.height); - v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_mbus_fmt, &fmt); - } - - if (hdw->srate_dirty || hdw->force_dirty) { - u32 val; - pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_audio %d", - hdw->srate_val); - switch (hdw->srate_val) { - default: - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: - val = 48000; - break; - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: - val = 44100; - break; - case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: - val = 32000; - break; - } - v4l2_device_call_all(&hdw->v4l2_dev, 0, - audio, s_clock_freq, val); - } - - /* Unable to set crop parameters; there is apparently no equivalent - for VIDIOC_S_CROP */ - - v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { - id = sd->grp_id; - if (id >= ARRAY_SIZE(pvr2_module_update_functions)) continue; - fp = pvr2_module_update_functions[id]; - if (!fp) continue; - (*fp)(hdw, sd); - } - - if (hdw->tuner_signal_stale || hdw->cropcap_stale) { - pvr2_hdw_status_poll(hdw); - } -} - - -/* Figure out if we need to commit control changes. If so, mark internal - state flags to indicate this fact and return true. Otherwise do nothing - else and return false. */ -static int pvr2_hdw_commit_setup(struct pvr2_hdw *hdw) -{ - unsigned int idx; - struct pvr2_ctrl *cptr; - int value; - int commit_flag = hdw->force_dirty; - char buf[100]; - unsigned int bcnt,ccnt; - - for (idx = 0; idx < hdw->control_cnt; idx++) { - cptr = hdw->controls + idx; - if (!cptr->info->is_dirty) continue; - if (!cptr->info->is_dirty(cptr)) continue; - commit_flag = !0; - - if (!(pvrusb2_debug & PVR2_TRACE_CTL)) continue; - bcnt = scnprintf(buf,sizeof(buf),"\"%s\" <-- ", - cptr->info->name); - value = 0; - cptr->info->get_value(cptr,&value); - pvr2_ctrl_value_to_sym_internal(cptr,~0,value, - buf+bcnt, - sizeof(buf)-bcnt,&ccnt); - bcnt += ccnt; - bcnt += scnprintf(buf+bcnt,sizeof(buf)-bcnt," <%s>", - get_ctrl_typename(cptr->info->type)); - pvr2_trace(PVR2_TRACE_CTL, - "/*--TRACE_COMMIT--*/ %.*s", - bcnt,buf); - } - - if (!commit_flag) { - /* Nothing has changed */ - return 0; - } - - hdw->state_pipeline_config = 0; - trace_stbit("state_pipeline_config",hdw->state_pipeline_config); - pvr2_hdw_state_sched(hdw); - - return !0; -} - - -/* Perform all operations needed to commit all control changes. This must - be performed in synchronization with the pipeline state and is thus - expected to be called as part of the driver's worker thread. Return - true if commit successful, otherwise return false to indicate that - commit isn't possible at this time. */ -static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) -{ - unsigned int idx; - struct pvr2_ctrl *cptr; - int disruptive_change; - - if (hdw->input_dirty && hdw->state_pathway_ok && - (((hdw->input_val == PVR2_CVAL_INPUT_DTV) ? - PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG) != - hdw->pathway_state)) { - /* Change of mode being asked for... */ - hdw->state_pathway_ok = 0; - trace_stbit("state_pathway_ok", hdw->state_pathway_ok); - } - if (!hdw->state_pathway_ok) { - /* Can't commit anything until pathway is ok. */ - return 0; - } - - /* Handle some required side effects when the video standard is - changed.... */ - if (hdw->std_dirty) { - int nvres; - int gop_size; - if (hdw->std_mask_cur & V4L2_STD_525_60) { - nvres = 480; - gop_size = 15; - } else { - nvres = 576; - gop_size = 12; - } - /* Rewrite the vertical resolution to be appropriate to the - video standard that has been selected. */ - if (nvres != hdw->res_ver_val) { - hdw->res_ver_val = nvres; - hdw->res_ver_dirty = !0; - } - /* Rewrite the GOP size to be appropriate to the video - standard that has been selected. */ - if (gop_size != hdw->enc_ctl_state.video_gop_size) { - struct v4l2_ext_controls cs; - struct v4l2_ext_control c1; - memset(&cs, 0, sizeof(cs)); - memset(&c1, 0, sizeof(c1)); - cs.controls = &c1; - cs.count = 1; - c1.id = V4L2_CID_MPEG_VIDEO_GOP_SIZE; - c1.value = gop_size; - cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs, - VIDIOC_S_EXT_CTRLS); - } - } - - /* The broadcast decoder can only scale down, so if - * res_*_dirty && crop window < output format ==> enlarge crop. - * - * The mpeg encoder receives fields of res_hor_val dots and - * res_ver_val halflines. Limits: hor<=720, ver<=576. - */ - if (hdw->res_hor_dirty && hdw->cropw_val < hdw->res_hor_val) { - hdw->cropw_val = hdw->res_hor_val; - hdw->cropw_dirty = !0; - } else if (hdw->cropw_dirty) { - hdw->res_hor_dirty = !0; /* must rescale */ - hdw->res_hor_val = min(720, hdw->cropw_val); - } - if (hdw->res_ver_dirty && hdw->croph_val < hdw->res_ver_val) { - hdw->croph_val = hdw->res_ver_val; - hdw->croph_dirty = !0; - } else if (hdw->croph_dirty) { - int nvres = hdw->std_mask_cur & V4L2_STD_525_60 ? 480 : 576; - hdw->res_ver_dirty = !0; - hdw->res_ver_val = min(nvres, hdw->croph_val); - } - - /* If any of the below has changed, then we can't do the update - while the pipeline is running. Pipeline must be paused first - and decoder -> encoder connection be made quiescent before we - can proceed. */ - disruptive_change = - (hdw->std_dirty || - hdw->enc_unsafe_stale || - hdw->srate_dirty || - hdw->res_ver_dirty || - hdw->res_hor_dirty || - hdw->cropw_dirty || - hdw->croph_dirty || - hdw->input_dirty || - (hdw->active_stream_type != hdw->desired_stream_type)); - if (disruptive_change && !hdw->state_pipeline_idle) { - /* Pipeline is not idle; we can't proceed. Arrange to - cause pipeline to stop so that we can try this again - later.... */ - hdw->state_pipeline_pause = !0; - return 0; - } - - if (hdw->srate_dirty) { - /* Write new sample rate into control structure since - * the master copy is stale. We must track srate - * separate from the mpeg control structure because - * other logic also uses this value. */ - struct v4l2_ext_controls cs; - struct v4l2_ext_control c1; - memset(&cs,0,sizeof(cs)); - memset(&c1,0,sizeof(c1)); - cs.controls = &c1; - cs.count = 1; - c1.id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ; - c1.value = hdw->srate_val; - cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs,VIDIOC_S_EXT_CTRLS); - } - - if (hdw->active_stream_type != hdw->desired_stream_type) { - /* Handle any side effects of stream config here */ - hdw->active_stream_type = hdw->desired_stream_type; - } - - if (hdw->hdw_desc->signal_routing_scheme == - PVR2_ROUTING_SCHEME_GOTVIEW) { - u32 b; - /* Handle GOTVIEW audio switching */ - pvr2_hdw_gpio_get_out(hdw,&b); - if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { - /* Set GPIO 11 */ - pvr2_hdw_gpio_chg_out(hdw,(1 << 11),~0); - } else { - /* Clear GPIO 11 */ - pvr2_hdw_gpio_chg_out(hdw,(1 << 11),0); - } - } - - /* Check and update state for all sub-devices. */ - pvr2_subdev_update(hdw); - - hdw->tuner_updated = 0; - hdw->force_dirty = 0; - for (idx = 0; idx < hdw->control_cnt; idx++) { - cptr = hdw->controls + idx; - if (!cptr->info->clear_dirty) continue; - cptr->info->clear_dirty(cptr); - } - - if ((hdw->pathway_state == PVR2_PATHWAY_ANALOG) && - hdw->state_encoder_run) { - /* If encoder isn't running or it can't be touched, then - this will get worked out later when we start the - encoder. */ - if (pvr2_encoder_adjust(hdw) < 0) return !0; - } - - hdw->state_pipeline_config = !0; - /* Hardware state may have changed in a way to cause the cropping - capabilities to have changed. So mark it stale, which will - cause a later re-fetch. */ - trace_stbit("state_pipeline_config",hdw->state_pipeline_config); - return !0; -} - - -int pvr2_hdw_commit_ctl(struct pvr2_hdw *hdw) -{ - int fl; - LOCK_TAKE(hdw->big_lock); - fl = pvr2_hdw_commit_setup(hdw); - LOCK_GIVE(hdw->big_lock); - if (!fl) return 0; - return pvr2_hdw_wait(hdw,0); -} - - -static void pvr2_hdw_worker_poll(struct work_struct *work) -{ - int fl = 0; - struct pvr2_hdw *hdw = container_of(work,struct pvr2_hdw,workpoll); - LOCK_TAKE(hdw->big_lock); do { - fl = pvr2_hdw_state_eval(hdw); - } while (0); LOCK_GIVE(hdw->big_lock); - if (fl && hdw->state_func) { - hdw->state_func(hdw->state_data); - } -} - - -static int pvr2_hdw_wait(struct pvr2_hdw *hdw,int state) -{ - return wait_event_interruptible( - hdw->state_wait_data, - (hdw->state_stale == 0) && - (!state || (hdw->master_state != state))); -} - - -/* Return name for this driver instance */ -const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw) -{ - return hdw->name; -} - - -const char *pvr2_hdw_get_desc(struct pvr2_hdw *hdw) -{ - return hdw->hdw_desc->description; -} - - -const char *pvr2_hdw_get_type(struct pvr2_hdw *hdw) -{ - return hdw->hdw_desc->shortname; -} - - -int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) -{ - int result; - LOCK_TAKE(hdw->ctl_lock); do { - hdw->cmd_buffer[0] = FX2CMD_GET_USB_SPEED; - result = pvr2_send_request(hdw, - hdw->cmd_buffer,1, - hdw->cmd_buffer,1); - if (result < 0) break; - result = (hdw->cmd_buffer[0] != 0); - } while(0); LOCK_GIVE(hdw->ctl_lock); - return result; -} - - -/* Execute poll of tuner status */ -void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw) -{ - LOCK_TAKE(hdw->big_lock); do { - pvr2_hdw_status_poll(hdw); - } while (0); LOCK_GIVE(hdw->big_lock); -} - - -static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw) -{ - if (!hdw->cropcap_stale) { - return 0; - } - pvr2_hdw_status_poll(hdw); - if (hdw->cropcap_stale) { - return -EIO; - } - return 0; -} - - -/* Return information about cropping capabilities */ -int pvr2_hdw_get_cropcap(struct pvr2_hdw *hdw, struct v4l2_cropcap *pp) -{ - int stat = 0; - LOCK_TAKE(hdw->big_lock); - stat = pvr2_hdw_check_cropcap(hdw); - if (!stat) { - memcpy(pp, &hdw->cropcap_info, sizeof(hdw->cropcap_info)); - } - LOCK_GIVE(hdw->big_lock); - return stat; -} - - -/* Return information about the tuner */ -int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp) -{ - LOCK_TAKE(hdw->big_lock); do { - if (hdw->tuner_signal_stale) { - pvr2_hdw_status_poll(hdw); - } - memcpy(vtp,&hdw->tuner_signal_info,sizeof(struct v4l2_tuner)); - } while (0); LOCK_GIVE(hdw->big_lock); - return 0; -} - - -/* Get handle to video output stream */ -struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *hp) -{ - return hp->vid_stream; -} - - -void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw) -{ - int nr = pvr2_hdw_get_unit_number(hdw); - LOCK_TAKE(hdw->big_lock); do { - printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr); - v4l2_device_call_all(&hdw->v4l2_dev, 0, core, log_status); - pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:"); - cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2"); - pvr2_hdw_state_log_state(hdw); - printk(KERN_INFO "pvrusb2: ================== END STATUS CARD #%d ==================\n", nr); - } while (0); LOCK_GIVE(hdw->big_lock); -} - - -/* Grab EEPROM contents, needed for direct method. */ -#define EEPROM_SIZE 8192 -#define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__) -static u8 *pvr2_full_eeprom_fetch(struct pvr2_hdw *hdw) -{ - struct i2c_msg msg[2]; - u8 *eeprom; - u8 iadd[2]; - u8 addr; - u16 eepromSize; - unsigned int offs; - int ret; - int mode16 = 0; - unsigned pcnt,tcnt; - eeprom = kmalloc(EEPROM_SIZE,GFP_KERNEL); - if (!eeprom) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Failed to allocate memory" - " required to read eeprom"); - return NULL; - } - - trace_eeprom("Value for eeprom addr from controller was 0x%x", - hdw->eeprom_addr); - addr = hdw->eeprom_addr; - /* Seems that if the high bit is set, then the *real* eeprom - address is shifted right now bit position (noticed this in - newer PVR USB2 hardware) */ - if (addr & 0x80) addr >>= 1; - - /* FX2 documentation states that a 16bit-addressed eeprom is - expected if the I2C address is an odd number (yeah, this is - strange but it's what they do) */ - mode16 = (addr & 1); - eepromSize = (mode16 ? EEPROM_SIZE : 256); - trace_eeprom("Examining %d byte eeprom at location 0x%x" - " using %d bit addressing",eepromSize,addr, - mode16 ? 16 : 8); - - msg[0].addr = addr; - msg[0].flags = 0; - msg[0].len = mode16 ? 2 : 1; - msg[0].buf = iadd; - msg[1].addr = addr; - msg[1].flags = I2C_M_RD; - - /* We have to do the actual eeprom data fetch ourselves, because - (1) we're only fetching part of the eeprom, and (2) if we were - getting the whole thing our I2C driver can't grab it in one - pass - which is what tveeprom is otherwise going to attempt */ - memset(eeprom,0,EEPROM_SIZE); - for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) { - pcnt = 16; - if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt; - offs = tcnt + (eepromSize - EEPROM_SIZE); - if (mode16) { - iadd[0] = offs >> 8; - iadd[1] = offs; - } else { - iadd[0] = offs; - } - msg[1].len = pcnt; - msg[1].buf = eeprom+tcnt; - if ((ret = i2c_transfer(&hdw->i2c_adap, - msg,ARRAY_SIZE(msg))) != 2) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "eeprom fetch set offs err=%d",ret); - kfree(eeprom); - return NULL; - } - } - return eeprom; -} - - -void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, - int mode, - int enable_flag) -{ - int ret; - u16 address; - unsigned int pipe; - LOCK_TAKE(hdw->big_lock); do { - if ((hdw->fw_buffer == NULL) == !enable_flag) break; - - if (!enable_flag) { - pvr2_trace(PVR2_TRACE_FIRMWARE, - "Cleaning up after CPU firmware fetch"); - kfree(hdw->fw_buffer); - hdw->fw_buffer = NULL; - hdw->fw_size = 0; - if (hdw->fw_cpu_flag) { - /* Now release the CPU. It will disconnect - and reconnect later. */ - pvr2_hdw_cpureset_assert(hdw,0); - } - break; - } - - hdw->fw_cpu_flag = (mode != 2); - if (hdw->fw_cpu_flag) { - hdw->fw_size = (mode == 1) ? 0x4000 : 0x2000; - pvr2_trace(PVR2_TRACE_FIRMWARE, - "Preparing to suck out CPU firmware" - " (size=%u)", hdw->fw_size); - hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL); - if (!hdw->fw_buffer) { - hdw->fw_size = 0; - break; - } - - /* We have to hold the CPU during firmware upload. */ - pvr2_hdw_cpureset_assert(hdw,1); - - /* download the firmware from address 0000-1fff in 2048 - (=0x800) bytes chunk. */ - - pvr2_trace(PVR2_TRACE_FIRMWARE, - "Grabbing CPU firmware"); - pipe = usb_rcvctrlpipe(hdw->usb_dev, 0); - for(address = 0; address < hdw->fw_size; - address += 0x800) { - ret = usb_control_msg(hdw->usb_dev,pipe, - 0xa0,0xc0, - address,0, - hdw->fw_buffer+address, - 0x800,HZ); - if (ret < 0) break; - } - - pvr2_trace(PVR2_TRACE_FIRMWARE, - "Done grabbing CPU firmware"); - } else { - pvr2_trace(PVR2_TRACE_FIRMWARE, - "Sucking down EEPROM contents"); - hdw->fw_buffer = pvr2_full_eeprom_fetch(hdw); - if (!hdw->fw_buffer) { - pvr2_trace(PVR2_TRACE_FIRMWARE, - "EEPROM content suck failed."); - break; - } - hdw->fw_size = EEPROM_SIZE; - pvr2_trace(PVR2_TRACE_FIRMWARE, - "Done sucking down EEPROM contents"); - } - - } while (0); LOCK_GIVE(hdw->big_lock); -} - - -/* Return true if we're in a mode for retrieval CPU firmware */ -int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *hdw) -{ - return hdw->fw_buffer != NULL; -} - - -int pvr2_hdw_cpufw_get(struct pvr2_hdw *hdw,unsigned int offs, - char *buf,unsigned int cnt) -{ - int ret = -EINVAL; - LOCK_TAKE(hdw->big_lock); do { - if (!buf) break; - if (!cnt) break; - - if (!hdw->fw_buffer) { - ret = -EIO; - break; - } - - if (offs >= hdw->fw_size) { - pvr2_trace(PVR2_TRACE_FIRMWARE, - "Read firmware data offs=%d EOF", - offs); - ret = 0; - break; - } - - if (offs + cnt > hdw->fw_size) cnt = hdw->fw_size - offs; - - memcpy(buf,hdw->fw_buffer+offs,cnt); - - pvr2_trace(PVR2_TRACE_FIRMWARE, - "Read firmware data offs=%d cnt=%d", - offs,cnt); - ret = cnt; - } while (0); LOCK_GIVE(hdw->big_lock); - - return ret; -} - - -int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *hdw, - enum pvr2_v4l_type index) -{ - switch (index) { - case pvr2_v4l_type_video: return hdw->v4l_minor_number_video; - case pvr2_v4l_type_vbi: return hdw->v4l_minor_number_vbi; - case pvr2_v4l_type_radio: return hdw->v4l_minor_number_radio; - default: return -1; - } -} - - -/* Store a v4l minor device number */ -void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw, - enum pvr2_v4l_type index,int v) -{ - switch (index) { - case pvr2_v4l_type_video: hdw->v4l_minor_number_video = v; - case pvr2_v4l_type_vbi: hdw->v4l_minor_number_vbi = v; - case pvr2_v4l_type_radio: hdw->v4l_minor_number_radio = v; - default: break; - } -} - - -static void pvr2_ctl_write_complete(struct urb *urb) -{ - struct pvr2_hdw *hdw = urb->context; - hdw->ctl_write_pend_flag = 0; - if (hdw->ctl_read_pend_flag) return; - complete(&hdw->ctl_done); -} - - -static void pvr2_ctl_read_complete(struct urb *urb) -{ - struct pvr2_hdw *hdw = urb->context; - hdw->ctl_read_pend_flag = 0; - if (hdw->ctl_write_pend_flag) return; - complete(&hdw->ctl_done); -} - - -static void pvr2_ctl_timeout(unsigned long data) -{ - struct pvr2_hdw *hdw = (struct pvr2_hdw *)data; - if (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) { - hdw->ctl_timeout_flag = !0; - if (hdw->ctl_write_pend_flag) - usb_unlink_urb(hdw->ctl_write_urb); - if (hdw->ctl_read_pend_flag) - usb_unlink_urb(hdw->ctl_read_urb); - } -} - - -/* Issue a command and get a response from the device. This extended - version includes a probe flag (which if set means that device errors - should not be logged or treated as fatal) and a timeout in jiffies. - This can be used to non-lethally probe the health of endpoint 1. */ -static int pvr2_send_request_ex(struct pvr2_hdw *hdw, - unsigned int timeout,int probe_fl, - void *write_data,unsigned int write_len, - void *read_data,unsigned int read_len) -{ - unsigned int idx; - int status = 0; - struct timer_list timer; - if (!hdw->ctl_lock_held) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Attempted to execute control transfer" - " without lock!!"); - return -EDEADLK; - } - if (!hdw->flag_ok && !probe_fl) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Attempted to execute control transfer" - " when device not ok"); - return -EIO; - } - if (!(hdw->ctl_read_urb && hdw->ctl_write_urb)) { - if (!probe_fl) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Attempted to execute control transfer" - " when USB is disconnected"); - } - return -ENOTTY; - } - - /* Ensure that we have sane parameters */ - if (!write_data) write_len = 0; - if (!read_data) read_len = 0; - if (write_len > PVR2_CTL_BUFFSIZE) { - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "Attempted to execute %d byte" - " control-write transfer (limit=%d)", - write_len,PVR2_CTL_BUFFSIZE); - return -EINVAL; - } - if (read_len > PVR2_CTL_BUFFSIZE) { - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "Attempted to execute %d byte" - " control-read transfer (limit=%d)", - write_len,PVR2_CTL_BUFFSIZE); - return -EINVAL; - } - if ((!write_len) && (!read_len)) { - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "Attempted to execute null control transfer?"); - return -EINVAL; - } - - - hdw->cmd_debug_state = 1; - if (write_len) { - hdw->cmd_debug_code = ((unsigned char *)write_data)[0]; - } else { - hdw->cmd_debug_code = 0; - } - hdw->cmd_debug_write_len = write_len; - hdw->cmd_debug_read_len = read_len; - - /* Initialize common stuff */ - init_completion(&hdw->ctl_done); - hdw->ctl_timeout_flag = 0; - hdw->ctl_write_pend_flag = 0; - hdw->ctl_read_pend_flag = 0; - init_timer(&timer); - timer.expires = jiffies + timeout; - timer.data = (unsigned long)hdw; - timer.function = pvr2_ctl_timeout; - - if (write_len) { - hdw->cmd_debug_state = 2; - /* Transfer write data to internal buffer */ - for (idx = 0; idx < write_len; idx++) { - hdw->ctl_write_buffer[idx] = - ((unsigned char *)write_data)[idx]; - } - /* Initiate a write request */ - usb_fill_bulk_urb(hdw->ctl_write_urb, - hdw->usb_dev, - usb_sndbulkpipe(hdw->usb_dev, - PVR2_CTL_WRITE_ENDPOINT), - hdw->ctl_write_buffer, - write_len, - pvr2_ctl_write_complete, - hdw); - hdw->ctl_write_urb->actual_length = 0; - hdw->ctl_write_pend_flag = !0; - status = usb_submit_urb(hdw->ctl_write_urb,GFP_KERNEL); - if (status < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Failed to submit write-control" - " URB status=%d",status); - hdw->ctl_write_pend_flag = 0; - goto done; - } - } - - if (read_len) { - hdw->cmd_debug_state = 3; - memset(hdw->ctl_read_buffer,0x43,read_len); - /* Initiate a read request */ - usb_fill_bulk_urb(hdw->ctl_read_urb, - hdw->usb_dev, - usb_rcvbulkpipe(hdw->usb_dev, - PVR2_CTL_READ_ENDPOINT), - hdw->ctl_read_buffer, - read_len, - pvr2_ctl_read_complete, - hdw); - hdw->ctl_read_urb->actual_length = 0; - hdw->ctl_read_pend_flag = !0; - status = usb_submit_urb(hdw->ctl_read_urb,GFP_KERNEL); - if (status < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Failed to submit read-control" - " URB status=%d",status); - hdw->ctl_read_pend_flag = 0; - goto done; - } - } - - /* Start timer */ - add_timer(&timer); - - /* Now wait for all I/O to complete */ - hdw->cmd_debug_state = 4; - while (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) { - wait_for_completion(&hdw->ctl_done); - } - hdw->cmd_debug_state = 5; - - /* Stop timer */ - del_timer_sync(&timer); - - hdw->cmd_debug_state = 6; - status = 0; - - if (hdw->ctl_timeout_flag) { - status = -ETIMEDOUT; - if (!probe_fl) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Timed out control-write"); - } - goto done; - } - - if (write_len) { - /* Validate results of write request */ - if ((hdw->ctl_write_urb->status != 0) && - (hdw->ctl_write_urb->status != -ENOENT) && - (hdw->ctl_write_urb->status != -ESHUTDOWN) && - (hdw->ctl_write_urb->status != -ECONNRESET)) { - /* USB subsystem is reporting some kind of failure - on the write */ - status = hdw->ctl_write_urb->status; - if (!probe_fl) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "control-write URB failure," - " status=%d", - status); - } - goto done; - } - if (hdw->ctl_write_urb->actual_length < write_len) { - /* Failed to write enough data */ - status = -EIO; - if (!probe_fl) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "control-write URB short," - " expected=%d got=%d", - write_len, - hdw->ctl_write_urb->actual_length); - } - goto done; - } - } - if (read_len) { - /* Validate results of read request */ - if ((hdw->ctl_read_urb->status != 0) && - (hdw->ctl_read_urb->status != -ENOENT) && - (hdw->ctl_read_urb->status != -ESHUTDOWN) && - (hdw->ctl_read_urb->status != -ECONNRESET)) { - /* USB subsystem is reporting some kind of failure - on the read */ - status = hdw->ctl_read_urb->status; - if (!probe_fl) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "control-read URB failure," - " status=%d", - status); - } - goto done; - } - if (hdw->ctl_read_urb->actual_length < read_len) { - /* Failed to read enough data */ - status = -EIO; - if (!probe_fl) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "control-read URB short," - " expected=%d got=%d", - read_len, - hdw->ctl_read_urb->actual_length); - } - goto done; - } - /* Transfer retrieved data out from internal buffer */ - for (idx = 0; idx < read_len; idx++) { - ((unsigned char *)read_data)[idx] = - hdw->ctl_read_buffer[idx]; - } - } - - done: - - hdw->cmd_debug_state = 0; - if ((status < 0) && (!probe_fl)) { - pvr2_hdw_render_useless(hdw); - } - return status; -} - - -int pvr2_send_request(struct pvr2_hdw *hdw, - void *write_data,unsigned int write_len, - void *read_data,unsigned int read_len) -{ - return pvr2_send_request_ex(hdw,HZ*4,0, - write_data,write_len, - read_data,read_len); -} - - -static int pvr2_issue_simple_cmd(struct pvr2_hdw *hdw,u32 cmdcode) -{ - int ret; - unsigned int cnt = 1; - unsigned int args = 0; - LOCK_TAKE(hdw->ctl_lock); - hdw->cmd_buffer[0] = cmdcode & 0xffu; - args = (cmdcode >> 8) & 0xffu; - args = (args > 2) ? 2 : args; - if (args) { - cnt += args; - hdw->cmd_buffer[1] = (cmdcode >> 16) & 0xffu; - if (args > 1) { - hdw->cmd_buffer[2] = (cmdcode >> 24) & 0xffu; - } - } - if (pvrusb2_debug & PVR2_TRACE_INIT) { - unsigned int idx; - unsigned int ccnt,bcnt; - char tbuf[50]; - cmdcode &= 0xffu; - bcnt = 0; - ccnt = scnprintf(tbuf+bcnt, - sizeof(tbuf)-bcnt, - "Sending FX2 command 0x%x",cmdcode); - bcnt += ccnt; - for (idx = 0; idx < ARRAY_SIZE(pvr2_fx2cmd_desc); idx++) { - if (pvr2_fx2cmd_desc[idx].id == cmdcode) { - ccnt = scnprintf(tbuf+bcnt, - sizeof(tbuf)-bcnt, - " \"%s\"", - pvr2_fx2cmd_desc[idx].desc); - bcnt += ccnt; - break; - } - } - if (args) { - ccnt = scnprintf(tbuf+bcnt, - sizeof(tbuf)-bcnt, - " (%u",hdw->cmd_buffer[1]); - bcnt += ccnt; - if (args > 1) { - ccnt = scnprintf(tbuf+bcnt, - sizeof(tbuf)-bcnt, - ",%u",hdw->cmd_buffer[2]); - bcnt += ccnt; - } - ccnt = scnprintf(tbuf+bcnt, - sizeof(tbuf)-bcnt, - ")"); - bcnt += ccnt; - } - pvr2_trace(PVR2_TRACE_INIT,"%.*s",bcnt,tbuf); - } - ret = pvr2_send_request(hdw,hdw->cmd_buffer,cnt,NULL,0); - LOCK_GIVE(hdw->ctl_lock); - return ret; -} - - -int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data) -{ - int ret; - - LOCK_TAKE(hdw->ctl_lock); - - hdw->cmd_buffer[0] = FX2CMD_REG_WRITE; /* write register prefix */ - PVR2_DECOMPOSE_LE(hdw->cmd_buffer,1,data); - hdw->cmd_buffer[5] = 0; - hdw->cmd_buffer[6] = (reg >> 8) & 0xff; - hdw->cmd_buffer[7] = reg & 0xff; - - - ret = pvr2_send_request(hdw, hdw->cmd_buffer, 8, hdw->cmd_buffer, 0); - - LOCK_GIVE(hdw->ctl_lock); - - return ret; -} - - -static int pvr2_read_register(struct pvr2_hdw *hdw, u16 reg, u32 *data) -{ - int ret = 0; - - LOCK_TAKE(hdw->ctl_lock); - - hdw->cmd_buffer[0] = FX2CMD_REG_READ; /* read register prefix */ - hdw->cmd_buffer[1] = 0; - hdw->cmd_buffer[2] = 0; - hdw->cmd_buffer[3] = 0; - hdw->cmd_buffer[4] = 0; - hdw->cmd_buffer[5] = 0; - hdw->cmd_buffer[6] = (reg >> 8) & 0xff; - hdw->cmd_buffer[7] = reg & 0xff; - - ret |= pvr2_send_request(hdw, hdw->cmd_buffer, 8, hdw->cmd_buffer, 4); - *data = PVR2_COMPOSE_LE(hdw->cmd_buffer,0); - - LOCK_GIVE(hdw->ctl_lock); - - return ret; -} - - -void pvr2_hdw_render_useless(struct pvr2_hdw *hdw) -{ - if (!hdw->flag_ok) return; - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Device being rendered inoperable"); - if (hdw->vid_stream) { - pvr2_stream_setup(hdw->vid_stream,NULL,0,0); - } - hdw->flag_ok = 0; - trace_stbit("flag_ok",hdw->flag_ok); - pvr2_hdw_state_sched(hdw); -} - - -void pvr2_hdw_device_reset(struct pvr2_hdw *hdw) -{ - int ret; - pvr2_trace(PVR2_TRACE_INIT,"Performing a device reset..."); - ret = usb_lock_device_for_reset(hdw->usb_dev,NULL); - if (ret == 0) { - ret = usb_reset_device(hdw->usb_dev); - usb_unlock_device(hdw->usb_dev); - } else { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Failed to lock USB device ret=%d",ret); - } - if (init_pause_msec) { - pvr2_trace(PVR2_TRACE_INFO, - "Waiting %u msec for hardware to settle", - init_pause_msec); - msleep(init_pause_msec); - } - -} - - -void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val) -{ - char *da; - unsigned int pipe; - int ret; - - if (!hdw->usb_dev) return; - - da = kmalloc(16, GFP_KERNEL); - - if (da == NULL) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Unable to allocate memory to control CPU reset"); - return; - } - - pvr2_trace(PVR2_TRACE_INIT,"cpureset_assert(%d)",val); - - da[0] = val ? 0x01 : 0x00; - - /* Write the CPUCS register on the 8051. The lsb of the register - is the reset bit; a 1 asserts reset while a 0 clears it. */ - pipe = usb_sndctrlpipe(hdw->usb_dev, 0); - ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0x40,0xe600,0,da,1,HZ); - if (ret < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "cpureset_assert(%d) error=%d",val,ret); - pvr2_hdw_render_useless(hdw); - } - - kfree(da); -} - - -int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw) -{ - return pvr2_issue_simple_cmd(hdw,FX2CMD_DEEP_RESET); -} - - -int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw) -{ - return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_ON); -} - - -int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *hdw) -{ - return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_OFF); -} - - -int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) -{ - pvr2_trace(PVR2_TRACE_INIT, - "Requesting decoder reset"); - if (hdw->decoder_client_id) { - v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id, - core, reset, 0); - pvr2_hdw_cx25840_vbi_hack(hdw); - return 0; - } - pvr2_trace(PVR2_TRACE_INIT, - "Unable to reset decoder: nothing attached"); - return -ENOTTY; -} - - -static int pvr2_hdw_cmd_hcw_demod_reset(struct pvr2_hdw *hdw, int onoff) -{ - hdw->flag_ok = !0; - return pvr2_issue_simple_cmd(hdw, - FX2CMD_HCW_DEMOD_RESETIN | - (1 << 8) | - ((onoff ? 1 : 0) << 16)); -} - - -static int pvr2_hdw_cmd_onair_fe_power_ctrl(struct pvr2_hdw *hdw, int onoff) -{ - hdw->flag_ok = !0; - return pvr2_issue_simple_cmd(hdw,(onoff ? - FX2CMD_ONAIR_DTV_POWER_ON : - FX2CMD_ONAIR_DTV_POWER_OFF)); -} - - -static int pvr2_hdw_cmd_onair_digital_path_ctrl(struct pvr2_hdw *hdw, - int onoff) -{ - return pvr2_issue_simple_cmd(hdw,(onoff ? - FX2CMD_ONAIR_DTV_STREAMING_ON : - FX2CMD_ONAIR_DTV_STREAMING_OFF)); -} - - -static void pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl) -{ - int cmode; - /* Compare digital/analog desired setting with current setting. If - they don't match, fix it... */ - cmode = (digitalFl ? PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG); - if (cmode == hdw->pathway_state) { - /* They match; nothing to do */ - return; - } - - switch (hdw->hdw_desc->digital_control_scheme) { - case PVR2_DIGITAL_SCHEME_HAUPPAUGE: - pvr2_hdw_cmd_hcw_demod_reset(hdw,digitalFl); - if (cmode == PVR2_PATHWAY_ANALOG) { - /* If moving to analog mode, also force the decoder - to reset. If no decoder is attached, then it's - ok to ignore this because if/when the decoder - attaches, it will reset itself at that time. */ - pvr2_hdw_cmd_decoder_reset(hdw); - } - break; - case PVR2_DIGITAL_SCHEME_ONAIR: - /* Supposedly we should always have the power on whether in - digital or analog mode. But for now do what appears to - work... */ - pvr2_hdw_cmd_onair_fe_power_ctrl(hdw,digitalFl); - break; - default: break; - } - - pvr2_hdw_untrip_unlocked(hdw); - hdw->pathway_state = cmode; -} - - -static void pvr2_led_ctrl_hauppauge(struct pvr2_hdw *hdw, int onoff) -{ - /* change some GPIO data - * - * note: bit d7 of dir appears to control the LED, - * so we shut it off here. - * - */ - if (onoff) { - pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000481); - } else { - pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000401); - } - pvr2_hdw_gpio_chg_out(hdw, 0xffffffff, 0x00000000); -} - - -typedef void (*led_method_func)(struct pvr2_hdw *,int); - -static led_method_func led_methods[] = { - [PVR2_LED_SCHEME_HAUPPAUGE] = pvr2_led_ctrl_hauppauge, -}; - - -/* Toggle LED */ -static void pvr2_led_ctrl(struct pvr2_hdw *hdw,int onoff) -{ - unsigned int scheme_id; - led_method_func fp; - - if ((!onoff) == (!hdw->led_on)) return; - - hdw->led_on = onoff != 0; - - scheme_id = hdw->hdw_desc->led_scheme; - if (scheme_id < ARRAY_SIZE(led_methods)) { - fp = led_methods[scheme_id]; - } else { - fp = NULL; - } - - if (fp) (*fp)(hdw,onoff); -} - - -/* Stop / start video stream transport */ -static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl) -{ - int ret; - - /* If we're in analog mode, then just issue the usual analog - command. */ - if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) { - return pvr2_issue_simple_cmd(hdw, - (runFl ? - FX2CMD_STREAMING_ON : - FX2CMD_STREAMING_OFF)); - /*Note: Not reached */ - } - - if (hdw->pathway_state != PVR2_PATHWAY_DIGITAL) { - /* Whoops, we don't know what mode we're in... */ - return -EINVAL; - } - - /* To get here we have to be in digital mode. The mechanism here - is unfortunately different for different vendors. So we switch - on the device's digital scheme attribute in order to figure out - what to do. */ - switch (hdw->hdw_desc->digital_control_scheme) { - case PVR2_DIGITAL_SCHEME_HAUPPAUGE: - return pvr2_issue_simple_cmd(hdw, - (runFl ? - FX2CMD_HCW_DTV_STREAMING_ON : - FX2CMD_HCW_DTV_STREAMING_OFF)); - case PVR2_DIGITAL_SCHEME_ONAIR: - ret = pvr2_issue_simple_cmd(hdw, - (runFl ? - FX2CMD_STREAMING_ON : - FX2CMD_STREAMING_OFF)); - if (ret) return ret; - return pvr2_hdw_cmd_onair_digital_path_ctrl(hdw,runFl); - default: - return -EINVAL; - } -} - - -/* Evaluate whether or not state_pathway_ok can change */ -static int state_eval_pathway_ok(struct pvr2_hdw *hdw) -{ - if (hdw->state_pathway_ok) { - /* Nothing to do if pathway is already ok */ - return 0; - } - if (!hdw->state_pipeline_idle) { - /* Not allowed to change anything if pipeline is not idle */ - return 0; - } - pvr2_hdw_cmd_modeswitch(hdw,hdw->input_val == PVR2_CVAL_INPUT_DTV); - hdw->state_pathway_ok = !0; - trace_stbit("state_pathway_ok",hdw->state_pathway_ok); - return !0; -} - - -/* Evaluate whether or not state_encoder_ok can change */ -static int state_eval_encoder_ok(struct pvr2_hdw *hdw) -{ - if (hdw->state_encoder_ok) return 0; - if (hdw->flag_tripped) return 0; - if (hdw->state_encoder_run) return 0; - if (hdw->state_encoder_config) return 0; - if (hdw->state_decoder_run) return 0; - if (hdw->state_usbstream_run) return 0; - if (hdw->pathway_state == PVR2_PATHWAY_DIGITAL) { - if (!hdw->hdw_desc->flag_digital_requires_cx23416) return 0; - } else if (hdw->pathway_state != PVR2_PATHWAY_ANALOG) { - return 0; - } - - if (pvr2_upload_firmware2(hdw) < 0) { - hdw->flag_tripped = !0; - trace_stbit("flag_tripped",hdw->flag_tripped); - return !0; - } - hdw->state_encoder_ok = !0; - trace_stbit("state_encoder_ok",hdw->state_encoder_ok); - return !0; -} - - -/* Evaluate whether or not state_encoder_config can change */ -static int state_eval_encoder_config(struct pvr2_hdw *hdw) -{ - if (hdw->state_encoder_config) { - if (hdw->state_encoder_ok) { - if (hdw->state_pipeline_req && - !hdw->state_pipeline_pause) return 0; - } - hdw->state_encoder_config = 0; - hdw->state_encoder_waitok = 0; - trace_stbit("state_encoder_waitok",hdw->state_encoder_waitok); - /* paranoia - solve race if timer just completed */ - del_timer_sync(&hdw->encoder_wait_timer); - } else { - if (!hdw->state_pathway_ok || - (hdw->pathway_state != PVR2_PATHWAY_ANALOG) || - !hdw->state_encoder_ok || - !hdw->state_pipeline_idle || - hdw->state_pipeline_pause || - !hdw->state_pipeline_req || - !hdw->state_pipeline_config) { - /* We must reset the enforced wait interval if - anything has happened that might have disturbed - the encoder. This should be a rare case. */ - if (timer_pending(&hdw->encoder_wait_timer)) { - del_timer_sync(&hdw->encoder_wait_timer); - } - if (hdw->state_encoder_waitok) { - /* Must clear the state - therefore we did - something to a state bit and must also - return true. */ - hdw->state_encoder_waitok = 0; - trace_stbit("state_encoder_waitok", - hdw->state_encoder_waitok); - return !0; - } - return 0; - } - if (!hdw->state_encoder_waitok) { - if (!timer_pending(&hdw->encoder_wait_timer)) { - /* waitok flag wasn't set and timer isn't - running. Check flag once more to avoid - a race then start the timer. This is - the point when we measure out a minimal - quiet interval before doing something to - the encoder. */ - if (!hdw->state_encoder_waitok) { - hdw->encoder_wait_timer.expires = - jiffies + - (HZ * TIME_MSEC_ENCODER_WAIT - / 1000); - add_timer(&hdw->encoder_wait_timer); - } - } - /* We can't continue until we know we have been - quiet for the interval measured by this - timer. */ - return 0; - } - pvr2_encoder_configure(hdw); - if (hdw->state_encoder_ok) hdw->state_encoder_config = !0; - } - trace_stbit("state_encoder_config",hdw->state_encoder_config); - return !0; -} - - -/* Return true if the encoder should not be running. */ -static int state_check_disable_encoder_run(struct pvr2_hdw *hdw) -{ - if (!hdw->state_encoder_ok) { - /* Encoder isn't healthy at the moment, so stop it. */ - return !0; - } - if (!hdw->state_pathway_ok) { - /* Mode is not understood at the moment (i.e. it wants to - change), so encoder must be stopped. */ - return !0; - } - - switch (hdw->pathway_state) { - case PVR2_PATHWAY_ANALOG: - if (!hdw->state_decoder_run) { - /* We're in analog mode and the decoder is not - running; thus the encoder should be stopped as - well. */ - return !0; - } - break; - case PVR2_PATHWAY_DIGITAL: - if (hdw->state_encoder_runok) { - /* This is a funny case. We're in digital mode so - really the encoder should be stopped. However - if it really is running, only kill it after - runok has been set. This gives a chance for the - onair quirk to function (encoder must run - briefly first, at least once, before onair - digital streaming can work). */ - return !0; - } - break; - default: - /* Unknown mode; so encoder should be stopped. */ - return !0; - } - - /* If we get here, we haven't found a reason to stop the - encoder. */ - return 0; -} - - -/* Return true if the encoder should be running. */ -static int state_check_enable_encoder_run(struct pvr2_hdw *hdw) -{ - if (!hdw->state_encoder_ok) { - /* Don't run the encoder if it isn't healthy... */ - return 0; - } - if (!hdw->state_pathway_ok) { - /* Don't run the encoder if we don't (yet) know what mode - we need to be in... */ - return 0; - } - - switch (hdw->pathway_state) { - case PVR2_PATHWAY_ANALOG: - if (hdw->state_decoder_run && hdw->state_decoder_ready) { - /* In analog mode, if the decoder is running, then - run the encoder. */ - return !0; - } - break; - case PVR2_PATHWAY_DIGITAL: - if ((hdw->hdw_desc->digital_control_scheme == - PVR2_DIGITAL_SCHEME_ONAIR) && - !hdw->state_encoder_runok) { - /* This is a quirk. OnAir hardware won't stream - digital until the encoder has been run at least - once, for a minimal period of time (empiricially - measured to be 1/4 second). So if we're on - OnAir hardware and the encoder has never been - run at all, then start the encoder. Normal - state machine logic in the driver will - automatically handle the remaining bits. */ - return !0; - } - break; - default: - /* For completeness (unknown mode; encoder won't run ever) */ - break; - } - /* If we get here, then we haven't found any reason to run the - encoder, so don't run it. */ - return 0; -} - - -/* Evaluate whether or not state_encoder_run can change */ -static int state_eval_encoder_run(struct pvr2_hdw *hdw) -{ - if (hdw->state_encoder_run) { - if (!state_check_disable_encoder_run(hdw)) return 0; - if (hdw->state_encoder_ok) { - del_timer_sync(&hdw->encoder_run_timer); - if (pvr2_encoder_stop(hdw) < 0) return !0; - } - hdw->state_encoder_run = 0; - } else { - if (!state_check_enable_encoder_run(hdw)) return 0; - if (pvr2_encoder_start(hdw) < 0) return !0; - hdw->state_encoder_run = !0; - if (!hdw->state_encoder_runok) { - hdw->encoder_run_timer.expires = - jiffies + (HZ * TIME_MSEC_ENCODER_OK / 1000); - add_timer(&hdw->encoder_run_timer); - } - } - trace_stbit("state_encoder_run",hdw->state_encoder_run); - return !0; -} - - -/* Timeout function for quiescent timer. */ -static void pvr2_hdw_quiescent_timeout(unsigned long data) -{ - struct pvr2_hdw *hdw = (struct pvr2_hdw *)data; - hdw->state_decoder_quiescent = !0; - trace_stbit("state_decoder_quiescent",hdw->state_decoder_quiescent); - hdw->state_stale = !0; - queue_work(hdw->workqueue,&hdw->workpoll); -} - - -/* Timeout function for decoder stabilization timer. */ -static void pvr2_hdw_decoder_stabilization_timeout(unsigned long data) -{ - struct pvr2_hdw *hdw = (struct pvr2_hdw *)data; - hdw->state_decoder_ready = !0; - trace_stbit("state_decoder_ready", hdw->state_decoder_ready); - hdw->state_stale = !0; - queue_work(hdw->workqueue, &hdw->workpoll); -} - - -/* Timeout function for encoder wait timer. */ -static void pvr2_hdw_encoder_wait_timeout(unsigned long data) -{ - struct pvr2_hdw *hdw = (struct pvr2_hdw *)data; - hdw->state_encoder_waitok = !0; - trace_stbit("state_encoder_waitok",hdw->state_encoder_waitok); - hdw->state_stale = !0; - queue_work(hdw->workqueue,&hdw->workpoll); -} - - -/* Timeout function for encoder run timer. */ -static void pvr2_hdw_encoder_run_timeout(unsigned long data) -{ - struct pvr2_hdw *hdw = (struct pvr2_hdw *)data; - if (!hdw->state_encoder_runok) { - hdw->state_encoder_runok = !0; - trace_stbit("state_encoder_runok",hdw->state_encoder_runok); - hdw->state_stale = !0; - queue_work(hdw->workqueue,&hdw->workpoll); - } -} - - -/* Evaluate whether or not state_decoder_run can change */ -static int state_eval_decoder_run(struct pvr2_hdw *hdw) -{ - if (hdw->state_decoder_run) { - if (hdw->state_encoder_ok) { - if (hdw->state_pipeline_req && - !hdw->state_pipeline_pause && - hdw->state_pathway_ok) return 0; - } - if (!hdw->flag_decoder_missed) { - pvr2_decoder_enable(hdw,0); - } - hdw->state_decoder_quiescent = 0; - hdw->state_decoder_run = 0; - /* paranoia - solve race if timer(s) just completed */ - del_timer_sync(&hdw->quiescent_timer); - /* Kill the stabilization timer, in case we're killing the - encoder before the previous stabilization interval has - been properly timed. */ - del_timer_sync(&hdw->decoder_stabilization_timer); - hdw->state_decoder_ready = 0; - } else { - if (!hdw->state_decoder_quiescent) { - if (!timer_pending(&hdw->quiescent_timer)) { - /* We don't do something about the - quiescent timer until right here because - we also want to catch cases where the - decoder was already not running (like - after initialization) as opposed to - knowing that we had just stopped it. - The second flag check is here to cover a - race - the timer could have run and set - this flag just after the previous check - but before we did the pending check. */ - if (!hdw->state_decoder_quiescent) { - hdw->quiescent_timer.expires = - jiffies + - (HZ * TIME_MSEC_DECODER_WAIT - / 1000); - add_timer(&hdw->quiescent_timer); - } - } - /* Don't allow decoder to start again until it has - been quiesced first. This little detail should - hopefully further stabilize the encoder. */ - return 0; - } - if (!hdw->state_pathway_ok || - (hdw->pathway_state != PVR2_PATHWAY_ANALOG) || - !hdw->state_pipeline_req || - hdw->state_pipeline_pause || - !hdw->state_pipeline_config || - !hdw->state_encoder_config || - !hdw->state_encoder_ok) return 0; - del_timer_sync(&hdw->quiescent_timer); - if (hdw->flag_decoder_missed) return 0; - if (pvr2_decoder_enable(hdw,!0) < 0) return 0; - hdw->state_decoder_quiescent = 0; - hdw->state_decoder_ready = 0; - hdw->state_decoder_run = !0; - if (hdw->decoder_client_id == PVR2_CLIENT_ID_SAA7115) { - hdw->decoder_stabilization_timer.expires = - jiffies + - (HZ * TIME_MSEC_DECODER_STABILIZATION_WAIT / - 1000); - add_timer(&hdw->decoder_stabilization_timer); - } else { - hdw->state_decoder_ready = !0; - } - } - trace_stbit("state_decoder_quiescent",hdw->state_decoder_quiescent); - trace_stbit("state_decoder_run",hdw->state_decoder_run); - trace_stbit("state_decoder_ready", hdw->state_decoder_ready); - return !0; -} - - -/* Evaluate whether or not state_usbstream_run can change */ -static int state_eval_usbstream_run(struct pvr2_hdw *hdw) -{ - if (hdw->state_usbstream_run) { - int fl = !0; - if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) { - fl = (hdw->state_encoder_ok && - hdw->state_encoder_run); - } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) && - (hdw->hdw_desc->flag_digital_requires_cx23416)) { - fl = hdw->state_encoder_ok; - } - if (fl && - hdw->state_pipeline_req && - !hdw->state_pipeline_pause && - hdw->state_pathway_ok) { - return 0; - } - pvr2_hdw_cmd_usbstream(hdw,0); - hdw->state_usbstream_run = 0; - } else { - if (!hdw->state_pipeline_req || - hdw->state_pipeline_pause || - !hdw->state_pathway_ok) return 0; - if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) { - if (!hdw->state_encoder_ok || - !hdw->state_encoder_run) return 0; - } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) && - (hdw->hdw_desc->flag_digital_requires_cx23416)) { - if (!hdw->state_encoder_ok) return 0; - if (hdw->state_encoder_run) return 0; - if (hdw->hdw_desc->digital_control_scheme == - PVR2_DIGITAL_SCHEME_ONAIR) { - /* OnAir digital receivers won't stream - unless the analog encoder has run first. - Why? I have no idea. But don't even - try until we know the analog side is - known to have run. */ - if (!hdw->state_encoder_runok) return 0; - } - } - if (pvr2_hdw_cmd_usbstream(hdw,!0) < 0) return 0; - hdw->state_usbstream_run = !0; - } - trace_stbit("state_usbstream_run",hdw->state_usbstream_run); - return !0; -} - - -/* Attempt to configure pipeline, if needed */ -static int state_eval_pipeline_config(struct pvr2_hdw *hdw) -{ - if (hdw->state_pipeline_config || - hdw->state_pipeline_pause) return 0; - pvr2_hdw_commit_execute(hdw); - return !0; -} - - -/* Update pipeline idle and pipeline pause tracking states based on other - inputs. This must be called whenever the other relevant inputs have - changed. */ -static int state_update_pipeline_state(struct pvr2_hdw *hdw) -{ - unsigned int st; - int updatedFl = 0; - /* Update pipeline state */ - st = !(hdw->state_encoder_run || - hdw->state_decoder_run || - hdw->state_usbstream_run || - (!hdw->state_decoder_quiescent)); - if (!st != !hdw->state_pipeline_idle) { - hdw->state_pipeline_idle = st; - updatedFl = !0; - } - if (hdw->state_pipeline_idle && hdw->state_pipeline_pause) { - hdw->state_pipeline_pause = 0; - updatedFl = !0; - } - return updatedFl; -} - - -typedef int (*state_eval_func)(struct pvr2_hdw *); - -/* Set of functions to be run to evaluate various states in the driver. */ -static const state_eval_func eval_funcs[] = { - state_eval_pathway_ok, - state_eval_pipeline_config, - state_eval_encoder_ok, - state_eval_encoder_config, - state_eval_decoder_run, - state_eval_encoder_run, - state_eval_usbstream_run, -}; - - -/* Process various states and return true if we did anything interesting. */ -static int pvr2_hdw_state_update(struct pvr2_hdw *hdw) -{ - unsigned int i; - int state_updated = 0; - int check_flag; - - if (!hdw->state_stale) return 0; - if ((hdw->fw1_state != FW1_STATE_OK) || - !hdw->flag_ok) { - hdw->state_stale = 0; - return !0; - } - /* This loop is the heart of the entire driver. It keeps trying to - evaluate various bits of driver state until nothing changes for - one full iteration. Each "bit of state" tracks some global - aspect of the driver, e.g. whether decoder should run, if - pipeline is configured, usb streaming is on, etc. We separately - evaluate each of those questions based on other driver state to - arrive at the correct running configuration. */ - do { - check_flag = 0; - state_update_pipeline_state(hdw); - /* Iterate over each bit of state */ - for (i = 0; (i<ARRAY_SIZE(eval_funcs)) && hdw->flag_ok; i++) { - if ((*eval_funcs[i])(hdw)) { - check_flag = !0; - state_updated = !0; - state_update_pipeline_state(hdw); - } - } - } while (check_flag && hdw->flag_ok); - hdw->state_stale = 0; - trace_stbit("state_stale",hdw->state_stale); - return state_updated; -} - - -static unsigned int print_input_mask(unsigned int msk, - char *buf,unsigned int acnt) -{ - unsigned int idx,ccnt; - unsigned int tcnt = 0; - for (idx = 0; idx < ARRAY_SIZE(control_values_input); idx++) { - if (!((1 << idx) & msk)) continue; - ccnt = scnprintf(buf+tcnt, - acnt-tcnt, - "%s%s", - (tcnt ? ", " : ""), - control_values_input[idx]); - tcnt += ccnt; - } - return tcnt; -} - - -static const char *pvr2_pathway_state_name(int id) -{ - switch (id) { - case PVR2_PATHWAY_ANALOG: return "analog"; - case PVR2_PATHWAY_DIGITAL: return "digital"; - default: return "unknown"; - } -} - - -static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, - char *buf,unsigned int acnt) -{ - switch (which) { - case 0: - return scnprintf( - buf,acnt, - "driver:%s%s%s%s%s <mode=%s>", - (hdw->flag_ok ? " <ok>" : " <fail>"), - (hdw->flag_init_ok ? " <init>" : " <uninitialized>"), - (hdw->flag_disconnected ? " <disconnected>" : - " <connected>"), - (hdw->flag_tripped ? " <tripped>" : ""), - (hdw->flag_decoder_missed ? " <no decoder>" : ""), - pvr2_pathway_state_name(hdw->pathway_state)); - - case 1: - return scnprintf( - buf,acnt, - "pipeline:%s%s%s%s", - (hdw->state_pipeline_idle ? " <idle>" : ""), - (hdw->state_pipeline_config ? - " <configok>" : " <stale>"), - (hdw->state_pipeline_req ? " <req>" : ""), - (hdw->state_pipeline_pause ? " <pause>" : "")); - case 2: - return scnprintf( - buf,acnt, - "worker:%s%s%s%s%s%s%s", - (hdw->state_decoder_run ? - (hdw->state_decoder_ready ? - "<decode:run>" : " <decode:start>") : - (hdw->state_decoder_quiescent ? - "" : " <decode:stop>")), - (hdw->state_decoder_quiescent ? - " <decode:quiescent>" : ""), - (hdw->state_encoder_ok ? - "" : " <encode:init>"), - (hdw->state_encoder_run ? - (hdw->state_encoder_runok ? - " <encode:run>" : - " <encode:firstrun>") : - (hdw->state_encoder_runok ? - " <encode:stop>" : - " <encode:virgin>")), - (hdw->state_encoder_config ? - " <encode:configok>" : - (hdw->state_encoder_waitok ? - "" : " <encode:waitok>")), - (hdw->state_usbstream_run ? - " <usb:run>" : " <usb:stop>"), - (hdw->state_pathway_ok ? - " <pathway:ok>" : "")); - case 3: - return scnprintf( - buf,acnt, - "state: %s", - pvr2_get_state_name(hdw->master_state)); - case 4: { - unsigned int tcnt = 0; - unsigned int ccnt; - - ccnt = scnprintf(buf, - acnt, - "Hardware supported inputs: "); - tcnt += ccnt; - tcnt += print_input_mask(hdw->input_avail_mask, - buf+tcnt, - acnt-tcnt); - if (hdw->input_avail_mask != hdw->input_allowed_mask) { - ccnt = scnprintf(buf+tcnt, - acnt-tcnt, - "; allowed inputs: "); - tcnt += ccnt; - tcnt += print_input_mask(hdw->input_allowed_mask, - buf+tcnt, - acnt-tcnt); - } - return tcnt; - } - case 5: { - struct pvr2_stream_stats stats; - if (!hdw->vid_stream) break; - pvr2_stream_get_stats(hdw->vid_stream, - &stats, - 0); - return scnprintf( - buf,acnt, - "Bytes streamed=%u" - " URBs: queued=%u idle=%u ready=%u" - " processed=%u failed=%u", - stats.bytes_processed, - stats.buffers_in_queue, - stats.buffers_in_idle, - stats.buffers_in_ready, - stats.buffers_processed, - stats.buffers_failed); - } - case 6: { - unsigned int id = hdw->ir_scheme_active; - return scnprintf(buf, acnt, "ir scheme: id=%d %s", id, - (id >= ARRAY_SIZE(ir_scheme_names) ? - "?" : ir_scheme_names[id])); - } - default: break; - } - return 0; -} - - -/* Generate report containing info about attached sub-devices and attached - i2c clients, including an indication of which attached i2c clients are - actually sub-devices. */ -static unsigned int pvr2_hdw_report_clients(struct pvr2_hdw *hdw, - char *buf, unsigned int acnt) -{ - struct v4l2_subdev *sd; - unsigned int tcnt = 0; - unsigned int ccnt; - struct i2c_client *client; - const char *p; - unsigned int id; - - ccnt = scnprintf(buf, acnt, "Associated v4l2-subdev drivers and I2C clients:\n"); - tcnt += ccnt; - v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { - id = sd->grp_id; - p = NULL; - if (id < ARRAY_SIZE(module_names)) p = module_names[id]; - if (p) { - ccnt = scnprintf(buf + tcnt, acnt - tcnt, " %s:", p); - tcnt += ccnt; - } else { - ccnt = scnprintf(buf + tcnt, acnt - tcnt, - " (unknown id=%u):", id); - tcnt += ccnt; - } - client = v4l2_get_subdevdata(sd); - if (client) { - ccnt = scnprintf(buf + tcnt, acnt - tcnt, - " %s @ %02x\n", client->name, - client->addr); - tcnt += ccnt; - } else { - ccnt = scnprintf(buf + tcnt, acnt - tcnt, - " no i2c client\n"); - tcnt += ccnt; - } - } - return tcnt; -} - - -unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw, - char *buf,unsigned int acnt) -{ - unsigned int bcnt,ccnt,idx; - bcnt = 0; - LOCK_TAKE(hdw->big_lock); - for (idx = 0; ; idx++) { - ccnt = pvr2_hdw_report_unlocked(hdw,idx,buf,acnt); - if (!ccnt) break; - bcnt += ccnt; acnt -= ccnt; buf += ccnt; - if (!acnt) break; - buf[0] = '\n'; ccnt = 1; - bcnt += ccnt; acnt -= ccnt; buf += ccnt; - } - ccnt = pvr2_hdw_report_clients(hdw, buf, acnt); - bcnt += ccnt; acnt -= ccnt; buf += ccnt; - LOCK_GIVE(hdw->big_lock); - return bcnt; -} - - -static void pvr2_hdw_state_log_state(struct pvr2_hdw *hdw) -{ - char buf[256]; - unsigned int idx, ccnt; - unsigned int lcnt, ucnt; - - for (idx = 0; ; idx++) { - ccnt = pvr2_hdw_report_unlocked(hdw,idx,buf,sizeof(buf)); - if (!ccnt) break; - printk(KERN_INFO "%s %.*s\n",hdw->name,ccnt,buf); - } - ccnt = pvr2_hdw_report_clients(hdw, buf, sizeof(buf)); - ucnt = 0; - while (ucnt < ccnt) { - lcnt = 0; - while ((lcnt + ucnt < ccnt) && (buf[lcnt + ucnt] != '\n')) { - lcnt++; - } - printk(KERN_INFO "%s %.*s\n", hdw->name, lcnt, buf + ucnt); - ucnt += lcnt + 1; - } -} - - -/* Evaluate and update the driver's current state, taking various actions - as appropriate for the update. */ -static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw) -{ - unsigned int st; - int state_updated = 0; - int callback_flag = 0; - int analog_mode; - - pvr2_trace(PVR2_TRACE_STBITS, - "Drive state check START"); - if (pvrusb2_debug & PVR2_TRACE_STBITS) { - pvr2_hdw_state_log_state(hdw); - } - - /* Process all state and get back over disposition */ - state_updated = pvr2_hdw_state_update(hdw); - - analog_mode = (hdw->pathway_state != PVR2_PATHWAY_DIGITAL); - - /* Update master state based upon all other states. */ - if (!hdw->flag_ok) { - st = PVR2_STATE_DEAD; - } else if (hdw->fw1_state != FW1_STATE_OK) { - st = PVR2_STATE_COLD; - } else if ((analog_mode || - hdw->hdw_desc->flag_digital_requires_cx23416) && - !hdw->state_encoder_ok) { - st = PVR2_STATE_WARM; - } else if (hdw->flag_tripped || - (analog_mode && hdw->flag_decoder_missed)) { - st = PVR2_STATE_ERROR; - } else if (hdw->state_usbstream_run && - (!analog_mode || - (hdw->state_encoder_run && hdw->state_decoder_run))) { - st = PVR2_STATE_RUN; - } else { - st = PVR2_STATE_READY; - } - if (hdw->master_state != st) { - pvr2_trace(PVR2_TRACE_STATE, - "Device state change from %s to %s", - pvr2_get_state_name(hdw->master_state), - pvr2_get_state_name(st)); - pvr2_led_ctrl(hdw,st == PVR2_STATE_RUN); - hdw->master_state = st; - state_updated = !0; - callback_flag = !0; - } - if (state_updated) { - /* Trigger anyone waiting on any state changes here. */ - wake_up(&hdw->state_wait_data); - } - - if (pvrusb2_debug & PVR2_TRACE_STBITS) { - pvr2_hdw_state_log_state(hdw); - } - pvr2_trace(PVR2_TRACE_STBITS, - "Drive state check DONE callback=%d",callback_flag); - - return callback_flag; -} - - -/* Cause kernel thread to check / update driver state */ -static void pvr2_hdw_state_sched(struct pvr2_hdw *hdw) -{ - if (hdw->state_stale) return; - hdw->state_stale = !0; - trace_stbit("state_stale",hdw->state_stale); - queue_work(hdw->workqueue,&hdw->workpoll); -} - - -int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *dp) -{ - return pvr2_read_register(hdw,PVR2_GPIO_DIR,dp); -} - - -int pvr2_hdw_gpio_get_out(struct pvr2_hdw *hdw,u32 *dp) -{ - return pvr2_read_register(hdw,PVR2_GPIO_OUT,dp); -} - - -int pvr2_hdw_gpio_get_in(struct pvr2_hdw *hdw,u32 *dp) -{ - return pvr2_read_register(hdw,PVR2_GPIO_IN,dp); -} - - -int pvr2_hdw_gpio_chg_dir(struct pvr2_hdw *hdw,u32 msk,u32 val) -{ - u32 cval,nval; - int ret; - if (~msk) { - ret = pvr2_read_register(hdw,PVR2_GPIO_DIR,&cval); - if (ret) return ret; - nval = (cval & ~msk) | (val & msk); - pvr2_trace(PVR2_TRACE_GPIO, - "GPIO direction changing 0x%x:0x%x" - " from 0x%x to 0x%x", - msk,val,cval,nval); - } else { - nval = val; - pvr2_trace(PVR2_TRACE_GPIO, - "GPIO direction changing to 0x%x",nval); - } - return pvr2_write_register(hdw,PVR2_GPIO_DIR,nval); -} - - -int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val) -{ - u32 cval,nval; - int ret; - if (~msk) { - ret = pvr2_read_register(hdw,PVR2_GPIO_OUT,&cval); - if (ret) return ret; - nval = (cval & ~msk) | (val & msk); - pvr2_trace(PVR2_TRACE_GPIO, - "GPIO output changing 0x%x:0x%x from 0x%x to 0x%x", - msk,val,cval,nval); - } else { - nval = val; - pvr2_trace(PVR2_TRACE_GPIO, - "GPIO output changing to 0x%x",nval); - } - return pvr2_write_register(hdw,PVR2_GPIO_OUT,nval); -} - - -void pvr2_hdw_status_poll(struct pvr2_hdw *hdw) -{ - struct v4l2_tuner *vtp = &hdw->tuner_signal_info; - memset(vtp, 0, sizeof(*vtp)); - vtp->type = (hdw->input_val == PVR2_CVAL_INPUT_RADIO) ? - V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - hdw->tuner_signal_stale = 0; - /* Note: There apparently is no replacement for VIDIOC_CROPCAP - using v4l2-subdev - therefore we can't support that AT ALL right - now. (Of course, no sub-drivers seem to implement it either. - But now it's a a chicken and egg problem...) */ - v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, g_tuner, vtp); - pvr2_trace(PVR2_TRACE_CHIPS, "subdev status poll" - " type=%u strength=%u audio=0x%x cap=0x%x" - " low=%u hi=%u", - vtp->type, - vtp->signal, vtp->rxsubchans, vtp->capability, - vtp->rangelow, vtp->rangehigh); - - /* We have to do this to avoid getting into constant polling if - there's nobody to answer a poll of cropcap info. */ - hdw->cropcap_stale = 0; -} - - -unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw) -{ - return hdw->input_avail_mask; -} - - -unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *hdw) -{ - return hdw->input_allowed_mask; -} - - -static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v) -{ - if (hdw->input_val != v) { - hdw->input_val = v; - hdw->input_dirty = !0; - } - - /* Handle side effects - if we switch to a mode that needs the RF - tuner, then select the right frequency choice as well and mark - it dirty. */ - if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { - hdw->freqSelector = 0; - hdw->freqDirty = !0; - } else if ((hdw->input_val == PVR2_CVAL_INPUT_TV) || - (hdw->input_val == PVR2_CVAL_INPUT_DTV)) { - hdw->freqSelector = 1; - hdw->freqDirty = !0; - } - return 0; -} - - -int pvr2_hdw_set_input_allowed(struct pvr2_hdw *hdw, - unsigned int change_mask, - unsigned int change_val) -{ - int ret = 0; - unsigned int nv,m,idx; - LOCK_TAKE(hdw->big_lock); - do { - nv = hdw->input_allowed_mask & ~change_mask; - nv |= (change_val & change_mask); - nv &= hdw->input_avail_mask; - if (!nv) { - /* No legal modes left; return error instead. */ - ret = -EPERM; - break; - } - hdw->input_allowed_mask = nv; - if ((1 << hdw->input_val) & hdw->input_allowed_mask) { - /* Current mode is still in the allowed mask, so - we're done. */ - break; - } - /* Select and switch to a mode that is still in the allowed - mask */ - if (!hdw->input_allowed_mask) { - /* Nothing legal; give up */ - break; - } - m = hdw->input_allowed_mask; - for (idx = 0; idx < (sizeof(m) << 3); idx++) { - if (!((1 << idx) & m)) continue; - pvr2_hdw_set_input(hdw,idx); - break; - } - } while (0); - LOCK_GIVE(hdw->big_lock); - return ret; -} - - -/* Find I2C address of eeprom */ -static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) -{ - int result; - LOCK_TAKE(hdw->ctl_lock); do { - hdw->cmd_buffer[0] = FX2CMD_GET_EEPROM_ADDR; - result = pvr2_send_request(hdw, - hdw->cmd_buffer,1, - hdw->cmd_buffer,1); - if (result < 0) break; - result = hdw->cmd_buffer[0]; - } while(0); LOCK_GIVE(hdw->ctl_lock); - return result; -} - - -int pvr2_hdw_register_access(struct pvr2_hdw *hdw, - struct v4l2_dbg_match *match, u64 reg_id, - int setFl, u64 *val_ptr) -{ -#ifdef CONFIG_VIDEO_ADV_DEBUG - struct v4l2_dbg_register req; - int stat = 0; - int okFl = 0; - - if (!capable(CAP_SYS_ADMIN)) return -EPERM; - - req.match = *match; - req.reg = reg_id; - if (setFl) req.val = *val_ptr; - /* It would be nice to know if a sub-device answered the request */ - v4l2_device_call_all(&hdw->v4l2_dev, 0, core, g_register, &req); - if (!setFl) *val_ptr = req.val; - if (okFl) { - return stat; - } - return -EINVAL; -#else - return -ENOSYS; -#endif -} - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h deleted file mode 100644 index 8060fc666eeb..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ /dev/null @@ -1,360 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __PVRUSB2_HDW_H -#define __PVRUSB2_HDW_H - -#include <linux/usb.h> -#include <linux/videodev2.h> -#include "pvrusb2-io.h" -#include "pvrusb2-ctrl.h" - - -/* Private internal control ids, look these up with - pvr2_hdw_get_ctrl_by_id() - these are NOT visible in V4L */ -#define PVR2_CID_STDCUR 2 -#define PVR2_CID_STDAVAIL 3 -#define PVR2_CID_INPUT 4 -#define PVR2_CID_AUDIOMODE 5 -#define PVR2_CID_FREQUENCY 6 -#define PVR2_CID_HRES 7 -#define PVR2_CID_VRES 8 -#define PVR2_CID_CROPL 9 -#define PVR2_CID_CROPT 10 -#define PVR2_CID_CROPW 11 -#define PVR2_CID_CROPH 12 -#define PVR2_CID_CROPCAPPAN 13 -#define PVR2_CID_CROPCAPPAD 14 -#define PVR2_CID_CROPCAPBL 15 -#define PVR2_CID_CROPCAPBT 16 -#define PVR2_CID_CROPCAPBW 17 -#define PVR2_CID_CROPCAPBH 18 -#define PVR2_CID_STDDETECT 19 - -/* Legal values for the INPUT state variable */ -#define PVR2_CVAL_INPUT_TV 0 -#define PVR2_CVAL_INPUT_DTV 1 -#define PVR2_CVAL_INPUT_COMPOSITE 2 -#define PVR2_CVAL_INPUT_SVIDEO 3 -#define PVR2_CVAL_INPUT_RADIO 4 - -enum pvr2_config { - pvr2_config_empty, /* No configuration */ - pvr2_config_mpeg, /* Encoded / compressed video */ - pvr2_config_vbi, /* Standard vbi info */ - pvr2_config_pcm, /* Audio raw pcm stream */ - pvr2_config_rawvideo, /* Video raw frames */ -}; - -enum pvr2_v4l_type { - pvr2_v4l_type_video, - pvr2_v4l_type_vbi, - pvr2_v4l_type_radio, -}; - -/* Major states that we can be in: - * - * DEAD - Device is in an unusable state and cannot be recovered. This - * can happen if we completely lose the ability to communicate with it - * (but it might still on the bus). In this state there's nothing we can - * do; it must be replugged in order to recover. - * - * COLD - Device is in an unusable state, needs microcontroller firmware. - * - * WARM - We can communicate with the device and the proper - * microcontroller firmware is running, but other device initialization is - * still needed (e.g. encoder firmware). - * - * ERROR - A problem prevents capture operation (e.g. encoder firmware - * missing). - * - * READY - Device is operational, but not streaming. - * - * RUN - Device is streaming. - * - */ -#define PVR2_STATE_NONE 0 -#define PVR2_STATE_DEAD 1 -#define PVR2_STATE_COLD 2 -#define PVR2_STATE_WARM 3 -#define PVR2_STATE_ERROR 4 -#define PVR2_STATE_READY 5 -#define PVR2_STATE_RUN 6 - -/* Translate configuration enum to a string label */ -const char *pvr2_config_get_name(enum pvr2_config); - -struct pvr2_hdw; - -/* Create and return a structure for interacting with the underlying - hardware */ -struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, - const struct usb_device_id *devid); - -/* Perform second stage initialization, passing in a notification callback - for when the master state changes. */ -int pvr2_hdw_initialize(struct pvr2_hdw *, - void (*callback_func)(void *), - void *callback_data); - -/* Destroy hardware interaction structure */ -void pvr2_hdw_destroy(struct pvr2_hdw *); - -/* Return true if in the ready (normal) state */ -int pvr2_hdw_dev_ok(struct pvr2_hdw *); - -/* Return small integer number [1..N] for logical instance number of this - device. This is useful for indexing array-valued module parameters. */ -int pvr2_hdw_get_unit_number(struct pvr2_hdw *); - -/* Get pointer to underlying USB device */ -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 *); - -/* Retrieve per-instance string identifier for this specific device */ -const char *pvr2_hdw_get_device_identifier(struct pvr2_hdw *); - -/* Called when hardware has been unplugged */ -void pvr2_hdw_disconnect(struct pvr2_hdw *); - -/* Get the number of defined controls */ -unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *); - -/* Retrieve a control handle given its index (0..count-1) */ -struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *,unsigned int); - -/* Retrieve a control handle given its internal ID (if any) */ -struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *,unsigned int); - -/* Retrieve a control handle given its V4L ID (if any) */ -struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *,unsigned int ctl_id); - -/* Retrieve a control handle given its immediate predecessor V4L ID (if any) */ -struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *, - unsigned int ctl_id); - -/* Commit all control changes made up to this point */ -int pvr2_hdw_commit_ctl(struct pvr2_hdw *); - -/* Return a bit mask of valid input selections for this device. Mask bits - * will be according to PVR_CVAL_INPUT_xxxx definitions. */ -unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *); - -/* Return a bit mask of allowed input selections for this device. Mask bits - * will be according to PVR_CVAL_INPUT_xxxx definitions. */ -unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *); - -/* Change the set of allowed input selections for this device. Both - change_mask and change_valu are mask bits according to - PVR_CVAL_INPUT_xxxx definitions. The change_mask parameter indicate - which settings are being changed and the change_val parameter indicates - whether corresponding settings are being set or cleared. */ -int pvr2_hdw_set_input_allowed(struct pvr2_hdw *, - unsigned int change_mask, - unsigned int change_val); - -/* Return name for this driver instance */ -const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *); - -/* Mark tuner status stale so that it will be re-fetched */ -void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *); - -/* Return information about the tuner */ -int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *); - -/* Return information about cropping capabilities */ -int pvr2_hdw_get_cropcap(struct pvr2_hdw *, struct v4l2_cropcap *); - -/* Query device and see if it thinks it is on a high-speed USB link */ -int pvr2_hdw_is_hsm(struct pvr2_hdw *); - -/* Return a string token representative of the hardware type */ -const char *pvr2_hdw_get_type(struct pvr2_hdw *); - -/* Return a single line description of the hardware type */ -const char *pvr2_hdw_get_desc(struct pvr2_hdw *); - -/* Turn streaming on/off */ -int pvr2_hdw_set_streaming(struct pvr2_hdw *,int); - -/* Find out if streaming is on */ -int pvr2_hdw_get_streaming(struct pvr2_hdw *); - -/* Retrieve driver overall state */ -int pvr2_hdw_get_state(struct pvr2_hdw *); - -/* Configure the type of stream to generate */ -int pvr2_hdw_set_stream_type(struct pvr2_hdw *, enum pvr2_config); - -/* Get handle to video output stream */ -struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *); - -/* Enable / disable retrieval of CPU firmware or prom contents. This must - be enabled before pvr2_hdw_cpufw_get() will function. Note that doing - this may prevent the device from running (and leaving this mode may - imply a device reset). */ -void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *, - int mode, /* 0=8KB FX2, 1=16KB FX2, 2=PROM */ - int enable_flag); - -/* Return true if we're in a mode for retrieval CPU firmware */ -int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *); - -/* Retrieve a piece of the CPU's firmware at the given offset. Return - value is the number of bytes retrieved or zero if we're past the end or - an error otherwise (e.g. if firmware retrieval is not enabled). */ -int pvr2_hdw_cpufw_get(struct pvr2_hdw *,unsigned int offs, - char *buf,unsigned int cnt); - -/* Retrieve a previously stored v4l minor device number */ -int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *,enum pvr2_v4l_type index); - -/* Store a v4l minor device number */ -void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *, - enum pvr2_v4l_type index,int); - -/* Direct read/write access to chip's registers: - match - specify criteria to identify target chip (this is a v4l dbg struct) - reg_id - register number to access - setFl - true to set the register, false to read it - val_ptr - storage location for source / result. */ -int pvr2_hdw_register_access(struct pvr2_hdw *, - struct v4l2_dbg_match *match, u64 reg_id, - int setFl, u64 *val_ptr); - -/* The following entry points are all lower level things you normally don't - want to worry about. */ - -/* Issue a command and get a response from the device. LOTS of higher - level stuff is built on this. */ -int pvr2_send_request(struct pvr2_hdw *, - void *write_ptr,unsigned int write_len, - void *read_ptr,unsigned int read_len); - -/* Slightly higher level device communication functions. */ -int pvr2_write_register(struct pvr2_hdw *, u16, u32); - -/* Call if for any reason we can't talk to the hardware anymore - this will - cause the driver to stop flailing on the device. */ -void pvr2_hdw_render_useless(struct pvr2_hdw *); - -/* Set / clear 8051's reset bit */ -void pvr2_hdw_cpureset_assert(struct pvr2_hdw *,int); - -/* Execute a USB-commanded device reset */ -void pvr2_hdw_device_reset(struct pvr2_hdw *); - -/* Reset worker's error trapping circuit breaker */ -int pvr2_hdw_untrip(struct pvr2_hdw *); - -/* Execute hard reset command (after this point it's likely that the - encoder will have to be reconfigured). This also clears the "useless" - state. */ -int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *); - -/* Execute simple reset command */ -int pvr2_hdw_cmd_powerup(struct pvr2_hdw *); - -/* suspend */ -int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *); - -/* Order decoder to reset */ -int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *); - -/* Direct manipulation of GPIO bits */ -int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *); -int pvr2_hdw_gpio_get_out(struct pvr2_hdw *hdw,u32 *); -int pvr2_hdw_gpio_get_in(struct pvr2_hdw *hdw,u32 *); -int pvr2_hdw_gpio_chg_dir(struct pvr2_hdw *hdw,u32 msk,u32 val); -int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val); - -/* This data structure is specifically for the next function... */ -struct pvr2_hdw_debug_info { - int big_lock_held; - int ctl_lock_held; - int flag_disconnected; - int flag_init_ok; - int flag_ok; - int fw1_state; - int flag_decoder_missed; - int flag_tripped; - int state_encoder_ok; - int state_encoder_run; - int state_decoder_run; - int state_decoder_ready; - int state_usbstream_run; - int state_decoder_quiescent; - int state_pipeline_config; - int state_pipeline_req; - int state_pipeline_pause; - int state_pipeline_idle; - int cmd_debug_state; - int cmd_debug_write_len; - int cmd_debug_read_len; - int cmd_debug_write_pend; - int cmd_debug_read_pend; - int cmd_debug_timeout; - int cmd_debug_rstatus; - int cmd_debug_wstatus; - unsigned char cmd_code; -}; - -/* Non-intrusively retrieve internal state info - this is useful for - diagnosing lockups. Note that this operation is completed without any - kind of locking and so it is not atomic and may yield inconsistent - results. This is *purely* a debugging aid. */ -void pvr2_hdw_get_debug_info_unlocked(const struct pvr2_hdw *hdw, - struct pvr2_hdw_debug_info *); - -/* Intrusively retrieve internal state info - this is useful for - diagnosing overall driver state. This operation synchronizes against - the overall driver mutex - so if there are locking problems this will - likely hang! This is *purely* a debugging aid. */ -void pvr2_hdw_get_debug_info_locked(struct pvr2_hdw *hdw, - struct pvr2_hdw_debug_info *); - -/* Report out several lines of text that describes driver internal state. - Results are written into the passed-in buffer. */ -unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw, - char *buf_ptr,unsigned int buf_size); - -/* Cause modules to log their state once */ -void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw); - -/* Cause encoder firmware to be uploaded into the device. This is normally - done autonomously, but the interface is exported here because it is also - a debugging aid. */ -int pvr2_upload_firmware2(struct pvr2_hdw *hdw); - -#endif /* __PVRUSB2_HDW_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c deleted file mode 100644 index 885ce11f222d..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ /dev/null @@ -1,698 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/i2c.h> -#include <linux/module.h> -#include <media/ir-kbd-i2c.h> -#include "pvrusb2-i2c-core.h" -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-debug.h" -#include "pvrusb2-fx2-cmd.h" -#include "pvrusb2.h" - -#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) - -/* - - This module attempts to implement a compliant I2C adapter for the pvrusb2 - device. - -*/ - -static unsigned int i2c_scan; -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 int pvr2_disable_ir_video; -module_param_named(disable_autoload_ir_video, pvr2_disable_ir_video, - int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(disable_autoload_ir_video, - "1=do not try to autoload ir_video IR receiver"); - -static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */ - u8 i2c_addr, /* I2C address we're talking to */ - u8 *data, /* Data to write */ - u16 length) /* Size of data to write */ -{ - /* Return value - default 0 means success */ - int ret; - - - if (!data) length = 0; - if (length > (sizeof(hdw->cmd_buffer) - 3)) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Killing an I2C write to %u that is too large" - " (desired=%u limit=%u)", - i2c_addr, - length,(unsigned int)(sizeof(hdw->cmd_buffer) - 3)); - return -ENOTSUPP; - } - - LOCK_TAKE(hdw->ctl_lock); - - /* Clear the command buffer (likely to be paranoia) */ - memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer)); - - /* Set up command buffer for an I2C write */ - hdw->cmd_buffer[0] = FX2CMD_I2C_WRITE; /* write prefix */ - hdw->cmd_buffer[1] = i2c_addr; /* i2c addr of chip */ - hdw->cmd_buffer[2] = length; /* length of what follows */ - if (length) memcpy(hdw->cmd_buffer + 3, data, length); - - /* Do the operation */ - ret = pvr2_send_request(hdw, - hdw->cmd_buffer, - length + 3, - hdw->cmd_buffer, - 1); - if (!ret) { - if (hdw->cmd_buffer[0] != 8) { - ret = -EIO; - if (hdw->cmd_buffer[0] != 7) { - trace_i2c("unexpected status" - " from i2_write[%d]: %d", - i2c_addr,hdw->cmd_buffer[0]); - } - } - } - - LOCK_GIVE(hdw->ctl_lock); - - return ret; -} - -static int pvr2_i2c_read(struct pvr2_hdw *hdw, /* Context */ - u8 i2c_addr, /* I2C address we're talking to */ - u8 *data, /* Data to write */ - u16 dlen, /* Size of data to write */ - u8 *res, /* Where to put data we read */ - u16 rlen) /* Amount of data to read */ -{ - /* Return value - default 0 means success */ - int ret; - - - if (!data) dlen = 0; - if (dlen > (sizeof(hdw->cmd_buffer) - 4)) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Killing an I2C read to %u that has wlen too large" - " (desired=%u limit=%u)", - i2c_addr, - dlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 4)); - return -ENOTSUPP; - } - if (res && (rlen > (sizeof(hdw->cmd_buffer) - 1))) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Killing an I2C read to %u that has rlen too large" - " (desired=%u limit=%u)", - i2c_addr, - rlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 1)); - return -ENOTSUPP; - } - - LOCK_TAKE(hdw->ctl_lock); - - /* Clear the command buffer (likely to be paranoia) */ - memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer)); - - /* Set up command buffer for an I2C write followed by a read */ - hdw->cmd_buffer[0] = FX2CMD_I2C_READ; /* read prefix */ - hdw->cmd_buffer[1] = dlen; /* arg length */ - hdw->cmd_buffer[2] = rlen; /* answer length. Device will send one - more byte (status). */ - hdw->cmd_buffer[3] = i2c_addr; /* i2c addr of chip */ - if (dlen) memcpy(hdw->cmd_buffer + 4, data, dlen); - - /* Do the operation */ - ret = pvr2_send_request(hdw, - hdw->cmd_buffer, - 4 + dlen, - hdw->cmd_buffer, - rlen + 1); - if (!ret) { - if (hdw->cmd_buffer[0] != 8) { - ret = -EIO; - if (hdw->cmd_buffer[0] != 7) { - trace_i2c("unexpected status" - " from i2_read[%d]: %d", - i2c_addr,hdw->cmd_buffer[0]); - } - } - } - - /* Copy back the result */ - if (res && rlen) { - if (ret) { - /* Error, just blank out the return buffer */ - memset(res, 0, rlen); - } else { - memcpy(res, hdw->cmd_buffer + 1, rlen); - } - } - - LOCK_GIVE(hdw->ctl_lock); - - return ret; -} - -/* This is the common low level entry point for doing I2C operations to the - hardware. */ -static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw, - u8 i2c_addr, - u8 *wdata, - u16 wlen, - u8 *rdata, - u16 rlen) -{ - if (!rdata) rlen = 0; - if (!wdata) wlen = 0; - if (rlen || !wlen) { - return pvr2_i2c_read(hdw,i2c_addr,wdata,wlen,rdata,rlen); - } else { - return pvr2_i2c_write(hdw,i2c_addr,wdata,wlen); - } -} - - -/* This is a special entry point for cases of I2C transaction attempts to - the IR receiver. The implementation here simulates the IR receiver by - issuing a command to the FX2 firmware and using that response to return - what the real I2C receiver would have returned. We use this for 24xxx - devices, where the IR receiver chip has been removed and replaced with - FX2 related logic. */ -static int i2c_24xxx_ir(struct pvr2_hdw *hdw, - u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen) -{ - u8 dat[4]; - unsigned int stat; - - if (!(rlen || wlen)) { - /* This is a probe attempt. Just let it succeed. */ - return 0; - } - - /* We don't understand this kind of transaction */ - if ((wlen != 0) || (rlen == 0)) return -EIO; - - if (rlen < 3) { - /* Mike Isely <isely@pobox.com> Appears to be a probe - attempt from lirc. Just fill in zeroes and return. If - we try instead to do the full transaction here, then bad - things seem to happen within the lirc driver module - (version 0.8.0-7 sources from Debian, when run under - vanilla 2.6.17.6 kernel) - and I don't have the patience - to chase it down. */ - if (rlen > 0) rdata[0] = 0; - if (rlen > 1) rdata[1] = 0; - return 0; - } - - /* Issue a command to the FX2 to read the IR receiver. */ - LOCK_TAKE(hdw->ctl_lock); do { - hdw->cmd_buffer[0] = FX2CMD_GET_IR_CODE; - stat = pvr2_send_request(hdw, - hdw->cmd_buffer,1, - hdw->cmd_buffer,4); - dat[0] = hdw->cmd_buffer[0]; - dat[1] = hdw->cmd_buffer[1]; - dat[2] = hdw->cmd_buffer[2]; - dat[3] = hdw->cmd_buffer[3]; - } while (0); LOCK_GIVE(hdw->ctl_lock); - - /* Give up if that operation failed. */ - if (stat != 0) return stat; - - /* Mangle the results into something that looks like the real IR - receiver. */ - rdata[2] = 0xc1; - if (dat[0] != 1) { - /* No code received. */ - rdata[0] = 0; - rdata[1] = 0; - } else { - u16 val; - /* Mash the FX2 firmware-provided IR code into something - that the normal i2c chip-level driver expects. */ - val = dat[1]; - val <<= 8; - val |= dat[2]; - val >>= 1; - val &= ~0x0003; - val |= 0x8000; - rdata[0] = (val >> 8) & 0xffu; - rdata[1] = val & 0xffu; - } - - return 0; -} - -/* This is a special entry point that is entered if an I2C operation is - attempted to a wm8775 chip on model 24xxx hardware. Autodetect of this - part doesn't work, but we know it is really there. So let's look for - the autodetect attempt and just return success if we see that. */ -static int i2c_hack_wm8775(struct pvr2_hdw *hdw, - u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen) -{ - if (!(rlen || wlen)) { - // This is a probe attempt. Just let it succeed. - return 0; - } - 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 - falsely detect this part and then the system gets hosed up after msp3400 - gets confused and dies. What we want to do here is try to keep msp3400 - away and also try to notice if the chip is wedged and send a warning to - the system log. */ -static int i2c_hack_cx25840(struct pvr2_hdw *hdw, - u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen) -{ - int ret; - unsigned int subaddr; - u8 wbuf[2]; - int state = hdw->i2c_cx25840_hack_state; - - if (!(rlen || wlen)) { - // Probe attempt - always just succeed and don't bother the - // hardware (this helps to make the state machine further - // down somewhat easier). - return 0; - } - - if (state == 3) { - return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen); - } - - /* We're looking for the exact pattern where the revision register - is being read. The cx25840 module will always look at the - revision register first. Any other pattern of access therefore - has to be a probe attempt from somebody else so we'll reject it. - Normally we could just let each client just probe the part - anyway, but when the cx25840 is wedged, msp3400 will get a false - positive and that just screws things up... */ - - if (wlen == 0) { - switch (state) { - case 1: subaddr = 0x0100; break; - case 2: subaddr = 0x0101; break; - default: goto fail; - } - } else if (wlen == 2) { - subaddr = (wdata[0] << 8) | wdata[1]; - switch (subaddr) { - case 0x0100: state = 1; break; - case 0x0101: state = 2; break; - default: goto fail; - } - } else { - goto fail; - } - if (!rlen) goto success; - state = 0; - if (rlen != 1) goto fail; - - /* If we get to here then we have a legitimate read for one of the - two revision bytes, so pass it through. */ - wbuf[0] = subaddr >> 8; - wbuf[1] = subaddr; - ret = pvr2_i2c_basic_op(hdw,i2c_addr,wbuf,2,rdata,rlen); - - if ((ret != 0) || (*rdata == 0x04) || (*rdata == 0x0a)) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "WARNING: Detected a wedged cx25840 chip;" - " the device will not work."); - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "WARNING: Try power cycling the pvrusb2 device."); - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "WARNING: Disabling further access to the device" - " to prevent other foul-ups."); - // This blocks all further communication with the part. - hdw->i2c_func[0x44] = NULL; - pvr2_hdw_render_useless(hdw); - goto fail; - } - - /* Success! */ - pvr2_trace(PVR2_TRACE_CHIPS,"cx25840 appears to be OK."); - state = 3; - - success: - hdw->i2c_cx25840_hack_state = state; - return 0; - - fail: - hdw->i2c_cx25840_hack_state = state; - return -EIO; -} - -/* This is a very, very limited I2C adapter implementation. We can only - support what we actually know will work on the device... */ -static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msgs[], - int num) -{ - int ret = -ENOTSUPP; - pvr2_i2c_func funcp = NULL; - struct pvr2_hdw *hdw = (struct pvr2_hdw *)(i2c_adap->algo_data); - - if (!num) { - ret = -EINVAL; - goto done; - } - if (msgs[0].addr < PVR2_I2C_FUNC_CNT) { - funcp = hdw->i2c_func[msgs[0].addr]; - } - if (!funcp) { - ret = -EIO; - goto done; - } - - if (num == 1) { - if (msgs[0].flags & I2C_M_RD) { - /* Simple read */ - u16 tcnt,bcnt,offs; - if (!msgs[0].len) { - /* Length == 0 read. This is a probe. */ - if (funcp(hdw,msgs[0].addr,NULL,0,NULL,0)) { - ret = -EIO; - goto done; - } - ret = 1; - goto done; - } - /* If the read is short enough we'll do the whole - thing atomically. Otherwise we have no choice - but to break apart the reads. */ - tcnt = msgs[0].len; - offs = 0; - while (tcnt) { - bcnt = tcnt; - if (bcnt > sizeof(hdw->cmd_buffer)-1) { - bcnt = sizeof(hdw->cmd_buffer)-1; - } - if (funcp(hdw,msgs[0].addr,NULL,0, - msgs[0].buf+offs,bcnt)) { - ret = -EIO; - goto done; - } - offs += bcnt; - tcnt -= bcnt; - } - ret = 1; - goto done; - } else { - /* Simple write */ - ret = 1; - if (funcp(hdw,msgs[0].addr, - msgs[0].buf,msgs[0].len,NULL,0)) { - ret = -EIO; - } - goto done; - } - } else if (num == 2) { - if (msgs[0].addr != msgs[1].addr) { - trace_i2c("i2c refusing 2 phase transfer with" - " conflicting target addresses"); - ret = -ENOTSUPP; - goto done; - } - if ((!((msgs[0].flags & I2C_M_RD))) && - (msgs[1].flags & I2C_M_RD)) { - u16 tcnt,bcnt,wcnt,offs; - /* Write followed by atomic read. If the read - portion is short enough we'll do the whole thing - atomically. Otherwise we have no choice but to - break apart the reads. */ - tcnt = msgs[1].len; - wcnt = msgs[0].len; - offs = 0; - while (tcnt || wcnt) { - bcnt = tcnt; - if (bcnt > sizeof(hdw->cmd_buffer)-1) { - bcnt = sizeof(hdw->cmd_buffer)-1; - } - if (funcp(hdw,msgs[0].addr, - msgs[0].buf,wcnt, - msgs[1].buf+offs,bcnt)) { - ret = -EIO; - goto done; - } - offs += bcnt; - tcnt -= bcnt; - wcnt = 0; - } - ret = 2; - goto done; - } else { - trace_i2c("i2c refusing complex transfer" - " read0=%d read1=%d", - (msgs[0].flags & I2C_M_RD), - (msgs[1].flags & I2C_M_RD)); - } - } else { - trace_i2c("i2c refusing %d phase transfer",num); - } - - done: - if (pvrusb2_debug & PVR2_TRACE_I2C_TRAF) { - unsigned int idx,offs,cnt; - for (idx = 0; idx < num; idx++) { - cnt = msgs[idx].len; - printk(KERN_INFO - "pvrusb2 i2c xfer %u/%u:" - " addr=0x%x len=%d %s", - idx+1,num, - msgs[idx].addr, - cnt, - (msgs[idx].flags & I2C_M_RD ? - "read" : "write")); - if ((ret > 0) || !(msgs[idx].flags & I2C_M_RD)) { - if (cnt > 8) cnt = 8; - printk(" ["); - for (offs = 0; offs < (cnt>8?8:cnt); offs++) { - if (offs) printk(" "); - printk("%02x",msgs[idx].buf[offs]); - } - if (offs < cnt) printk(" ..."); - printk("]"); - } - if (idx+1 == num) { - printk(" result=%d",ret); - } - printk("\n"); - } - if (!num) { - printk(KERN_INFO - "pvrusb2 i2c xfer null transfer result=%d\n", - ret); - } - } - return ret; -} - -static u32 pvr2_i2c_functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; -} - -static struct i2c_algorithm pvr2_i2c_algo_template = { - .master_xfer = pvr2_i2c_xfer, - .functionality = pvr2_i2c_functionality, -}; - -static struct i2c_adapter pvr2_i2c_adap_template = { - .owner = THIS_MODULE, - .class = 0, -}; - - -/* Return true if device exists at given address */ -static int do_i2c_probe(struct pvr2_hdw *hdw, int addr) -{ - struct i2c_msg msg[1]; - int rc; - msg[0].addr = 0; - msg[0].flags = I2C_M_RD; - msg[0].len = 0; - msg[0].buf = NULL; - msg[0].addr = addr; - rc = i2c_transfer(&hdw->i2c_adap, msg, ARRAY_SIZE(msg)); - return rc == 1; -} - -static void do_i2c_scan(struct pvr2_hdw *hdw) -{ - int i; - printk(KERN_INFO "%s: i2c scan beginning\n", hdw->name); - for (i = 0; i < 128; i++) { - if (do_i2c_probe(hdw, i)) { - printk(KERN_INFO "%s: i2c scan: found device @ 0x%x\n", - hdw->name, i); - } - } - printk(KERN_INFO "%s: i2c scan done.\n", hdw->name); -} - -static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw) -{ - struct i2c_board_info info; - struct IR_i2c_init_data *init_data = &hdw->ir_init_data; - if (pvr2_disable_ir_video) { - pvr2_trace(PVR2_TRACE_INFO, - "Automatic binding of ir_video has been disabled."); - return; - } - memset(&info, 0, sizeof(struct i2c_board_info)); - switch (hdw->ir_scheme_active) { - case PVR2_IR_SCHEME_24XXX: /* FX2-controlled IR */ - case PVR2_IR_SCHEME_29XXX: /* Original 29xxx device */ - init_data->ir_codes = RC_MAP_HAUPPAUGE; - init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP; - init_data->type = RC_TYPE_RC5; - init_data->name = hdw->hdw_desc->description; - init_data->polling_interval = 100; /* ms From ir-kbd-i2c */ - /* IR Receiver */ - info.addr = 0x18; - info.platform_data = init_data; - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); - pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.", - info.type, info.addr); - i2c_new_device(&hdw->i2c_adap, &info); - break; - case PVR2_IR_SCHEME_ZILOG: /* HVR-1950 style */ - case PVR2_IR_SCHEME_24XXX_MCE: /* 24xxx MCE device */ - init_data->ir_codes = RC_MAP_HAUPPAUGE; - init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; - init_data->type = RC_TYPE_RC5; - init_data->name = hdw->hdw_desc->description; - /* IR Receiver */ - info.addr = 0x71; - info.platform_data = init_data; - strlcpy(info.type, "ir_rx_z8f0811_haup", I2C_NAME_SIZE); - pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.", - info.type, info.addr); - i2c_new_device(&hdw->i2c_adap, &info); - /* IR Trasmitter */ - info.addr = 0x70; - info.platform_data = init_data; - strlcpy(info.type, "ir_tx_z8f0811_haup", I2C_NAME_SIZE); - pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.", - info.type, info.addr); - i2c_new_device(&hdw->i2c_adap, &info); - break; - default: - /* The device either doesn't support I2C-based IR or we - don't know (yet) how to operate IR on the device. */ - break; - } -} - -void pvr2_i2c_core_init(struct pvr2_hdw *hdw) -{ - unsigned int idx; - - /* The default action for all possible I2C addresses is just to do - the transfer normally. */ - for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) { - hdw->i2c_func[idx] = pvr2_i2c_basic_op; - } - - /* 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->ir_scheme_active == PVR2_IR_SCHEME_24XXX) { - /* Set up translation so that our IR looks like a - 29xxx device */ - hdw->i2c_func[0x18] = i2c_24xxx_ir; - } - } - if (hdw->hdw_desc->flag_has_cx25840) { - hdw->i2c_func[0x44] = i2c_hack_cx25840; - } - if (hdw->hdw_desc->flag_has_wm8775) { - hdw->i2c_func[0x1b] = i2c_hack_wm8775; - } - - // Configure the adapter and set up everything else related to it. - memcpy(&hdw->i2c_adap,&pvr2_i2c_adap_template,sizeof(hdw->i2c_adap)); - memcpy(&hdw->i2c_algo,&pvr2_i2c_algo_template,sizeof(hdw->i2c_algo)); - strlcpy(hdw->i2c_adap.name,hdw->name,sizeof(hdw->i2c_adap.name)); - hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev; - hdw->i2c_adap.algo = &hdw->i2c_algo; - hdw->i2c_adap.algo_data = hdw; - hdw->i2c_linked = !0; - i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev); - i2c_add_adapter(&hdw->i2c_adap); - if (hdw->i2c_func[0x18] == i2c_24xxx_ir) { - /* Probe for a different type of IR receiver on this - device. This is really the only way to differentiate - older 24xxx devices from 24xxx variants that include an - IR blaster. If the IR blaster is present, the IR - receiver is part of that chip and thus we must disable - the emulated IR receiver. */ - if (do_i2c_probe(hdw, 0x71)) { - pvr2_trace(PVR2_TRACE_INFO, - "Device has newer IR hardware;" - " disabling unneeded virtual IR device"); - hdw->i2c_func[0x18] = NULL; - /* Remember that this is a different device... */ - hdw->ir_scheme_active = PVR2_IR_SCHEME_24XXX_MCE; - } - } - if (i2c_scan) do_i2c_scan(hdw); - - pvr2_i2c_register_ir(hdw); -} - -void pvr2_i2c_core_done(struct pvr2_hdw *hdw) -{ - if (hdw->i2c_linked) { - i2c_del_adapter(&hdw->i2c_adap); - hdw->i2c_linked = 0; - } -} - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h deleted file mode 100644 index 6a75769200bd..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __PVRUSB2_I2C_CORE_H -#define __PVRUSB2_I2C_CORE_H - -struct pvr2_hdw; - -void pvr2_i2c_core_init(struct pvr2_hdw *); -void pvr2_i2c_core_done(struct pvr2_hdw *); - - -#endif /* __PVRUSB2_I2C_ADAPTER_H */ - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c deleted file mode 100644 index 20b6ae0bb40d..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-io.c +++ /dev/null @@ -1,695 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "pvrusb2-io.h" -#include "pvrusb2-debug.h" -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/slab.h> -#include <linux/mutex.h> - -static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state); - -#define BUFFER_SIG 0x47653271 - -// #define SANITY_CHECK_BUFFERS - - -#ifdef SANITY_CHECK_BUFFERS -#define BUFFER_CHECK(bp) do { \ - if ((bp)->signature != BUFFER_SIG) { \ - pvr2_trace(PVR2_TRACE_ERROR_LEGS, \ - "Buffer %p is bad at %s:%d", \ - (bp),__FILE__,__LINE__); \ - pvr2_buffer_describe(bp,"BadSig"); \ - BUG(); \ - } \ -} while (0) -#else -#define BUFFER_CHECK(bp) do {} while(0) -#endif - -struct pvr2_stream { - /* Buffers queued for reading */ - struct list_head queued_list; - unsigned int q_count; - unsigned int q_bcount; - /* Buffers with retrieved data */ - struct list_head ready_list; - unsigned int r_count; - unsigned int r_bcount; - /* Buffers available for use */ - struct list_head idle_list; - unsigned int i_count; - unsigned int i_bcount; - /* Pointers to all buffers */ - struct pvr2_buffer **buffers; - /* Array size of buffers */ - unsigned int buffer_slot_count; - /* Total buffers actually in circulation */ - unsigned int buffer_total_count; - /* Designed number of buffers to be in circulation */ - unsigned int buffer_target_count; - /* Executed when ready list become non-empty */ - pvr2_stream_callback callback_func; - void *callback_data; - /* Context for transfer endpoint */ - struct usb_device *dev; - int endpoint; - /* Overhead for mutex enforcement */ - spinlock_t list_lock; - struct mutex mutex; - /* Tracking state for tolerating errors */ - unsigned int fail_count; - unsigned int fail_tolerance; - - unsigned int buffers_processed; - unsigned int buffers_failed; - unsigned int bytes_processed; -}; - -struct pvr2_buffer { - int id; - int signature; - enum pvr2_buffer_state state; - void *ptr; /* Pointer to storage area */ - unsigned int max_count; /* Size of storage area */ - unsigned int used_count; /* Amount of valid data in storage area */ - int status; /* Transfer result status */ - struct pvr2_stream *stream; - struct list_head list_overhead; - struct urb *purb; -}; - -static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state st) -{ - switch (st) { - case pvr2_buffer_state_none: return "none"; - case pvr2_buffer_state_idle: return "idle"; - case pvr2_buffer_state_queued: return "queued"; - case pvr2_buffer_state_ready: return "ready"; - } - return "unknown"; -} - -#ifdef SANITY_CHECK_BUFFERS -static void pvr2_buffer_describe(struct pvr2_buffer *bp,const char *msg) -{ - pvr2_trace(PVR2_TRACE_INFO, - "buffer%s%s %p state=%s id=%d status=%d" - " stream=%p purb=%p sig=0x%x", - (msg ? " " : ""), - (msg ? msg : ""), - bp, - (bp ? pvr2_buffer_state_decode(bp->state) : "(invalid)"), - (bp ? bp->id : 0), - (bp ? bp->status : 0), - (bp ? bp->stream : NULL), - (bp ? bp->purb : NULL), - (bp ? bp->signature : 0)); -} -#endif /* SANITY_CHECK_BUFFERS */ - -static void pvr2_buffer_remove(struct pvr2_buffer *bp) -{ - unsigned int *cnt; - unsigned int *bcnt; - unsigned int ccnt; - struct pvr2_stream *sp = bp->stream; - switch (bp->state) { - case pvr2_buffer_state_idle: - cnt = &sp->i_count; - bcnt = &sp->i_bcount; - ccnt = bp->max_count; - break; - case pvr2_buffer_state_queued: - cnt = &sp->q_count; - bcnt = &sp->q_bcount; - ccnt = bp->max_count; - break; - case pvr2_buffer_state_ready: - cnt = &sp->r_count; - bcnt = &sp->r_bcount; - ccnt = bp->used_count; - break; - default: - return; - } - list_del_init(&bp->list_overhead); - (*cnt)--; - (*bcnt) -= ccnt; - pvr2_trace(PVR2_TRACE_BUF_FLOW, - "/*---TRACE_FLOW---*/" - " bufferPool %8s dec cap=%07d cnt=%02d", - pvr2_buffer_state_decode(bp->state),*bcnt,*cnt); - bp->state = pvr2_buffer_state_none; -} - -static void pvr2_buffer_set_none(struct pvr2_buffer *bp) -{ - unsigned long irq_flags; - struct pvr2_stream *sp; - BUFFER_CHECK(bp); - sp = bp->stream; - pvr2_trace(PVR2_TRACE_BUF_FLOW, - "/*---TRACE_FLOW---*/ bufferState %p %6s --> %6s", - bp, - pvr2_buffer_state_decode(bp->state), - pvr2_buffer_state_decode(pvr2_buffer_state_none)); - spin_lock_irqsave(&sp->list_lock,irq_flags); - pvr2_buffer_remove(bp); - spin_unlock_irqrestore(&sp->list_lock,irq_flags); -} - -static int pvr2_buffer_set_ready(struct pvr2_buffer *bp) -{ - int fl; - unsigned long irq_flags; - struct pvr2_stream *sp; - BUFFER_CHECK(bp); - sp = bp->stream; - pvr2_trace(PVR2_TRACE_BUF_FLOW, - "/*---TRACE_FLOW---*/ bufferState %p %6s --> %6s", - bp, - pvr2_buffer_state_decode(bp->state), - pvr2_buffer_state_decode(pvr2_buffer_state_ready)); - spin_lock_irqsave(&sp->list_lock,irq_flags); - fl = (sp->r_count == 0); - pvr2_buffer_remove(bp); - list_add_tail(&bp->list_overhead,&sp->ready_list); - bp->state = pvr2_buffer_state_ready; - (sp->r_count)++; - sp->r_bcount += bp->used_count; - pvr2_trace(PVR2_TRACE_BUF_FLOW, - "/*---TRACE_FLOW---*/" - " bufferPool %8s inc cap=%07d cnt=%02d", - pvr2_buffer_state_decode(bp->state), - sp->r_bcount,sp->r_count); - spin_unlock_irqrestore(&sp->list_lock,irq_flags); - return fl; -} - -static void pvr2_buffer_set_idle(struct pvr2_buffer *bp) -{ - unsigned long irq_flags; - struct pvr2_stream *sp; - BUFFER_CHECK(bp); - sp = bp->stream; - pvr2_trace(PVR2_TRACE_BUF_FLOW, - "/*---TRACE_FLOW---*/ bufferState %p %6s --> %6s", - bp, - pvr2_buffer_state_decode(bp->state), - pvr2_buffer_state_decode(pvr2_buffer_state_idle)); - spin_lock_irqsave(&sp->list_lock,irq_flags); - pvr2_buffer_remove(bp); - list_add_tail(&bp->list_overhead,&sp->idle_list); - bp->state = pvr2_buffer_state_idle; - (sp->i_count)++; - sp->i_bcount += bp->max_count; - pvr2_trace(PVR2_TRACE_BUF_FLOW, - "/*---TRACE_FLOW---*/" - " bufferPool %8s inc cap=%07d cnt=%02d", - pvr2_buffer_state_decode(bp->state), - sp->i_bcount,sp->i_count); - spin_unlock_irqrestore(&sp->list_lock,irq_flags); -} - -static void pvr2_buffer_set_queued(struct pvr2_buffer *bp) -{ - unsigned long irq_flags; - struct pvr2_stream *sp; - BUFFER_CHECK(bp); - sp = bp->stream; - pvr2_trace(PVR2_TRACE_BUF_FLOW, - "/*---TRACE_FLOW---*/ bufferState %p %6s --> %6s", - bp, - pvr2_buffer_state_decode(bp->state), - pvr2_buffer_state_decode(pvr2_buffer_state_queued)); - spin_lock_irqsave(&sp->list_lock,irq_flags); - pvr2_buffer_remove(bp); - list_add_tail(&bp->list_overhead,&sp->queued_list); - bp->state = pvr2_buffer_state_queued; - (sp->q_count)++; - sp->q_bcount += bp->max_count; - pvr2_trace(PVR2_TRACE_BUF_FLOW, - "/*---TRACE_FLOW---*/" - " bufferPool %8s inc cap=%07d cnt=%02d", - pvr2_buffer_state_decode(bp->state), - sp->q_bcount,sp->q_count); - spin_unlock_irqrestore(&sp->list_lock,irq_flags); -} - -static void pvr2_buffer_wipe(struct pvr2_buffer *bp) -{ - if (bp->state == pvr2_buffer_state_queued) { - usb_kill_urb(bp->purb); - } -} - -static int pvr2_buffer_init(struct pvr2_buffer *bp, - struct pvr2_stream *sp, - unsigned int id) -{ - memset(bp,0,sizeof(*bp)); - bp->signature = BUFFER_SIG; - bp->id = id; - pvr2_trace(PVR2_TRACE_BUF_POOL, - "/*---TRACE_FLOW---*/ bufferInit %p stream=%p",bp,sp); - bp->stream = sp; - bp->state = pvr2_buffer_state_none; - INIT_LIST_HEAD(&bp->list_overhead); - bp->purb = usb_alloc_urb(0,GFP_KERNEL); - if (! bp->purb) return -ENOMEM; -#ifdef SANITY_CHECK_BUFFERS - pvr2_buffer_describe(bp,"create"); -#endif - return 0; -} - -static void pvr2_buffer_done(struct pvr2_buffer *bp) -{ -#ifdef SANITY_CHECK_BUFFERS - pvr2_buffer_describe(bp,"delete"); -#endif - pvr2_buffer_wipe(bp); - pvr2_buffer_set_none(bp); - bp->signature = 0; - bp->stream = NULL; - usb_free_urb(bp->purb); - pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/" - " bufferDone %p",bp); -} - -static int pvr2_stream_buffer_count(struct pvr2_stream *sp,unsigned int cnt) -{ - int ret; - unsigned int scnt; - - /* Allocate buffers pointer array in multiples of 32 entries */ - if (cnt == sp->buffer_total_count) return 0; - - pvr2_trace(PVR2_TRACE_BUF_POOL, - "/*---TRACE_FLOW---*/ poolResize " - " stream=%p cur=%d adj=%+d", - sp, - sp->buffer_total_count, - cnt-sp->buffer_total_count); - - scnt = cnt & ~0x1f; - if (cnt > scnt) scnt += 0x20; - - if (cnt > sp->buffer_total_count) { - if (scnt > sp->buffer_slot_count) { - struct pvr2_buffer **nb; - nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL); - if (!nb) return -ENOMEM; - if (sp->buffer_slot_count) { - memcpy(nb,sp->buffers, - sp->buffer_slot_count * sizeof(*nb)); - kfree(sp->buffers); - } - sp->buffers = nb; - sp->buffer_slot_count = scnt; - } - while (sp->buffer_total_count < cnt) { - struct pvr2_buffer *bp; - bp = kmalloc(sizeof(*bp),GFP_KERNEL); - if (!bp) return -ENOMEM; - ret = pvr2_buffer_init(bp,sp,sp->buffer_total_count); - if (ret) { - kfree(bp); - return -ENOMEM; - } - sp->buffers[sp->buffer_total_count] = bp; - (sp->buffer_total_count)++; - pvr2_buffer_set_idle(bp); - } - } else { - while (sp->buffer_total_count > cnt) { - struct pvr2_buffer *bp; - bp = sp->buffers[sp->buffer_total_count - 1]; - /* Paranoia */ - sp->buffers[sp->buffer_total_count - 1] = NULL; - (sp->buffer_total_count)--; - pvr2_buffer_done(bp); - kfree(bp); - } - if (scnt < sp->buffer_slot_count) { - struct pvr2_buffer **nb = NULL; - if (scnt) { - nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL); - if (!nb) return -ENOMEM; - memcpy(nb,sp->buffers,scnt * sizeof(*nb)); - } - kfree(sp->buffers); - sp->buffers = nb; - sp->buffer_slot_count = scnt; - } - } - return 0; -} - -static int pvr2_stream_achieve_buffer_count(struct pvr2_stream *sp) -{ - struct pvr2_buffer *bp; - unsigned int cnt; - - if (sp->buffer_total_count == sp->buffer_target_count) return 0; - - pvr2_trace(PVR2_TRACE_BUF_POOL, - "/*---TRACE_FLOW---*/" - " poolCheck stream=%p cur=%d tgt=%d", - sp,sp->buffer_total_count,sp->buffer_target_count); - - if (sp->buffer_total_count < sp->buffer_target_count) { - return pvr2_stream_buffer_count(sp,sp->buffer_target_count); - } - - cnt = 0; - while ((sp->buffer_total_count - cnt) > sp->buffer_target_count) { - bp = sp->buffers[sp->buffer_total_count - (cnt + 1)]; - if (bp->state != pvr2_buffer_state_idle) break; - cnt++; - } - if (cnt) { - pvr2_stream_buffer_count(sp,sp->buffer_total_count - cnt); - } - - return 0; -} - -static void pvr2_stream_internal_flush(struct pvr2_stream *sp) -{ - struct list_head *lp; - struct pvr2_buffer *bp1; - while ((lp = sp->queued_list.next) != &sp->queued_list) { - bp1 = list_entry(lp,struct pvr2_buffer,list_overhead); - pvr2_buffer_wipe(bp1); - /* At this point, we should be guaranteed that no - completion callback may happen on this buffer. But it's - possible that it might have completed after we noticed - it but before we wiped it. So double check its status - here first. */ - if (bp1->state != pvr2_buffer_state_queued) continue; - pvr2_buffer_set_idle(bp1); - } - if (sp->buffer_total_count != sp->buffer_target_count) { - pvr2_stream_achieve_buffer_count(sp); - } -} - -static void pvr2_stream_init(struct pvr2_stream *sp) -{ - spin_lock_init(&sp->list_lock); - mutex_init(&sp->mutex); - INIT_LIST_HEAD(&sp->queued_list); - INIT_LIST_HEAD(&sp->ready_list); - INIT_LIST_HEAD(&sp->idle_list); -} - -static void pvr2_stream_done(struct pvr2_stream *sp) -{ - mutex_lock(&sp->mutex); do { - pvr2_stream_internal_flush(sp); - pvr2_stream_buffer_count(sp,0); - } while (0); mutex_unlock(&sp->mutex); -} - -static void buffer_complete(struct urb *urb) -{ - struct pvr2_buffer *bp = urb->context; - struct pvr2_stream *sp; - unsigned long irq_flags; - BUFFER_CHECK(bp); - sp = bp->stream; - bp->used_count = 0; - bp->status = 0; - pvr2_trace(PVR2_TRACE_BUF_FLOW, - "/*---TRACE_FLOW---*/ bufferComplete %p stat=%d cnt=%d", - bp,urb->status,urb->actual_length); - spin_lock_irqsave(&sp->list_lock,irq_flags); - if ((!(urb->status)) || - (urb->status == -ENOENT) || - (urb->status == -ECONNRESET) || - (urb->status == -ESHUTDOWN)) { - (sp->buffers_processed)++; - sp->bytes_processed += urb->actual_length; - bp->used_count = urb->actual_length; - if (sp->fail_count) { - pvr2_trace(PVR2_TRACE_TOLERANCE, - "stream %p transfer ok" - " - fail count reset",sp); - sp->fail_count = 0; - } - } else if (sp->fail_count < sp->fail_tolerance) { - // We can tolerate this error, because we're below the - // threshold... - (sp->fail_count)++; - (sp->buffers_failed)++; - pvr2_trace(PVR2_TRACE_TOLERANCE, - "stream %p ignoring error %d" - " - fail count increased to %u", - sp,urb->status,sp->fail_count); - } else { - (sp->buffers_failed)++; - bp->status = urb->status; - } - spin_unlock_irqrestore(&sp->list_lock,irq_flags); - pvr2_buffer_set_ready(bp); - if (sp && sp->callback_func) { - sp->callback_func(sp->callback_data); - } -} - -struct pvr2_stream *pvr2_stream_create(void) -{ - struct pvr2_stream *sp; - sp = kzalloc(sizeof(*sp),GFP_KERNEL); - if (!sp) return sp; - pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_create: sp=%p",sp); - pvr2_stream_init(sp); - return sp; -} - -void pvr2_stream_destroy(struct pvr2_stream *sp) -{ - if (!sp) return; - pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_destroy: sp=%p",sp); - pvr2_stream_done(sp); - kfree(sp); -} - -void pvr2_stream_setup(struct pvr2_stream *sp, - struct usb_device *dev, - int endpoint, - unsigned int tolerance) -{ - mutex_lock(&sp->mutex); do { - pvr2_stream_internal_flush(sp); - sp->dev = dev; - sp->endpoint = endpoint; - sp->fail_tolerance = tolerance; - } while(0); mutex_unlock(&sp->mutex); -} - -void pvr2_stream_set_callback(struct pvr2_stream *sp, - pvr2_stream_callback func, - void *data) -{ - unsigned long irq_flags; - mutex_lock(&sp->mutex); do { - spin_lock_irqsave(&sp->list_lock,irq_flags); - sp->callback_data = data; - sp->callback_func = func; - spin_unlock_irqrestore(&sp->list_lock,irq_flags); - } while(0); mutex_unlock(&sp->mutex); -} - -void pvr2_stream_get_stats(struct pvr2_stream *sp, - struct pvr2_stream_stats *stats, - int zero_counts) -{ - unsigned long irq_flags; - spin_lock_irqsave(&sp->list_lock,irq_flags); - if (stats) { - stats->buffers_in_queue = sp->q_count; - stats->buffers_in_idle = sp->i_count; - stats->buffers_in_ready = sp->r_count; - stats->buffers_processed = sp->buffers_processed; - stats->buffers_failed = sp->buffers_failed; - stats->bytes_processed = sp->bytes_processed; - } - if (zero_counts) { - sp->buffers_processed = 0; - sp->buffers_failed = 0; - sp->bytes_processed = 0; - } - spin_unlock_irqrestore(&sp->list_lock,irq_flags); -} - -/* Query / set the nominal buffer count */ -int pvr2_stream_get_buffer_count(struct pvr2_stream *sp) -{ - return sp->buffer_target_count; -} - -int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt) -{ - int ret; - if (sp->buffer_target_count == cnt) return 0; - mutex_lock(&sp->mutex); do { - sp->buffer_target_count = cnt; - ret = pvr2_stream_achieve_buffer_count(sp); - } while(0); mutex_unlock(&sp->mutex); - return ret; -} - -struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *sp) -{ - struct list_head *lp = sp->idle_list.next; - if (lp == &sp->idle_list) return NULL; - return list_entry(lp,struct pvr2_buffer,list_overhead); -} - -struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *sp) -{ - struct list_head *lp = sp->ready_list.next; - if (lp == &sp->ready_list) return NULL; - return list_entry(lp,struct pvr2_buffer,list_overhead); -} - -struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id) -{ - if (id < 0) return NULL; - if (id >= sp->buffer_total_count) return NULL; - return sp->buffers[id]; -} - -int pvr2_stream_get_ready_count(struct pvr2_stream *sp) -{ - return sp->r_count; -} - -void pvr2_stream_kill(struct pvr2_stream *sp) -{ - struct pvr2_buffer *bp; - mutex_lock(&sp->mutex); do { - pvr2_stream_internal_flush(sp); - while ((bp = pvr2_stream_get_ready_buffer(sp)) != NULL) { - pvr2_buffer_set_idle(bp); - } - if (sp->buffer_total_count != sp->buffer_target_count) { - pvr2_stream_achieve_buffer_count(sp); - } - } while(0); mutex_unlock(&sp->mutex); -} - -int pvr2_buffer_queue(struct pvr2_buffer *bp) -{ -#undef SEED_BUFFER -#ifdef SEED_BUFFER - unsigned int idx; - unsigned int val; -#endif - int ret = 0; - struct pvr2_stream *sp; - if (!bp) return -EINVAL; - sp = bp->stream; - mutex_lock(&sp->mutex); do { - pvr2_buffer_wipe(bp); - if (!sp->dev) { - ret = -EIO; - break; - } - pvr2_buffer_set_queued(bp); -#ifdef SEED_BUFFER - for (idx = 0; idx < (bp->max_count) / 4; idx++) { - val = bp->id << 24; - val |= idx; - ((unsigned int *)(bp->ptr))[idx] = val; - } -#endif - bp->status = -EINPROGRESS; - usb_fill_bulk_urb(bp->purb, // struct urb *urb - sp->dev, // struct usb_device *dev - // endpoint (below) - usb_rcvbulkpipe(sp->dev,sp->endpoint), - bp->ptr, // void *transfer_buffer - bp->max_count, // int buffer_length - buffer_complete, - bp); - usb_submit_urb(bp->purb,GFP_KERNEL); - } while(0); mutex_unlock(&sp->mutex); - return ret; -} - -int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt) -{ - int ret = 0; - unsigned long irq_flags; - struct pvr2_stream *sp; - if (!bp) return -EINVAL; - sp = bp->stream; - mutex_lock(&sp->mutex); do { - spin_lock_irqsave(&sp->list_lock,irq_flags); - if (bp->state != pvr2_buffer_state_idle) { - ret = -EPERM; - } else { - bp->ptr = ptr; - bp->stream->i_bcount -= bp->max_count; - bp->max_count = cnt; - bp->stream->i_bcount += bp->max_count; - pvr2_trace(PVR2_TRACE_BUF_FLOW, - "/*---TRACE_FLOW---*/ bufferPool " - " %8s cap cap=%07d cnt=%02d", - pvr2_buffer_state_decode( - pvr2_buffer_state_idle), - bp->stream->i_bcount,bp->stream->i_count); - } - spin_unlock_irqrestore(&sp->list_lock,irq_flags); - } while(0); mutex_unlock(&sp->mutex); - return ret; -} - -unsigned int pvr2_buffer_get_count(struct pvr2_buffer *bp) -{ - return bp->used_count; -} - -int pvr2_buffer_get_status(struct pvr2_buffer *bp) -{ - return bp->status; -} - -int pvr2_buffer_get_id(struct pvr2_buffer *bp) -{ - return bp->id; -} - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.h b/drivers/media/video/pvrusb2/pvrusb2-io.h deleted file mode 100644 index afb7e87c0394..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-io.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __PVRUSB2_IO_H -#define __PVRUSB2_IO_H - -#include <linux/usb.h> -#include <linux/list.h> - -typedef void (*pvr2_stream_callback)(void *); - -enum pvr2_buffer_state { - pvr2_buffer_state_none = 0, // Not on any list - pvr2_buffer_state_idle = 1, // Buffer is ready to be used again - pvr2_buffer_state_queued = 2, // Buffer has been queued for filling - pvr2_buffer_state_ready = 3, // Buffer has data available -}; - -struct pvr2_stream; -struct pvr2_buffer; - -struct pvr2_stream_stats { - unsigned int buffers_in_queue; - unsigned int buffers_in_idle; - unsigned int buffers_in_ready; - unsigned int buffers_processed; - unsigned int buffers_failed; - unsigned int bytes_processed; -}; - -/* Initialize / tear down stream structure */ -struct pvr2_stream *pvr2_stream_create(void); -void pvr2_stream_destroy(struct pvr2_stream *); -void pvr2_stream_setup(struct pvr2_stream *, - struct usb_device *dev,int endpoint, - unsigned int tolerance); -void pvr2_stream_set_callback(struct pvr2_stream *, - pvr2_stream_callback func, - void *data); -void pvr2_stream_get_stats(struct pvr2_stream *, - struct pvr2_stream_stats *, - int zero_counts); - -/* Query / set the nominal buffer count */ -int pvr2_stream_get_buffer_count(struct pvr2_stream *); -int pvr2_stream_set_buffer_count(struct pvr2_stream *,unsigned int); - -/* Get a pointer to a buffer that is either idle, ready, or is specified - named. */ -struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *); -struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *); -struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id); - -/* Find out how many buffers are idle or ready */ -int pvr2_stream_get_ready_count(struct pvr2_stream *); - - -/* Kill all pending buffers and throw away any ready buffers as well */ -void pvr2_stream_kill(struct pvr2_stream *); - -/* Set up the actual storage for a buffer */ -int pvr2_buffer_set_buffer(struct pvr2_buffer *,void *ptr,unsigned int cnt); - -/* Find out size of data in the given ready buffer */ -unsigned int pvr2_buffer_get_count(struct pvr2_buffer *); - -/* Retrieve completion code for given ready buffer */ -int pvr2_buffer_get_status(struct pvr2_buffer *); - -/* Retrieve ID of given buffer */ -int pvr2_buffer_get_id(struct pvr2_buffer *); - -/* Start reading into given buffer (kill it if needed) */ -int pvr2_buffer_queue(struct pvr2_buffer *); - -#endif /* __PVRUSB2_IO_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/video/pvrusb2/pvrusb2-ioread.c deleted file mode 100644 index bba6115c9ae8..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-ioread.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "pvrusb2-ioread.h" -#include "pvrusb2-debug.h" -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/mutex.h> -#include <asm/uaccess.h> - -#define BUFFER_COUNT 32 -#define BUFFER_SIZE PAGE_ALIGN(0x4000) - -struct pvr2_ioread { - struct pvr2_stream *stream; - char *buffer_storage[BUFFER_COUNT]; - char *sync_key_ptr; - unsigned int sync_key_len; - unsigned int sync_buf_offs; - unsigned int sync_state; - unsigned int sync_trashed_count; - int enabled; // Streaming is on - int spigot_open; // OK to pass data to client - int stream_running; // Passing data to client now - - /* State relevant to current buffer being read */ - struct pvr2_buffer *c_buf; - char *c_data_ptr; - unsigned int c_data_len; - unsigned int c_data_offs; - struct mutex mutex; -}; - -static int pvr2_ioread_init(struct pvr2_ioread *cp) -{ - unsigned int idx; - - cp->stream = NULL; - mutex_init(&cp->mutex); - - for (idx = 0; idx < BUFFER_COUNT; idx++) { - cp->buffer_storage[idx] = kmalloc(BUFFER_SIZE,GFP_KERNEL); - if (!(cp->buffer_storage[idx])) break; - } - - if (idx < BUFFER_COUNT) { - // An allocation appears to have failed - for (idx = 0; idx < BUFFER_COUNT; idx++) { - if (!(cp->buffer_storage[idx])) continue; - kfree(cp->buffer_storage[idx]); - } - return -ENOMEM; - } - return 0; -} - -static void pvr2_ioread_done(struct pvr2_ioread *cp) -{ - unsigned int idx; - - pvr2_ioread_setup(cp,NULL); - for (idx = 0; idx < BUFFER_COUNT; idx++) { - if (!(cp->buffer_storage[idx])) continue; - kfree(cp->buffer_storage[idx]); - } -} - -struct pvr2_ioread *pvr2_ioread_create(void) -{ - struct pvr2_ioread *cp; - cp = kzalloc(sizeof(*cp),GFP_KERNEL); - if (!cp) return NULL; - pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_create id=%p",cp); - if (pvr2_ioread_init(cp) < 0) { - kfree(cp); - return NULL; - } - return cp; -} - -void pvr2_ioread_destroy(struct pvr2_ioread *cp) -{ - if (!cp) return; - pvr2_ioread_done(cp); - pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_destroy id=%p",cp); - if (cp->sync_key_ptr) { - kfree(cp->sync_key_ptr); - cp->sync_key_ptr = NULL; - } - kfree(cp); -} - -void pvr2_ioread_set_sync_key(struct pvr2_ioread *cp, - const char *sync_key_ptr, - unsigned int sync_key_len) -{ - if (!cp) return; - - if (!sync_key_ptr) sync_key_len = 0; - if ((sync_key_len == cp->sync_key_len) && - ((!sync_key_len) || - (!memcmp(sync_key_ptr,cp->sync_key_ptr,sync_key_len)))) return; - - if (sync_key_len != cp->sync_key_len) { - if (cp->sync_key_ptr) { - kfree(cp->sync_key_ptr); - cp->sync_key_ptr = NULL; - } - cp->sync_key_len = 0; - if (sync_key_len) { - cp->sync_key_ptr = kmalloc(sync_key_len,GFP_KERNEL); - if (cp->sync_key_ptr) { - cp->sync_key_len = sync_key_len; - } - } - } - if (!cp->sync_key_len) return; - memcpy(cp->sync_key_ptr,sync_key_ptr,cp->sync_key_len); -} - -static void pvr2_ioread_stop(struct pvr2_ioread *cp) -{ - if (!(cp->enabled)) return; - pvr2_trace(PVR2_TRACE_START_STOP, - "/*---TRACE_READ---*/ pvr2_ioread_stop id=%p",cp); - pvr2_stream_kill(cp->stream); - cp->c_buf = NULL; - cp->c_data_ptr = NULL; - cp->c_data_len = 0; - cp->c_data_offs = 0; - cp->enabled = 0; - cp->stream_running = 0; - cp->spigot_open = 0; - if (cp->sync_state) { - pvr2_trace(PVR2_TRACE_DATA_FLOW, - "/*---TRACE_READ---*/ sync_state <== 0"); - cp->sync_state = 0; - } -} - -static int pvr2_ioread_start(struct pvr2_ioread *cp) -{ - int stat; - struct pvr2_buffer *bp; - if (cp->enabled) return 0; - if (!(cp->stream)) return 0; - pvr2_trace(PVR2_TRACE_START_STOP, - "/*---TRACE_READ---*/ pvr2_ioread_start id=%p",cp); - while ((bp = pvr2_stream_get_idle_buffer(cp->stream)) != NULL) { - stat = pvr2_buffer_queue(bp); - if (stat < 0) { - pvr2_trace(PVR2_TRACE_DATA_FLOW, - "/*---TRACE_READ---*/" - " pvr2_ioread_start id=%p" - " error=%d", - cp,stat); - pvr2_ioread_stop(cp); - return stat; - } - } - cp->enabled = !0; - cp->c_buf = NULL; - cp->c_data_ptr = NULL; - cp->c_data_len = 0; - cp->c_data_offs = 0; - cp->stream_running = 0; - if (cp->sync_key_len) { - pvr2_trace(PVR2_TRACE_DATA_FLOW, - "/*---TRACE_READ---*/ sync_state <== 1"); - cp->sync_state = 1; - cp->sync_trashed_count = 0; - cp->sync_buf_offs = 0; - } - cp->spigot_open = 0; - return 0; -} - -struct pvr2_stream *pvr2_ioread_get_stream(struct pvr2_ioread *cp) -{ - return cp->stream; -} - -int pvr2_ioread_setup(struct pvr2_ioread *cp,struct pvr2_stream *sp) -{ - int ret; - unsigned int idx; - struct pvr2_buffer *bp; - - mutex_lock(&cp->mutex); do { - if (cp->stream) { - pvr2_trace(PVR2_TRACE_START_STOP, - "/*---TRACE_READ---*/" - " pvr2_ioread_setup (tear-down) id=%p",cp); - pvr2_ioread_stop(cp); - pvr2_stream_kill(cp->stream); - if (pvr2_stream_get_buffer_count(cp->stream)) { - pvr2_stream_set_buffer_count(cp->stream,0); - } - cp->stream = NULL; - } - if (sp) { - pvr2_trace(PVR2_TRACE_START_STOP, - "/*---TRACE_READ---*/" - " pvr2_ioread_setup (setup) id=%p",cp); - pvr2_stream_kill(sp); - ret = pvr2_stream_set_buffer_count(sp,BUFFER_COUNT); - if (ret < 0) { - mutex_unlock(&cp->mutex); - return ret; - } - for (idx = 0; idx < BUFFER_COUNT; idx++) { - bp = pvr2_stream_get_buffer(sp,idx); - pvr2_buffer_set_buffer(bp, - cp->buffer_storage[idx], - BUFFER_SIZE); - } - cp->stream = sp; - } - } while (0); mutex_unlock(&cp->mutex); - - return 0; -} - -int pvr2_ioread_set_enabled(struct pvr2_ioread *cp,int fl) -{ - int ret = 0; - if ((!fl) == (!(cp->enabled))) return ret; - - mutex_lock(&cp->mutex); do { - if (fl) { - ret = pvr2_ioread_start(cp); - } else { - pvr2_ioread_stop(cp); - } - } while (0); mutex_unlock(&cp->mutex); - return ret; -} - -static int pvr2_ioread_get_buffer(struct pvr2_ioread *cp) -{ - int stat; - - while (cp->c_data_len <= cp->c_data_offs) { - if (cp->c_buf) { - // Flush out current buffer first. - stat = pvr2_buffer_queue(cp->c_buf); - if (stat < 0) { - // Streaming error... - pvr2_trace(PVR2_TRACE_DATA_FLOW, - "/*---TRACE_READ---*/" - " pvr2_ioread_read id=%p" - " queue_error=%d", - cp,stat); - pvr2_ioread_stop(cp); - return 0; - } - cp->c_buf = NULL; - cp->c_data_ptr = NULL; - cp->c_data_len = 0; - cp->c_data_offs = 0; - } - // Now get a freshly filled buffer. - cp->c_buf = pvr2_stream_get_ready_buffer(cp->stream); - if (!cp->c_buf) break; // Nothing ready; done. - cp->c_data_len = pvr2_buffer_get_count(cp->c_buf); - if (!cp->c_data_len) { - // Nothing transferred. Was there an error? - stat = pvr2_buffer_get_status(cp->c_buf); - if (stat < 0) { - // Streaming error... - pvr2_trace(PVR2_TRACE_DATA_FLOW, - "/*---TRACE_READ---*/" - " pvr2_ioread_read id=%p" - " buffer_error=%d", - cp,stat); - pvr2_ioread_stop(cp); - // Give up. - return 0; - } - // Start over... - continue; - } - cp->c_data_offs = 0; - cp->c_data_ptr = cp->buffer_storage[ - pvr2_buffer_get_id(cp->c_buf)]; - } - return !0; -} - -static void pvr2_ioread_filter(struct pvr2_ioread *cp) -{ - unsigned int idx; - if (!cp->enabled) return; - if (cp->sync_state != 1) return; - - // Search the stream for our synchronization key. This is made - // complicated by the fact that in order to be honest with - // ourselves here we must search across buffer boundaries... - mutex_lock(&cp->mutex); while (1) { - // Ensure we have a buffer - if (!pvr2_ioread_get_buffer(cp)) break; - if (!cp->c_data_len) break; - - // Now walk the buffer contents until we match the key or - // run out of buffer data. - for (idx = cp->c_data_offs; idx < cp->c_data_len; idx++) { - if (cp->sync_buf_offs >= cp->sync_key_len) break; - if (cp->c_data_ptr[idx] == - cp->sync_key_ptr[cp->sync_buf_offs]) { - // Found the next key byte - (cp->sync_buf_offs)++; - } else { - // Whoops, mismatched. Start key over... - cp->sync_buf_offs = 0; - } - } - - // Consume what we've walked through - cp->c_data_offs += idx; - cp->sync_trashed_count += idx; - - // If we've found the key, then update state and get out. - if (cp->sync_buf_offs >= cp->sync_key_len) { - cp->sync_trashed_count -= cp->sync_key_len; - pvr2_trace(PVR2_TRACE_DATA_FLOW, - "/*---TRACE_READ---*/" - " sync_state <== 2 (skipped %u bytes)", - cp->sync_trashed_count); - cp->sync_state = 2; - cp->sync_buf_offs = 0; - break; - } - - if (cp->c_data_offs < cp->c_data_len) { - // Sanity check - should NEVER get here - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "ERROR: pvr2_ioread filter sync problem" - " len=%u offs=%u", - cp->c_data_len,cp->c_data_offs); - // Get out so we don't get stuck in an infinite - // loop. - break; - } - - continue; // (for clarity) - } mutex_unlock(&cp->mutex); -} - -int pvr2_ioread_avail(struct pvr2_ioread *cp) -{ - int ret; - if (!(cp->enabled)) { - // Stream is not enabled; so this is an I/O error - return -EIO; - } - - if (cp->sync_state == 1) { - pvr2_ioread_filter(cp); - if (cp->sync_state == 1) return -EAGAIN; - } - - ret = 0; - if (cp->stream_running) { - if (!pvr2_stream_get_ready_count(cp->stream)) { - // No data available at all right now. - ret = -EAGAIN; - } - } else { - if (pvr2_stream_get_ready_count(cp->stream) < BUFFER_COUNT/2) { - // Haven't buffered up enough yet; try again later - ret = -EAGAIN; - } - } - - if ((!(cp->spigot_open)) != (!(ret == 0))) { - cp->spigot_open = (ret == 0); - pvr2_trace(PVR2_TRACE_DATA_FLOW, - "/*---TRACE_READ---*/ data is %s", - cp->spigot_open ? "available" : "pending"); - } - - return ret; -} - -int pvr2_ioread_read(struct pvr2_ioread *cp,void __user *buf,unsigned int cnt) -{ - unsigned int copied_cnt; - unsigned int bcnt; - const char *src; - int stat; - int ret = 0; - unsigned int req_cnt = cnt; - - if (!cnt) { - pvr2_trace(PVR2_TRACE_TRAP, - "/*---TRACE_READ---*/ pvr2_ioread_read id=%p" - " ZERO Request? Returning zero.",cp); - return 0; - } - - stat = pvr2_ioread_avail(cp); - if (stat < 0) return stat; - - cp->stream_running = !0; - - mutex_lock(&cp->mutex); do { - - // Suck data out of the buffers and copy to the user - copied_cnt = 0; - if (!buf) cnt = 0; - while (1) { - if (!pvr2_ioread_get_buffer(cp)) { - ret = -EIO; - break; - } - - if (!cnt) break; - - if (cp->sync_state == 2) { - // We're repeating the sync key data into - // the stream. - src = cp->sync_key_ptr + cp->sync_buf_offs; - bcnt = cp->sync_key_len - cp->sync_buf_offs; - } else { - // Normal buffer copy - src = cp->c_data_ptr + cp->c_data_offs; - bcnt = cp->c_data_len - cp->c_data_offs; - } - - if (!bcnt) break; - - // Don't run past user's buffer - if (bcnt > cnt) bcnt = cnt; - - if (copy_to_user(buf,src,bcnt)) { - // User supplied a bad pointer? - // Give up - this *will* cause data - // to be lost. - ret = -EFAULT; - break; - } - cnt -= bcnt; - buf += bcnt; - copied_cnt += bcnt; - - if (cp->sync_state == 2) { - // Update offset inside sync key that we're - // repeating back out. - cp->sync_buf_offs += bcnt; - if (cp->sync_buf_offs >= cp->sync_key_len) { - // Consumed entire key; switch mode - // to normal. - pvr2_trace(PVR2_TRACE_DATA_FLOW, - "/*---TRACE_READ---*/" - " sync_state <== 0"); - cp->sync_state = 0; - } - } else { - // Update buffer offset. - cp->c_data_offs += bcnt; - } - } - - } while (0); mutex_unlock(&cp->mutex); - - if (!ret) { - if (copied_cnt) { - // If anything was copied, return that count - ret = copied_cnt; - } else { - // Nothing copied; suggest to caller that another - // attempt should be tried again later - ret = -EAGAIN; - } - } - - pvr2_trace(PVR2_TRACE_DATA_FLOW, - "/*---TRACE_READ---*/ pvr2_ioread_read" - " id=%p request=%d result=%d", - cp,req_cnt,ret); - return ret; -} - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.h b/drivers/media/video/pvrusb2/pvrusb2-ioread.h deleted file mode 100644 index 100e0780e1aa..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-ioread.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __PVRUSB2_IOREAD_H -#define __PVRUSB2_IOREAD_H - -#include "pvrusb2-io.h" - -struct pvr2_ioread; - -struct pvr2_ioread *pvr2_ioread_create(void); -void pvr2_ioread_destroy(struct pvr2_ioread *); -int pvr2_ioread_setup(struct pvr2_ioread *,struct pvr2_stream *); -struct pvr2_stream *pvr2_ioread_get_stream(struct pvr2_ioread *); -void pvr2_ioread_set_sync_key(struct pvr2_ioread *, - const char *sync_key_ptr, - unsigned int sync_key_len); -int pvr2_ioread_set_enabled(struct pvr2_ioread *,int fl); -int pvr2_ioread_read(struct pvr2_ioread *,void __user *buf,unsigned int cnt); -int pvr2_ioread_avail(struct pvr2_ioread *); - -#endif /* __PVRUSB2_IOREAD_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c deleted file mode 100644 index c1d9bb61cd77..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-main.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/usb.h> -#include <linux/videodev2.h> - -#include "pvrusb2-hdw.h" -#include "pvrusb2-devattr.h" -#include "pvrusb2-context.h" -#include "pvrusb2-debug.h" -#include "pvrusb2-v4l2.h" -#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS -#include "pvrusb2-sysfs.h" -#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ - -#define DRIVER_AUTHOR "Mike Isely <isely@pobox.com>" -#define DRIVER_DESC "Hauppauge WinTV-PVR-USB2 MPEG2 Encoder/Tuner" -#define DRIVER_VERSION "V4L in-tree version" - -#define DEFAULT_DEBUG_MASK (PVR2_TRACE_ERROR_LEGS| \ - PVR2_TRACE_INFO| \ - PVR2_TRACE_STD| \ - PVR2_TRACE_TOLERANCE| \ - PVR2_TRACE_TRAP| \ - 0) - -int pvrusb2_debug = DEFAULT_DEBUG_MASK; - -module_param_named(debug,pvrusb2_debug,int,S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(debug, "Debug trace mask"); - -#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS -static struct pvr2_sysfs_class *class_ptr = NULL; -#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ - -static void pvr_setup_attach(struct pvr2_context *pvr) -{ - /* Create association with v4l layer */ - pvr2_v4l2_create(pvr); -#ifdef CONFIG_VIDEO_PVRUSB2_DVB - /* Create association with dvb layer */ - pvr2_dvb_create(pvr); -#endif -#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS - pvr2_sysfs_create(pvr,class_ptr); -#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ -} - -static int pvr_probe(struct usb_interface *intf, - const struct usb_device_id *devid) -{ - struct pvr2_context *pvr; - - /* Create underlying hardware interface */ - pvr = pvr2_context_create(intf,devid,pvr_setup_attach); - if (!pvr) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "Failed to create hdw handler"); - return -ENOMEM; - } - - pvr2_trace(PVR2_TRACE_INIT,"pvr_probe(pvr=%p)",pvr); - - usb_set_intfdata(intf, pvr); - - return 0; -} - -/* - * pvr_disconnect() - * - */ -static void pvr_disconnect(struct usb_interface *intf) -{ - struct pvr2_context *pvr = usb_get_intfdata(intf); - - pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) BEGIN",pvr); - - usb_set_intfdata (intf, NULL); - pvr2_context_disconnect(pvr); - - pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) DONE",pvr); - -} - -static struct usb_driver pvr_driver = { - .name = "pvrusb2", - .id_table = pvr2_device_table, - .probe = pvr_probe, - .disconnect = pvr_disconnect -}; - -/* - * pvr_init() / pvr_exit() - * - * This code is run to initialize/exit the driver. - * - */ -static int __init pvr_init(void) -{ - int ret; - - pvr2_trace(PVR2_TRACE_INIT,"pvr_init"); - - ret = pvr2_context_global_init(); - if (ret != 0) { - pvr2_trace(PVR2_TRACE_INIT,"pvr_init failure code=%d",ret); - return ret; - } - -#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS - class_ptr = pvr2_sysfs_class_create(); -#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ - - ret = usb_register(&pvr_driver); - - if (ret == 0) - printk(KERN_INFO "pvrusb2: " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - if (pvrusb2_debug) - printk(KERN_INFO "pvrusb2: Debug mask is %d (0x%x)\n", - pvrusb2_debug,pvrusb2_debug); - - pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete"); - - return ret; -} - -static void __exit pvr_exit(void) -{ - pvr2_trace(PVR2_TRACE_INIT,"pvr_exit"); - - usb_deregister(&pvr_driver); - - pvr2_context_global_done(); - -#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS - pvr2_sysfs_class_destroy(class_ptr); -#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ - - pvr2_trace(PVR2_TRACE_INIT,"pvr_exit complete"); -} - -module_init(pvr_init); -module_exit(pvr_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -MODULE_VERSION("0.9.1"); - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.c b/drivers/media/video/pvrusb2/pvrusb2-std.c deleted file mode 100644 index 453627b07833..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-std.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "pvrusb2-std.h" -#include "pvrusb2-debug.h" -#include <asm/string.h> -#include <linux/slab.h> - -struct std_name { - const char *name; - v4l2_std_id id; -}; - - -#define CSTD_PAL \ - (V4L2_STD_PAL_B| \ - V4L2_STD_PAL_B1| \ - V4L2_STD_PAL_G| \ - V4L2_STD_PAL_H| \ - V4L2_STD_PAL_I| \ - V4L2_STD_PAL_D| \ - V4L2_STD_PAL_D1| \ - V4L2_STD_PAL_K| \ - V4L2_STD_PAL_M| \ - V4L2_STD_PAL_N| \ - V4L2_STD_PAL_Nc| \ - V4L2_STD_PAL_60) - -#define CSTD_NTSC \ - (V4L2_STD_NTSC_M| \ - V4L2_STD_NTSC_M_JP| \ - V4L2_STD_NTSC_M_KR| \ - V4L2_STD_NTSC_443) - -#define CSTD_ATSC \ - (V4L2_STD_ATSC_8_VSB| \ - V4L2_STD_ATSC_16_VSB) - -#define CSTD_SECAM \ - (V4L2_STD_SECAM_B| \ - V4L2_STD_SECAM_D| \ - V4L2_STD_SECAM_G| \ - V4L2_STD_SECAM_H| \ - V4L2_STD_SECAM_K| \ - V4L2_STD_SECAM_K1| \ - V4L2_STD_SECAM_L| \ - V4L2_STD_SECAM_LC) - -#define TSTD_B (V4L2_STD_PAL_B|V4L2_STD_SECAM_B) -#define TSTD_B1 (V4L2_STD_PAL_B1) -#define TSTD_D (V4L2_STD_PAL_D|V4L2_STD_SECAM_D) -#define TSTD_D1 (V4L2_STD_PAL_D1) -#define TSTD_G (V4L2_STD_PAL_G|V4L2_STD_SECAM_G) -#define TSTD_H (V4L2_STD_PAL_H|V4L2_STD_SECAM_H) -#define TSTD_I (V4L2_STD_PAL_I) -#define TSTD_K (V4L2_STD_PAL_K|V4L2_STD_SECAM_K) -#define TSTD_K1 (V4L2_STD_SECAM_K1) -#define TSTD_L (V4L2_STD_SECAM_L) -#define TSTD_M (V4L2_STD_PAL_M|V4L2_STD_NTSC_M) -#define TSTD_N (V4L2_STD_PAL_N) -#define TSTD_Nc (V4L2_STD_PAL_Nc) -#define TSTD_60 (V4L2_STD_PAL_60) - -#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_ATSC|CSTD_SECAM) - -/* Mapping of standard bits to color system */ -static const struct std_name std_groups[] = { - {"PAL",CSTD_PAL}, - {"NTSC",CSTD_NTSC}, - {"SECAM",CSTD_SECAM}, - {"ATSC",CSTD_ATSC}, -}; - -/* Mapping of standard bits to modulation system */ -static const struct std_name std_items[] = { - {"B",TSTD_B}, - {"B1",TSTD_B1}, - {"D",TSTD_D}, - {"D1",TSTD_D1}, - {"G",TSTD_G}, - {"H",TSTD_H}, - {"I",TSTD_I}, - {"K",TSTD_K}, - {"K1",TSTD_K1}, - {"L",TSTD_L}, - {"LC",V4L2_STD_SECAM_LC}, - {"M",TSTD_M}, - {"Mj",V4L2_STD_NTSC_M_JP}, - {"443",V4L2_STD_NTSC_443}, - {"Mk",V4L2_STD_NTSC_M_KR}, - {"N",TSTD_N}, - {"Nc",TSTD_Nc}, - {"60",TSTD_60}, - {"8VSB",V4L2_STD_ATSC_8_VSB}, - {"16VSB",V4L2_STD_ATSC_16_VSB}, -}; - - -// Search an array of std_name structures and return a pointer to the -// element with the matching name. -static const struct std_name *find_std_name(const struct std_name *arrPtr, - unsigned int arrSize, - const char *bufPtr, - unsigned int bufSize) -{ - unsigned int idx; - const struct std_name *p; - for (idx = 0; idx < arrSize; idx++) { - p = arrPtr + idx; - if (strlen(p->name) != bufSize) continue; - if (!memcmp(bufPtr,p->name,bufSize)) return p; - } - return NULL; -} - - -int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr, - unsigned int bufSize) -{ - v4l2_std_id id = 0; - v4l2_std_id cmsk = 0; - v4l2_std_id t; - int mMode = 0; - unsigned int cnt; - char ch; - const struct std_name *sp; - - while (bufSize) { - if (!mMode) { - cnt = 0; - while ((cnt < bufSize) && (bufPtr[cnt] != '-')) cnt++; - if (cnt >= bufSize) return 0; // No more characters - sp = find_std_name(std_groups, ARRAY_SIZE(std_groups), - bufPtr,cnt); - if (!sp) return 0; // Illegal color system name - cnt++; - bufPtr += cnt; - bufSize -= cnt; - mMode = !0; - cmsk = sp->id; - continue; - } - cnt = 0; - while (cnt < bufSize) { - ch = bufPtr[cnt]; - if (ch == ';') { - mMode = 0; - break; - } - if (ch == '/') break; - cnt++; - } - sp = find_std_name(std_items, ARRAY_SIZE(std_items), - bufPtr,cnt); - if (!sp) return 0; // Illegal modulation system ID - t = sp->id & cmsk; - if (!t) return 0; // Specific color + modulation system illegal - id |= t; - if (cnt < bufSize) cnt++; - bufPtr += cnt; - bufSize -= cnt; - } - - if (idPtr) *idPtr = id; - return !0; -} - - -unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize, - v4l2_std_id id) -{ - unsigned int idx1,idx2; - const struct std_name *ip,*gp; - int gfl,cfl; - unsigned int c1,c2; - cfl = 0; - c1 = 0; - for (idx1 = 0; idx1 < ARRAY_SIZE(std_groups); idx1++) { - gp = std_groups + idx1; - gfl = 0; - for (idx2 = 0; idx2 < ARRAY_SIZE(std_items); idx2++) { - ip = std_items + idx2; - if (!(gp->id & ip->id & id)) continue; - if (!gfl) { - if (cfl) { - c2 = scnprintf(bufPtr,bufSize,";"); - c1 += c2; - bufSize -= c2; - bufPtr += c2; - } - cfl = !0; - c2 = scnprintf(bufPtr,bufSize, - "%s-",gp->name); - gfl = !0; - } else { - c2 = scnprintf(bufPtr,bufSize,"/"); - } - c1 += c2; - bufSize -= c2; - bufPtr += c2; - c2 = scnprintf(bufPtr,bufSize, - ip->name); - c1 += c2; - bufSize -= c2; - bufPtr += c2; - } - } - return c1; -} - - -// Template data for possible enumerated video standards. Here we group -// standards which share common frame rates and resolution. -static struct v4l2_standard generic_standards[] = { - { - .id = (TSTD_B|TSTD_B1| - TSTD_D|TSTD_D1| - TSTD_G| - TSTD_H| - TSTD_I| - TSTD_K|TSTD_K1| - TSTD_L| - V4L2_STD_SECAM_LC | - TSTD_N|TSTD_Nc), - .frameperiod = - { - .numerator = 1, - .denominator= 25 - }, - .framelines = 625, - .reserved = {0,0,0,0} - }, { - .id = (TSTD_M| - V4L2_STD_NTSC_M_JP| - V4L2_STD_NTSC_M_KR), - .frameperiod = - { - .numerator = 1001, - .denominator= 30000 - }, - .framelines = 525, - .reserved = {0,0,0,0} - }, { // This is a total wild guess - .id = (TSTD_60), - .frameperiod = - { - .numerator = 1001, - .denominator= 30000 - }, - .framelines = 525, - .reserved = {0,0,0,0} - }, { // This is total wild guess - .id = V4L2_STD_NTSC_443, - .frameperiod = - { - .numerator = 1001, - .denominator= 30000 - }, - .framelines = 525, - .reserved = {0,0,0,0} - } -}; - -static struct v4l2_standard *match_std(v4l2_std_id id) -{ - unsigned int idx; - for (idx = 0; idx < ARRAY_SIZE(generic_standards); idx++) { - if (generic_standards[idx].id & id) { - return generic_standards + idx; - } - } - return NULL; -} - -static int pvr2_std_fill(struct v4l2_standard *std,v4l2_std_id id) -{ - struct v4l2_standard *template; - int idx; - unsigned int bcnt; - template = match_std(id); - if (!template) return 0; - idx = std->index; - memcpy(std,template,sizeof(*template)); - std->index = idx; - std->id = id; - bcnt = pvr2_std_id_to_str(std->name,sizeof(std->name)-1,id); - std->name[bcnt] = 0; - pvr2_trace(PVR2_TRACE_STD,"Set up standard idx=%u name=%s", - std->index,std->name); - return !0; -} - -/* These are special cases of combined standards that we should enumerate - separately if the component pieces are present. */ -static v4l2_std_id std_mixes[] = { - V4L2_STD_PAL_B | V4L2_STD_PAL_G, - V4L2_STD_PAL_D | V4L2_STD_PAL_K, - V4L2_STD_SECAM_B | V4L2_STD_SECAM_G, - V4L2_STD_SECAM_D | V4L2_STD_SECAM_K, -}; - -struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr, - v4l2_std_id id) -{ - unsigned int std_cnt = 0; - unsigned int idx,bcnt,idx2; - v4l2_std_id idmsk,cmsk,fmsk; - struct v4l2_standard *stddefs; - - if (pvrusb2_debug & PVR2_TRACE_STD) { - char buf[100]; - bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id); - pvr2_trace( - PVR2_TRACE_STD,"Mapping standards mask=0x%x (%.*s)", - (int)id,bcnt,buf); - } - - *countptr = 0; - std_cnt = 0; - fmsk = 0; - for (idmsk = 1, cmsk = id; cmsk; idmsk <<= 1) { - if (!(idmsk & cmsk)) continue; - cmsk &= ~idmsk; - if (match_std(idmsk)) { - std_cnt++; - continue; - } - fmsk |= idmsk; - } - - for (idx2 = 0; idx2 < ARRAY_SIZE(std_mixes); idx2++) { - if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++; - } - - /* Don't complain about ATSC standard values */ - fmsk &= ~CSTD_ATSC; - - if (fmsk) { - char buf[100]; - bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk); - pvr2_trace( - PVR2_TRACE_ERROR_LEGS, - "WARNING:" - " Failed to classify the following standard(s): %.*s", - bcnt,buf); - } - - pvr2_trace(PVR2_TRACE_STD,"Setting up %u unique standard(s)", - std_cnt); - if (!std_cnt) return NULL; // paranoia - - stddefs = kzalloc(sizeof(struct v4l2_standard) * std_cnt, - GFP_KERNEL); - if (!stddefs) - return NULL; - - for (idx = 0; idx < std_cnt; idx++) - stddefs[idx].index = idx; - - idx = 0; - - /* Enumerate potential special cases */ - for (idx2 = 0; (idx2 < ARRAY_SIZE(std_mixes)) && (idx < std_cnt); - idx2++) { - if (!(id & std_mixes[idx2])) continue; - if (pvr2_std_fill(stddefs+idx,std_mixes[idx2])) idx++; - } - /* Now enumerate individual pieces */ - for (idmsk = 1, cmsk = id; cmsk && (idx < std_cnt); idmsk <<= 1) { - if (!(idmsk & cmsk)) continue; - cmsk &= ~idmsk; - if (!pvr2_std_fill(stddefs+idx,idmsk)) continue; - idx++; - } - - *countptr = std_cnt; - return stddefs; -} - -v4l2_std_id pvr2_std_get_usable(void) -{ - return CSTD_ALL; -} - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.h b/drivers/media/video/pvrusb2/pvrusb2-std.h deleted file mode 100644 index a35c53d0b320..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-std.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __PVRUSB2_STD_H -#define __PVRUSB2_STD_H - -#include <linux/videodev2.h> - -// Convert string describing one or more video standards into a mask of V4L -// standard bits. Return true if conversion succeeds otherwise return -// false. String is expected to be of the form: C1-x/y;C2-a/b where C1 and -// C2 are color system names (e.g. "PAL", "NTSC") and x, y, a, and b are -// modulation schemes (e.g. "M", "B", "G", etc). -int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr, - unsigned int bufSize); - -// Convert any arbitrary set of video standard bits into an unambiguous -// readable string. Return value is the number of bytes consumed in the -// buffer. The formatted string is of a form that can be parsed by our -// sibling std_std_to_id() function. -unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize, - v4l2_std_id id); - -// Create an array of suitable v4l2_standard structures given a bit mask of -// video standards to support. The array is allocated from the heap, and -// the number of elements is returned in the first argument. -struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr, - v4l2_std_id id); - -// Return mask of which video standard bits are valid -v4l2_std_id pvr2_std_get_usable(void); - -#endif /* __PVRUSB2_STD_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c deleted file mode 100644 index 6ef1335b2858..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ /dev/null @@ -1,861 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/string.h> -#include <linux/slab.h> -#include "pvrusb2-sysfs.h" -#include "pvrusb2-hdw.h" -#include "pvrusb2-debug.h" -#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC -#include "pvrusb2-debugifc.h" -#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ - -#define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__) - -struct pvr2_sysfs { - struct pvr2_channel channel; - struct device *class_dev; -#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC - struct pvr2_sysfs_debugifc *debugifc; -#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ - struct pvr2_sysfs_ctl_item *item_first; - struct pvr2_sysfs_ctl_item *item_last; - struct device_attribute attr_v4l_minor_number; - struct device_attribute attr_v4l_radio_minor_number; - struct device_attribute attr_unit_number; - struct device_attribute attr_bus_info; - struct device_attribute attr_hdw_name; - struct device_attribute attr_hdw_desc; - int v4l_minor_number_created_ok; - int v4l_radio_minor_number_created_ok; - int unit_number_created_ok; - int bus_info_created_ok; - int hdw_name_created_ok; - int hdw_desc_created_ok; -}; - -#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC -struct pvr2_sysfs_debugifc { - struct device_attribute attr_debugcmd; - struct device_attribute attr_debuginfo; - int debugcmd_created_ok; - int debuginfo_created_ok; -}; -#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ - -struct pvr2_sysfs_ctl_item { - struct device_attribute attr_name; - struct device_attribute attr_type; - struct device_attribute attr_min; - struct device_attribute attr_max; - struct device_attribute attr_def; - struct device_attribute attr_enum; - struct device_attribute attr_bits; - struct device_attribute attr_val; - struct device_attribute attr_custom; - struct pvr2_ctrl *cptr; - int ctl_id; - struct pvr2_sysfs *chptr; - struct pvr2_sysfs_ctl_item *item_next; - struct attribute *attr_gen[8]; - struct attribute_group grp; - int created_ok; - char name[80]; -}; - -struct pvr2_sysfs_class { - struct class class; -}; - -static ssize_t show_name(struct device *class_dev, - struct device_attribute *attr, - char *buf) -{ - struct pvr2_sysfs_ctl_item *cip; - const char *name; - cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_name); - name = pvr2_ctrl_get_desc(cip->cptr); - pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s", - cip->chptr, cip->ctl_id, name); - if (!name) return -EINVAL; - return scnprintf(buf, PAGE_SIZE, "%s\n", name); -} - -static ssize_t show_type(struct device *class_dev, - struct device_attribute *attr, - char *buf) -{ - struct pvr2_sysfs_ctl_item *cip; - const char *name; - enum pvr2_ctl_type tp; - cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_type); - tp = pvr2_ctrl_get_type(cip->cptr); - switch (tp) { - case pvr2_ctl_int: name = "integer"; break; - case pvr2_ctl_enum: name = "enum"; break; - case pvr2_ctl_bitmask: name = "bitmask"; break; - case pvr2_ctl_bool: name = "boolean"; break; - default: name = "?"; break; - } - pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s", - cip->chptr, cip->ctl_id, name); - if (!name) return -EINVAL; - return scnprintf(buf, PAGE_SIZE, "%s\n", name); -} - -static ssize_t show_min(struct device *class_dev, - struct device_attribute *attr, - char *buf) -{ - struct pvr2_sysfs_ctl_item *cip; - long val; - cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_min); - val = pvr2_ctrl_get_min(cip->cptr); - pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld", - cip->chptr, cip->ctl_id, val); - return scnprintf(buf, PAGE_SIZE, "%ld\n", val); -} - -static ssize_t show_max(struct device *class_dev, - struct device_attribute *attr, - char *buf) -{ - struct pvr2_sysfs_ctl_item *cip; - long val; - cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_max); - val = pvr2_ctrl_get_max(cip->cptr); - pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld", - cip->chptr, cip->ctl_id, val); - return scnprintf(buf, PAGE_SIZE, "%ld\n", val); -} - -static ssize_t show_def(struct device *class_dev, - struct device_attribute *attr, - char *buf) -{ - struct pvr2_sysfs_ctl_item *cip; - int val; - int ret; - unsigned int cnt = 0; - cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_def); - ret = pvr2_ctrl_get_def(cip->cptr, &val); - if (ret < 0) return ret; - ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val, - buf, PAGE_SIZE - 1, &cnt); - pvr2_sysfs_trace("pvr2_sysfs(%p) show_def(cid=%d) is %.*s (%d)", - cip->chptr, cip->ctl_id, cnt, buf, val); - buf[cnt] = '\n'; - return cnt + 1; -} - -static ssize_t show_val_norm(struct device *class_dev, - struct device_attribute *attr, - char *buf) -{ - struct pvr2_sysfs_ctl_item *cip; - int val; - int ret; - unsigned int cnt = 0; - cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val); - ret = pvr2_ctrl_get_value(cip->cptr, &val); - if (ret < 0) return ret; - ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val, - buf, PAGE_SIZE - 1, &cnt); - pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)", - cip->chptr, cip->ctl_id, cnt, buf, val); - buf[cnt] = '\n'; - return cnt+1; -} - -static ssize_t show_val_custom(struct device *class_dev, - struct device_attribute *attr, - char *buf) -{ - struct pvr2_sysfs_ctl_item *cip; - int val; - int ret; - unsigned int cnt = 0; - cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom); - ret = pvr2_ctrl_get_value(cip->cptr, &val); - if (ret < 0) return ret; - ret = pvr2_ctrl_custom_value_to_sym(cip->cptr, ~0, val, - buf, PAGE_SIZE - 1, &cnt); - pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)", - cip->chptr, cip->ctl_id, cnt, buf, val); - buf[cnt] = '\n'; - return cnt+1; -} - -static ssize_t show_enum(struct device *class_dev, - struct device_attribute *attr, - char *buf) -{ - struct pvr2_sysfs_ctl_item *cip; - long val; - unsigned int bcnt, ccnt, ecnt; - cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_enum); - ecnt = pvr2_ctrl_get_cnt(cip->cptr); - bcnt = 0; - for (val = 0; val < ecnt; val++) { - pvr2_ctrl_get_valname(cip->cptr, val, buf + bcnt, - PAGE_SIZE - bcnt, &ccnt); - if (!ccnt) continue; - bcnt += ccnt; - if (bcnt >= PAGE_SIZE) break; - buf[bcnt] = '\n'; - bcnt++; - } - pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)", - cip->chptr, cip->ctl_id); - return bcnt; -} - -static ssize_t show_bits(struct device *class_dev, - struct device_attribute *attr, - char *buf) -{ - struct pvr2_sysfs_ctl_item *cip; - int valid_bits, msk; - unsigned int bcnt, ccnt; - cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_bits); - valid_bits = pvr2_ctrl_get_mask(cip->cptr); - bcnt = 0; - for (msk = 1; valid_bits; msk <<= 1) { - if (!(msk & valid_bits)) continue; - valid_bits &= ~msk; - pvr2_ctrl_get_valname(cip->cptr, msk, buf + bcnt, - PAGE_SIZE - bcnt, &ccnt); - bcnt += ccnt; - if (bcnt >= PAGE_SIZE) break; - buf[bcnt] = '\n'; - bcnt++; - } - pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)", - cip->chptr, cip->ctl_id); - return bcnt; -} - -static int store_val_any(struct pvr2_sysfs_ctl_item *cip, int customfl, - const char *buf,unsigned int count) -{ - int ret; - int mask,val; - if (customfl) { - ret = pvr2_ctrl_custom_sym_to_value(cip->cptr, buf, count, - &mask, &val); - } else { - ret = pvr2_ctrl_sym_to_value(cip->cptr, buf, count, - &mask, &val); - } - if (ret < 0) return ret; - ret = pvr2_ctrl_set_mask_value(cip->cptr, mask, val); - pvr2_hdw_commit_ctl(cip->chptr->channel.hdw); - return ret; -} - -static ssize_t store_val_norm(struct device *class_dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct pvr2_sysfs_ctl_item *cip; - int ret; - cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val); - pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"", - cip->chptr, cip->ctl_id, (int)count, buf); - ret = store_val_any(cip, 0, buf, count); - if (!ret) ret = count; - return ret; -} - -static ssize_t store_val_custom(struct device *class_dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct pvr2_sysfs_ctl_item *cip; - int ret; - cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom); - pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"", - cip->chptr, cip->ctl_id, (int)count, buf); - ret = store_val_any(cip, 1, buf, count); - if (!ret) ret = count; - return ret; -} - -static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) -{ - struct pvr2_sysfs_ctl_item *cip; - struct pvr2_ctrl *cptr; - unsigned int cnt,acnt; - int ret; - - cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id); - if (!cptr) return; - - cip = kzalloc(sizeof(*cip),GFP_KERNEL); - if (!cip) return; - pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip); - - cip->cptr = cptr; - cip->ctl_id = ctl_id; - - cip->chptr = sfp; - cip->item_next = NULL; - if (sfp->item_last) { - sfp->item_last->item_next = cip; - } else { - sfp->item_first = cip; - } - sfp->item_last = cip; - - sysfs_attr_init(&cip->attr_name.attr); - cip->attr_name.attr.name = "name"; - cip->attr_name.attr.mode = S_IRUGO; - cip->attr_name.show = show_name; - - sysfs_attr_init(&cip->attr_type.attr); - cip->attr_type.attr.name = "type"; - cip->attr_type.attr.mode = S_IRUGO; - cip->attr_type.show = show_type; - - sysfs_attr_init(&cip->attr_min.attr); - cip->attr_min.attr.name = "min_val"; - cip->attr_min.attr.mode = S_IRUGO; - cip->attr_min.show = show_min; - - sysfs_attr_init(&cip->attr_max.attr); - cip->attr_max.attr.name = "max_val"; - cip->attr_max.attr.mode = S_IRUGO; - cip->attr_max.show = show_max; - - sysfs_attr_init(&cip->attr_def.attr); - cip->attr_def.attr.name = "def_val"; - cip->attr_def.attr.mode = S_IRUGO; - cip->attr_def.show = show_def; - - sysfs_attr_init(&cip->attr_val.attr); - cip->attr_val.attr.name = "cur_val"; - cip->attr_val.attr.mode = S_IRUGO; - - sysfs_attr_init(&cip->attr_custom.attr); - cip->attr_custom.attr.name = "custom_val"; - cip->attr_custom.attr.mode = S_IRUGO; - - sysfs_attr_init(&cip->attr_enum.attr); - cip->attr_enum.attr.name = "enum_val"; - cip->attr_enum.attr.mode = S_IRUGO; - cip->attr_enum.show = show_enum; - - sysfs_attr_init(&cip->attr_bits.attr); - cip->attr_bits.attr.name = "bit_val"; - cip->attr_bits.attr.mode = S_IRUGO; - cip->attr_bits.show = show_bits; - - if (pvr2_ctrl_is_writable(cptr)) { - cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP; - cip->attr_custom.attr.mode |= S_IWUSR|S_IWGRP; - } - - acnt = 0; - cip->attr_gen[acnt++] = &cip->attr_name.attr; - cip->attr_gen[acnt++] = &cip->attr_type.attr; - cip->attr_gen[acnt++] = &cip->attr_val.attr; - cip->attr_gen[acnt++] = &cip->attr_def.attr; - cip->attr_val.show = show_val_norm; - cip->attr_val.store = store_val_norm; - if (pvr2_ctrl_has_custom_symbols(cptr)) { - cip->attr_gen[acnt++] = &cip->attr_custom.attr; - cip->attr_custom.show = show_val_custom; - cip->attr_custom.store = store_val_custom; - } - switch (pvr2_ctrl_get_type(cptr)) { - case pvr2_ctl_enum: - // Control is an enumeration - cip->attr_gen[acnt++] = &cip->attr_enum.attr; - break; - case pvr2_ctl_int: - // Control is an integer - cip->attr_gen[acnt++] = &cip->attr_min.attr; - cip->attr_gen[acnt++] = &cip->attr_max.attr; - break; - case pvr2_ctl_bitmask: - // Control is an bitmask - cip->attr_gen[acnt++] = &cip->attr_bits.attr; - break; - default: break; - } - - cnt = scnprintf(cip->name,sizeof(cip->name)-1,"ctl_%s", - pvr2_ctrl_get_name(cptr)); - cip->name[cnt] = 0; - cip->grp.name = cip->name; - cip->grp.attrs = cip->attr_gen; - - ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp); - if (ret) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "sysfs_create_group error: %d", - ret); - return; - } - cip->created_ok = !0; -} - -#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC -static ssize_t debuginfo_show(struct device *, struct device_attribute *, - char *); -static ssize_t debugcmd_show(struct device *, struct device_attribute *, - char *); -static ssize_t debugcmd_store(struct device *, struct device_attribute *, - const char *, size_t count); - -static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) -{ - struct pvr2_sysfs_debugifc *dip; - int ret; - - dip = kzalloc(sizeof(*dip),GFP_KERNEL); - if (!dip) return; - sysfs_attr_init(&dip->attr_debugcmd.attr); - 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; - sysfs_attr_init(&dip->attr_debuginfo.attr); - dip->attr_debuginfo.attr.name = "debuginfo"; - dip->attr_debuginfo.attr.mode = S_IRUGO; - dip->attr_debuginfo.show = debuginfo_show; - sfp->debugifc = dip; - ret = device_create_file(sfp->class_dev,&dip->attr_debugcmd); - if (ret < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "device_create_file error: %d", - ret); - } else { - dip->debugcmd_created_ok = !0; - } - ret = device_create_file(sfp->class_dev,&dip->attr_debuginfo); - if (ret < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "device_create_file error: %d", - ret); - } else { - dip->debuginfo_created_ok = !0; - } -} - - -static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp) -{ - if (!sfp->debugifc) return; - if (sfp->debugifc->debuginfo_created_ok) { - device_remove_file(sfp->class_dev, - &sfp->debugifc->attr_debuginfo); - } - if (sfp->debugifc->debugcmd_created_ok) { - device_remove_file(sfp->class_dev, - &sfp->debugifc->attr_debugcmd); - } - kfree(sfp->debugifc); - sfp->debugifc = NULL; -} -#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ - - -static void pvr2_sysfs_add_controls(struct pvr2_sysfs *sfp) -{ - unsigned int idx,cnt; - cnt = pvr2_hdw_get_ctrl_count(sfp->channel.hdw); - for (idx = 0; idx < cnt; idx++) { - pvr2_sysfs_add_control(sfp,idx); - } -} - - -static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp) -{ - struct pvr2_sysfs_ctl_item *cip1,*cip2; - for (cip1 = sfp->item_first; cip1; cip1 = cip2) { - cip2 = cip1->item_next; - if (cip1->created_ok) { - sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp); - } - pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1); - kfree(cip1); - } -} - - -static void pvr2_sysfs_class_release(struct class *class) -{ - struct pvr2_sysfs_class *clp; - clp = container_of(class,struct pvr2_sysfs_class,class); - pvr2_sysfs_trace("Destroying pvr2_sysfs_class id=%p",clp); - kfree(clp); -} - - -static void pvr2_sysfs_release(struct device *class_dev) -{ - pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev); - kfree(class_dev); -} - - -static void class_dev_destroy(struct pvr2_sysfs *sfp) -{ - struct device *dev; - if (!sfp->class_dev) return; -#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC - pvr2_sysfs_tear_down_debugifc(sfp); -#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ - pvr2_sysfs_tear_down_controls(sfp); - if (sfp->hdw_desc_created_ok) { - device_remove_file(sfp->class_dev, - &sfp->attr_hdw_desc); - } - if (sfp->hdw_name_created_ok) { - device_remove_file(sfp->class_dev, - &sfp->attr_hdw_name); - } - if (sfp->bus_info_created_ok) { - device_remove_file(sfp->class_dev, - &sfp->attr_bus_info); - } - if (sfp->v4l_minor_number_created_ok) { - device_remove_file(sfp->class_dev, - &sfp->attr_v4l_minor_number); - } - if (sfp->v4l_radio_minor_number_created_ok) { - device_remove_file(sfp->class_dev, - &sfp->attr_v4l_radio_minor_number); - } - if (sfp->unit_number_created_ok) { - device_remove_file(sfp->class_dev, - &sfp->attr_unit_number); - } - pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); - dev_set_drvdata(sfp->class_dev, NULL); - dev = sfp->class_dev->parent; - sfp->class_dev->parent = NULL; - put_device(dev); - device_unregister(sfp->class_dev); - sfp->class_dev = NULL; -} - - -static ssize_t v4l_minor_number_show(struct device *class_dev, - struct device_attribute *attr, char *buf) -{ - struct pvr2_sysfs *sfp; - sfp = dev_get_drvdata(class_dev); - if (!sfp) return -EINVAL; - return scnprintf(buf,PAGE_SIZE,"%d\n", - pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, - pvr2_v4l_type_video)); -} - - -static ssize_t bus_info_show(struct device *class_dev, - struct device_attribute *attr, char *buf) -{ - struct pvr2_sysfs *sfp; - sfp = dev_get_drvdata(class_dev); - if (!sfp) return -EINVAL; - return scnprintf(buf,PAGE_SIZE,"%s\n", - pvr2_hdw_get_bus_info(sfp->channel.hdw)); -} - - -static ssize_t hdw_name_show(struct device *class_dev, - struct device_attribute *attr, char *buf) -{ - struct pvr2_sysfs *sfp; - sfp = dev_get_drvdata(class_dev); - if (!sfp) return -EINVAL; - return scnprintf(buf,PAGE_SIZE,"%s\n", - pvr2_hdw_get_type(sfp->channel.hdw)); -} - - -static ssize_t hdw_desc_show(struct device *class_dev, - struct device_attribute *attr, char *buf) -{ - struct pvr2_sysfs *sfp; - sfp = dev_get_drvdata(class_dev); - if (!sfp) return -EINVAL; - return scnprintf(buf,PAGE_SIZE,"%s\n", - pvr2_hdw_get_desc(sfp->channel.hdw)); -} - - -static ssize_t v4l_radio_minor_number_show(struct device *class_dev, - struct device_attribute *attr, - char *buf) -{ - struct pvr2_sysfs *sfp; - sfp = dev_get_drvdata(class_dev); - if (!sfp) return -EINVAL; - return scnprintf(buf,PAGE_SIZE,"%d\n", - pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, - pvr2_v4l_type_radio)); -} - - -static ssize_t unit_number_show(struct device *class_dev, - struct device_attribute *attr, char *buf) -{ - struct pvr2_sysfs *sfp; - sfp = dev_get_drvdata(class_dev); - if (!sfp) return -EINVAL; - return scnprintf(buf,PAGE_SIZE,"%d\n", - pvr2_hdw_get_unit_number(sfp->channel.hdw)); -} - - -static void class_dev_create(struct pvr2_sysfs *sfp, - struct pvr2_sysfs_class *class_ptr) -{ - struct usb_device *usb_dev; - struct device *class_dev; - int ret; - - usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw); - if (!usb_dev) return; - class_dev = kzalloc(sizeof(*class_dev),GFP_KERNEL); - if (!class_dev) return; - - pvr2_sysfs_trace("Creating class_dev id=%p",class_dev); - - class_dev->class = &class_ptr->class; - - dev_set_name(class_dev, "%s", - pvr2_hdw_get_device_identifier(sfp->channel.hdw)); - - class_dev->parent = get_device(&usb_dev->dev); - - sfp->class_dev = class_dev; - dev_set_drvdata(class_dev, sfp); - ret = device_register(class_dev); - if (ret) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "device_register failed"); - put_device(class_dev); - return; - } - - sysfs_attr_init(&sfp->attr_v4l_minor_number.attr); - 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; - sfp->attr_v4l_minor_number.store = NULL; - ret = device_create_file(sfp->class_dev, - &sfp->attr_v4l_minor_number); - if (ret < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "device_create_file error: %d", - ret); - } else { - sfp->v4l_minor_number_created_ok = !0; - } - - sysfs_attr_init(&sfp->attr_v4l_radio_minor_number.attr); - 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; - sfp->attr_v4l_radio_minor_number.store = NULL; - ret = device_create_file(sfp->class_dev, - &sfp->attr_v4l_radio_minor_number); - if (ret < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "device_create_file error: %d", - ret); - } else { - sfp->v4l_radio_minor_number_created_ok = !0; - } - - sysfs_attr_init(&sfp->attr_unit_number.attr); - sfp->attr_unit_number.attr.name = "unit_number"; - sfp->attr_unit_number.attr.mode = S_IRUGO; - sfp->attr_unit_number.show = unit_number_show; - sfp->attr_unit_number.store = NULL; - ret = device_create_file(sfp->class_dev,&sfp->attr_unit_number); - if (ret < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "device_create_file error: %d", - ret); - } else { - sfp->unit_number_created_ok = !0; - } - - sysfs_attr_init(&sfp->attr_bus_info.attr); - 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 = device_create_file(sfp->class_dev, - &sfp->attr_bus_info); - if (ret < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "device_create_file error: %d", - ret); - } else { - sfp->bus_info_created_ok = !0; - } - - sysfs_attr_init(&sfp->attr_hdw_name.attr); - sfp->attr_hdw_name.attr.name = "device_hardware_type"; - sfp->attr_hdw_name.attr.mode = S_IRUGO; - sfp->attr_hdw_name.show = hdw_name_show; - sfp->attr_hdw_name.store = NULL; - ret = device_create_file(sfp->class_dev, - &sfp->attr_hdw_name); - if (ret < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "device_create_file error: %d", - ret); - } else { - sfp->hdw_name_created_ok = !0; - } - - sysfs_attr_init(&sfp->attr_hdw_desc.attr); - sfp->attr_hdw_desc.attr.name = "device_hardware_description"; - sfp->attr_hdw_desc.attr.mode = S_IRUGO; - sfp->attr_hdw_desc.show = hdw_desc_show; - sfp->attr_hdw_desc.store = NULL; - ret = device_create_file(sfp->class_dev, - &sfp->attr_hdw_desc); - if (ret < 0) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "device_create_file error: %d", - ret); - } else { - sfp->hdw_desc_created_ok = !0; - } - - pvr2_sysfs_add_controls(sfp); -#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC - pvr2_sysfs_add_debugifc(sfp); -#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ -} - - -static void pvr2_sysfs_internal_check(struct pvr2_channel *chp) -{ - struct pvr2_sysfs *sfp; - sfp = container_of(chp,struct pvr2_sysfs,channel); - if (!sfp->channel.mc_head->disconnect_flag) return; - pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_sysfs id=%p",sfp); - class_dev_destroy(sfp); - pvr2_channel_done(&sfp->channel); - kfree(sfp); -} - - -struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp, - struct pvr2_sysfs_class *class_ptr) -{ - struct pvr2_sysfs *sfp; - sfp = kzalloc(sizeof(*sfp),GFP_KERNEL); - if (!sfp) return sfp; - pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp); - pvr2_channel_init(&sfp->channel,mp); - sfp->channel.check_func = pvr2_sysfs_internal_check; - - class_dev_create(sfp,class_ptr); - return sfp; -} - - - -struct pvr2_sysfs_class *pvr2_sysfs_class_create(void) -{ - struct pvr2_sysfs_class *clp; - clp = kzalloc(sizeof(*clp),GFP_KERNEL); - if (!clp) return clp; - pvr2_sysfs_trace("Creating and registering pvr2_sysfs_class id=%p", - clp); - clp->class.name = "pvrusb2"; - clp->class.class_release = pvr2_sysfs_class_release; - clp->class.dev_release = pvr2_sysfs_release; - if (class_register(&clp->class)) { - pvr2_sysfs_trace( - "Registration failed for pvr2_sysfs_class id=%p",clp); - kfree(clp); - clp = NULL; - } - return clp; -} - - -void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp) -{ - pvr2_sysfs_trace("Unregistering pvr2_sysfs_class id=%p", clp); - class_unregister(&clp->class); -} - - -#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC -static ssize_t debuginfo_show(struct device *class_dev, - struct device_attribute *attr, char *buf) -{ - struct pvr2_sysfs *sfp; - sfp = dev_get_drvdata(class_dev); - if (!sfp) return -EINVAL; - pvr2_hdw_trigger_module_log(sfp->channel.hdw); - return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE); -} - - -static ssize_t debugcmd_show(struct device *class_dev, - struct device_attribute *attr, char *buf) -{ - struct pvr2_sysfs *sfp; - sfp = dev_get_drvdata(class_dev); - if (!sfp) return -EINVAL; - return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE); -} - - -static ssize_t debugcmd_store(struct device *class_dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct pvr2_sysfs *sfp; - int ret; - - sfp = dev_get_drvdata(class_dev); - if (!sfp) return -EINVAL; - - ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count); - if (ret < 0) return ret; - return count; -} -#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.h b/drivers/media/video/pvrusb2/pvrusb2-sysfs.h deleted file mode 100644 index 6d875bfe7991..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __PVRUSB2_SYSFS_H -#define __PVRUSB2_SYSFS_H - -#include <linux/list.h> -#include <linux/sysfs.h> -#include "pvrusb2-context.h" - -struct pvr2_sysfs; -struct pvr2_sysfs_class; - -struct pvr2_sysfs_class *pvr2_sysfs_class_create(void); -void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *); - -struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *, - struct pvr2_sysfs_class *); - -#endif /* __PVRUSB2_SYSFS_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-util.h b/drivers/media/video/pvrusb2/pvrusb2-util.h deleted file mode 100644 index 92b75544ee2e..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-util.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __PVRUSB2_UTIL_H -#define __PVRUSB2_UTIL_H - -#define PVR2_DECOMPOSE_LE(t,i,d) \ - do { \ - (t)[i] = (d) & 0xff;\ - (t)[i+1] = ((d) >> 8) & 0xff;\ - (t)[i+2] = ((d) >> 16) & 0xff;\ - (t)[i+3] = ((d) >> 24) & 0xff;\ - } while(0) - -#define PVR2_DECOMPOSE_BE(t,i,d) \ - do { \ - (t)[i+3] = (d) & 0xff;\ - (t)[i+2] = ((d) >> 8) & 0xff;\ - (t)[i+1] = ((d) >> 16) & 0xff;\ - (t)[i] = ((d) >> 24) & 0xff;\ - } while(0) - -#define PVR2_COMPOSE_LE(t,i) \ - ((((u32)((t)[i+3])) << 24) | \ - (((u32)((t)[i+2])) << 16) | \ - (((u32)((t)[i+1])) << 8) | \ - ((u32)((t)[i]))) - -#define PVR2_COMPOSE_BE(t,i) \ - ((((u32)((t)[i])) << 24) | \ - (((u32)((t)[i+1])) << 16) | \ - (((u32)((t)[i+2])) << 8) | \ - ((u32)((t)[i+3]))) - - -#endif /* __PVRUSB2_UTIL_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c deleted file mode 100644 index f344aed32a93..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ /dev/null @@ -1,1413 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/version.h> -#include "pvrusb2-context.h" -#include "pvrusb2-hdw.h" -#include "pvrusb2.h" -#include "pvrusb2-debug.h" -#include "pvrusb2-v4l2.h" -#include "pvrusb2-ioread.h" -#include <linux/videodev2.h> -#include <linux/module.h> -#include <media/v4l2-dev.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> - -struct pvr2_v4l2_dev; -struct pvr2_v4l2_fh; -struct pvr2_v4l2; - -struct pvr2_v4l2_dev { - struct video_device devbase; /* MUST be first! */ - struct pvr2_v4l2 *v4lp; - struct pvr2_context_stream *stream; - /* Information about this device: */ - enum pvr2_config config; /* Expected stream format */ - int v4l_type; /* V4L defined type for this device node */ - enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */ -}; - -struct pvr2_v4l2_fh { - struct pvr2_channel channel; - struct pvr2_v4l2_dev *pdi; - enum v4l2_priority prio; - struct pvr2_ioread *rhp; - struct file *file; - struct pvr2_v4l2 *vhead; - struct pvr2_v4l2_fh *vnext; - struct pvr2_v4l2_fh *vprev; - wait_queue_head_t wait_data; - int fw_mode_flag; - /* Map contiguous ordinal value to input id */ - unsigned char *input_map; - unsigned int input_cnt; -}; - -struct pvr2_v4l2 { - struct pvr2_channel channel; - struct pvr2_v4l2_fh *vfirst; - struct pvr2_v4l2_fh *vlast; - - struct v4l2_prio_state prio; - - /* streams - Note that these must be separately, individually, - * allocated pointers. This is because the v4l core is going to - * manage their deletion - separately, individually... */ - struct pvr2_v4l2_dev *dev_video; - struct pvr2_v4l2_dev *dev_radio; -}; - -static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1}; -module_param_array(video_nr, int, NULL, 0444); -MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor"); -static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1}; -module_param_array(radio_nr, int, NULL, 0444); -MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor"); -static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1}; -module_param_array(vbi_nr, int, NULL, 0444); -MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor"); - -static struct v4l2_capability pvr_capability ={ - .driver = "pvrusb2", - .card = "Hauppauge WinTV pvr-usb2", - .bus_info = "usb", - .version = LINUX_VERSION_CODE, - .capabilities = (V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | - V4L2_CAP_READWRITE), -}; - -static struct v4l2_fmtdesc pvr_fmtdesc [] = { - { - .index = 0, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .flags = V4L2_FMT_FLAG_COMPRESSED, - .description = "MPEG1/2", - // This should really be V4L2_PIX_FMT_MPEG, but xawtv - // breaks when I do that. - .pixelformat = 0, // V4L2_PIX_FMT_MPEG, - } -}; - -#define PVR_FORMAT_PIX 0 -#define PVR_FORMAT_VBI 1 - -static struct v4l2_format pvr_format [] = { - [PVR_FORMAT_PIX] = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .fmt = { - .pix = { - .width = 720, - .height = 576, - // This should really be V4L2_PIX_FMT_MPEG, - // but xawtv breaks when I do that. - .pixelformat = 0, // V4L2_PIX_FMT_MPEG, - .field = V4L2_FIELD_INTERLACED, - .bytesperline = 0, // doesn't make sense - // here - //FIXME : Don't know what to put here... - .sizeimage = (32*1024), - .colorspace = 0, // doesn't make sense here - .priv = 0 - } - } - }, - [PVR_FORMAT_VBI] = { - .type = V4L2_BUF_TYPE_VBI_CAPTURE, - .fmt = { - .vbi = { - .sampling_rate = 27000000, - .offset = 248, - .samples_per_line = 1443, - .sample_format = V4L2_PIX_FMT_GREY, - .start = { 0, 0 }, - .count = { 0, 0 }, - .flags = 0, - } - } - } -}; - - - -/* - * This is part of Video 4 Linux API. These procedures handle ioctl() calls. - */ -static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability *cap) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - - memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability)); - strlcpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw), - sizeof(cap->bus_info)); - strlcpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card)); - return 0; -} - -static int pvr2_g_priority(struct file *file, void *priv, enum v4l2_priority *p) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_v4l2 *vp = fh->vhead; - - *p = v4l2_prio_max(&vp->prio); - return 0; -} - -static int pvr2_s_priority(struct file *file, void *priv, enum v4l2_priority prio) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_v4l2 *vp = fh->vhead; - - return v4l2_prio_change(&vp->prio, &fh->prio, prio); -} - -static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - int val = 0; - int ret; - - ret = pvr2_ctrl_get_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), &val); - *std = val; - return ret; -} - -int pvr2_s_std(struct file *file, void *priv, v4l2_std_id *std) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - - return pvr2_ctrl_set_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), *std); -} - -static int pvr2_querystd(struct file *file, void *priv, v4l2_std_id *std) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - int val = 0; - int ret; - - ret = pvr2_ctrl_get_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDDETECT), &val); - *std = val; - return ret; -} - -static int pvr2_enum_input(struct file *file, void *priv, struct v4l2_input *vi) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - struct pvr2_ctrl *cptr; - struct v4l2_input tmp; - unsigned int cnt; - int val; - - cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT); - - memset(&tmp, 0, sizeof(tmp)); - tmp.index = vi->index; - if (vi->index >= fh->input_cnt) - return -EINVAL; - val = fh->input_map[vi->index]; - switch (val) { - case PVR2_CVAL_INPUT_TV: - case PVR2_CVAL_INPUT_DTV: - case PVR2_CVAL_INPUT_RADIO: - tmp.type = V4L2_INPUT_TYPE_TUNER; - break; - case PVR2_CVAL_INPUT_SVIDEO: - case PVR2_CVAL_INPUT_COMPOSITE: - tmp.type = V4L2_INPUT_TYPE_CAMERA; - break; - default: - return -EINVAL; - } - - cnt = 0; - pvr2_ctrl_get_valname(cptr, val, - tmp.name, sizeof(tmp.name) - 1, &cnt); - tmp.name[cnt] = 0; - - /* Don't bother with audioset, since this driver currently - always switches the audio whenever the video is - switched. */ - - /* Handling std is a tougher problem. It doesn't make - sense in cases where a device might be multi-standard. - We could just copy out the current value for the - standard, but it can change over time. For now just - leave it zero. */ - *vi = tmp; - return 0; -} - -static int pvr2_g_input(struct file *file, void *priv, unsigned int *i) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - unsigned int idx; - struct pvr2_ctrl *cptr; - int val; - int ret; - - cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT); - val = 0; - ret = pvr2_ctrl_get_value(cptr, &val); - *i = 0; - for (idx = 0; idx < fh->input_cnt; idx++) { - if (fh->input_map[idx] == val) { - *i = idx; - break; - } - } - return ret; -} - -static int pvr2_s_input(struct file *file, void *priv, unsigned int inp) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - - if (inp >= fh->input_cnt) - return -EINVAL; - return pvr2_ctrl_set_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT), - fh->input_map[inp]); -} - -static int pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin) -{ - /* pkt: FIXME: We are returning one "fake" input here - which could very well be called "whatever_we_like". - This is for apps that want to see an audio input - just to feel comfortable, as well as to test if - it can do stereo or sth. There is actually no guarantee - that the actual audio input cannot change behind the app's - back, but most applications should not mind that either. - - Hopefully, mplayer people will work with us on this (this - whole mess is to support mplayer pvr://), or Hans will come - up with a more standard way to say "we have inputs but we - don 't want you to change them independent of video" which - will sort this mess. - */ - - if (vin->index > 0) - return -EINVAL; - strncpy(vin->name, "PVRUSB2 Audio", 14); - vin->capability = V4L2_AUDCAP_STEREO; - return 0; -} - -static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin) -{ - /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */ - vin->index = 0; - strncpy(vin->name, "PVRUSB2 Audio", 14); - vin->capability = V4L2_AUDCAP_STEREO; - return 0; -} - -static int pvr2_s_audio(struct file *file, void *priv, struct v4l2_audio *vout) -{ - if (vout->index) - return -EINVAL; - return 0; -} - -static int pvr2_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - - if (vt->index != 0) - return -EINVAL; /* Only answer for the 1st tuner */ - - pvr2_hdw_execute_tuner_poll(hdw); - return pvr2_hdw_get_tuner_status(hdw, vt); -} - -static int pvr2_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - - if (vt->index != 0) - return -EINVAL; - - return pvr2_ctrl_set_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_AUDIOMODE), - vt->audmode); -} - -int pvr2_s_frequency(struct file *file, void *priv, struct v4l2_frequency *vf) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - unsigned long fv; - struct v4l2_tuner vt; - int cur_input; - struct pvr2_ctrl *ctrlp; - int ret; - - ret = pvr2_hdw_get_tuner_status(hdw, &vt); - if (ret != 0) - return ret; - ctrlp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT); - ret = pvr2_ctrl_get_value(ctrlp, &cur_input); - if (ret != 0) - return ret; - if (vf->type == V4L2_TUNER_RADIO) { - if (cur_input != PVR2_CVAL_INPUT_RADIO) - pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_RADIO); - } else { - if (cur_input == PVR2_CVAL_INPUT_RADIO) - pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_TV); - } - fv = vf->frequency; - if (vt.capability & V4L2_TUNER_CAP_LOW) - fv = (fv * 125) / 2; - else - fv = fv * 62500; - return pvr2_ctrl_set_value( - pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv); -} - -static int pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - int val = 0; - int cur_input; - struct v4l2_tuner vt; - int ret; - - ret = pvr2_hdw_get_tuner_status(hdw, &vt); - if (ret != 0) - return ret; - ret = pvr2_ctrl_get_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_FREQUENCY), - &val); - if (ret != 0) - return ret; - pvr2_ctrl_get_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT), - &cur_input); - if (cur_input == PVR2_CVAL_INPUT_RADIO) - vf->type = V4L2_TUNER_RADIO; - else - vf->type = V4L2_TUNER_ANALOG_TV; - if (vt.capability & V4L2_TUNER_CAP_LOW) - val = (val * 2) / 125; - else - val /= 62500; - vf->frequency = val; - return 0; -} - -static int pvr2_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fd) -{ - /* Only one format is supported : mpeg.*/ - if (fd->index != 0) - return -EINVAL; - - memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc)); - return 0; -} - -static int pvr2_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - int val; - - memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format)); - val = 0; - pvr2_ctrl_get_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES), - &val); - vf->fmt.pix.width = val; - val = 0; - pvr2_ctrl_get_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES), - &val); - vf->fmt.pix.height = val; - return 0; -} - -static int pvr2_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - int lmin, lmax, ldef; - struct pvr2_ctrl *hcp, *vcp; - int h = vf->fmt.pix.height; - int w = vf->fmt.pix.width; - - hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES); - vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES); - - lmin = pvr2_ctrl_get_min(hcp); - lmax = pvr2_ctrl_get_max(hcp); - pvr2_ctrl_get_def(hcp, &ldef); - if (w == -1) - w = ldef; - else if (w < lmin) - w = lmin; - else if (w > lmax) - w = lmax; - lmin = pvr2_ctrl_get_min(vcp); - lmax = pvr2_ctrl_get_max(vcp); - pvr2_ctrl_get_def(vcp, &ldef); - if (h == -1) - h = ldef; - else if (h < lmin) - h = lmin; - else if (h > lmax) - h = lmax; - - memcpy(vf, &pvr_format[PVR_FORMAT_PIX], - sizeof(struct v4l2_format)); - vf->fmt.pix.width = w; - vf->fmt.pix.height = h; - return 0; -} - -static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - struct pvr2_ctrl *hcp, *vcp; - int ret = pvr2_try_fmt_vid_cap(file, fh, vf); - - if (ret) - return ret; - hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES); - vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES); - pvr2_ctrl_set_value(hcp, vf->fmt.pix.width); - pvr2_ctrl_set_value(vcp, vf->fmt.pix.height); - return 0; -} - -static int pvr2_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - struct pvr2_v4l2_dev *pdi = fh->pdi; - int ret; - - if (!fh->pdi->stream) { - /* No stream defined for this node. This means - that we're not currently allowed to stream from - this node. */ - return -EPERM; - } - ret = pvr2_hdw_set_stream_type(hdw, pdi->config); - if (ret < 0) - return ret; - return pvr2_hdw_set_streaming(hdw, !0); -} - -static int pvr2_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - - if (!fh->pdi->stream) { - /* No stream defined for this node. This means - that we're not currently allowed to stream from - this node. */ - return -EPERM; - } - return pvr2_hdw_set_streaming(hdw, 0); -} - -static int pvr2_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *vc) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - struct pvr2_ctrl *cptr; - int val; - - if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) { - cptr = pvr2_hdw_get_ctrl_nextv4l( - hdw, (vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL)); - if (cptr) - vc->id = pvr2_ctrl_get_v4lid(cptr); - } else { - cptr = pvr2_hdw_get_ctrl_v4l(hdw, vc->id); - } - if (!cptr) { - pvr2_trace(PVR2_TRACE_V4LIOCTL, - "QUERYCTRL id=0x%x not implemented here", - vc->id); - return -EINVAL; - } - - pvr2_trace(PVR2_TRACE_V4LIOCTL, - "QUERYCTRL id=0x%x mapping name=%s (%s)", - vc->id, pvr2_ctrl_get_name(cptr), - pvr2_ctrl_get_desc(cptr)); - strlcpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name)); - vc->flags = pvr2_ctrl_get_v4lflags(cptr); - pvr2_ctrl_get_def(cptr, &val); - vc->default_value = val; - switch (pvr2_ctrl_get_type(cptr)) { - case pvr2_ctl_enum: - vc->type = V4L2_CTRL_TYPE_MENU; - vc->minimum = 0; - vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1; - vc->step = 1; - break; - case pvr2_ctl_bool: - vc->type = V4L2_CTRL_TYPE_BOOLEAN; - vc->minimum = 0; - vc->maximum = 1; - vc->step = 1; - break; - case pvr2_ctl_int: - vc->type = V4L2_CTRL_TYPE_INTEGER; - vc->minimum = pvr2_ctrl_get_min(cptr); - vc->maximum = pvr2_ctrl_get_max(cptr); - vc->step = 1; - break; - default: - pvr2_trace(PVR2_TRACE_V4LIOCTL, - "QUERYCTRL id=0x%x name=%s not mappable", - vc->id, pvr2_ctrl_get_name(cptr)); - return -EINVAL; - } - return 0; -} - -static int pvr2_querymenu(struct file *file, void *priv, struct v4l2_querymenu *vm) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - unsigned int cnt = 0; - int ret; - - ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw, vm->id), - vm->index, - vm->name, sizeof(vm->name) - 1, - &cnt); - vm->name[cnt] = 0; - return ret; -} - -static int pvr2_g_ctrl(struct file *file, void *priv, struct v4l2_control *vc) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - int val = 0; - int ret; - - ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id), - &val); - vc->value = val; - return ret; -} - -static int pvr2_s_ctrl(struct file *file, void *priv, struct v4l2_control *vc) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - - return pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id), - vc->value); -} - -static int pvr2_g_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *ctls) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - struct v4l2_ext_control *ctrl; - unsigned int idx; - int val; - int ret; - - ret = 0; - for (idx = 0; idx < ctls->count; idx++) { - ctrl = ctls->controls + idx; - ret = pvr2_ctrl_get_value( - pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id), &val); - if (ret) { - ctls->error_idx = idx; - return ret; - } - /* Ensure that if read as a 64 bit value, the user - will still get a hopefully sane value */ - ctrl->value64 = 0; - ctrl->value = val; - } - return 0; -} - -static int pvr2_s_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *ctls) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - struct v4l2_ext_control *ctrl; - unsigned int idx; - int ret; - - ret = 0; - for (idx = 0; idx < ctls->count; idx++) { - ctrl = ctls->controls + idx; - ret = pvr2_ctrl_set_value( - pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id), - ctrl->value); - if (ret) { - ctls->error_idx = idx; - return ret; - } - } - return 0; -} - -static int pvr2_try_ext_ctrls(struct file *file, void *priv, - struct v4l2_ext_controls *ctls) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - struct v4l2_ext_control *ctrl; - struct pvr2_ctrl *pctl; - unsigned int idx; - - /* For the moment just validate that the requested control - actually exists. */ - for (idx = 0; idx < ctls->count; idx++) { - ctrl = ctls->controls + idx; - pctl = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id); - if (!pctl) { - ctls->error_idx = idx; - return -EINVAL; - } - } - return 0; -} - -static int pvr2_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cap) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - int ret; - - if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - ret = pvr2_hdw_get_cropcap(hdw, cap); - cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */ - return ret; -} - -static int pvr2_g_crop(struct file *file, void *priv, struct v4l2_crop *crop) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - int val = 0; - int ret; - - if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - ret = pvr2_ctrl_get_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val); - if (ret != 0) - return -EINVAL; - crop->c.left = val; - ret = pvr2_ctrl_get_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val); - if (ret != 0) - return -EINVAL; - crop->c.top = val; - ret = pvr2_ctrl_get_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val); - if (ret != 0) - return -EINVAL; - crop->c.width = val; - ret = pvr2_ctrl_get_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val); - if (ret != 0) - return -EINVAL; - crop->c.height = val; - return 0; -} - -static int pvr2_s_crop(struct file *file, void *priv, struct v4l2_crop *crop) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - int ret; - - if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - ret = pvr2_ctrl_set_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), - crop->c.left); - if (ret != 0) - return -EINVAL; - ret = pvr2_ctrl_set_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), - crop->c.top); - if (ret != 0) - return -EINVAL; - ret = pvr2_ctrl_set_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), - crop->c.width); - if (ret != 0) - return -EINVAL; - ret = pvr2_ctrl_set_value( - pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), - crop->c.height); - if (ret != 0) - return -EINVAL; - return 0; -} - -static int pvr2_log_status(struct file *file, void *priv) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - - pvr2_hdw_trigger_module_log(hdw); - return 0; -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int pvr2_g_register(struct file *file, void *priv, struct v4l2_dbg_register *req) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - u64 val; - int ret; - - ret = pvr2_hdw_register_access( - hdw, &req->match, req->reg, - 0, &val); - req->val = val; - return ret; -} - -static int pvr2_s_register(struct file *file, void *priv, struct v4l2_dbg_register *req) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - u64 val; - int ret; - - val = req->val; - ret = pvr2_hdw_register_access( - hdw, &req->match, req->reg, - 1, &val); - return ret; -} -#endif - -static const struct v4l2_ioctl_ops pvr2_ioctl_ops = { - .vidioc_querycap = pvr2_querycap, - .vidioc_g_priority = pvr2_g_priority, - .vidioc_s_priority = pvr2_s_priority, - .vidioc_s_audio = pvr2_s_audio, - .vidioc_g_audio = pvr2_g_audio, - .vidioc_enumaudio = pvr2_enumaudio, - .vidioc_enum_input = pvr2_enum_input, - .vidioc_cropcap = pvr2_cropcap, - .vidioc_s_crop = pvr2_s_crop, - .vidioc_g_crop = pvr2_g_crop, - .vidioc_g_input = pvr2_g_input, - .vidioc_s_input = pvr2_s_input, - .vidioc_g_frequency = pvr2_g_frequency, - .vidioc_s_frequency = pvr2_s_frequency, - .vidioc_s_tuner = pvr2_s_tuner, - .vidioc_g_tuner = pvr2_g_tuner, - .vidioc_g_std = pvr2_g_std, - .vidioc_s_std = pvr2_s_std, - .vidioc_querystd = pvr2_querystd, - .vidioc_log_status = pvr2_log_status, - .vidioc_enum_fmt_vid_cap = pvr2_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = pvr2_g_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = pvr2_s_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = pvr2_try_fmt_vid_cap, - .vidioc_streamon = pvr2_streamon, - .vidioc_streamoff = pvr2_streamoff, - .vidioc_queryctrl = pvr2_queryctrl, - .vidioc_querymenu = pvr2_querymenu, - .vidioc_g_ctrl = pvr2_g_ctrl, - .vidioc_s_ctrl = pvr2_s_ctrl, - .vidioc_g_ext_ctrls = pvr2_g_ext_ctrls, - .vidioc_s_ext_ctrls = pvr2_s_ext_ctrls, - .vidioc_try_ext_ctrls = pvr2_try_ext_ctrls, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = pvr2_g_register, - .vidioc_s_register = pvr2_s_register, -#endif -}; - -static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) -{ - struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw; - enum pvr2_config cfg = dip->config; - char msg[80]; - unsigned int mcnt; - - /* Construct the unregistration message *before* we actually - perform the unregistration step. By doing it this way we don't - have to worry about potentially touching deleted resources. */ - mcnt = scnprintf(msg, sizeof(msg) - 1, - "pvrusb2: unregistered device %s [%s]", - video_device_node_name(&dip->devbase), - pvr2_config_get_name(cfg)); - msg[mcnt] = 0; - - pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1); - - /* Paranoia */ - dip->v4lp = NULL; - dip->stream = NULL; - - /* Actual deallocation happens later when all internal references - are gone. */ - video_unregister_device(&dip->devbase); - - printk(KERN_INFO "%s\n", msg); - -} - - -static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip) -{ - if (!dip) return; - if (!dip->devbase.parent) return; - dip->devbase.parent = NULL; - device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE); -} - - -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 = NULL; - } - if (vp->dev_radio) { - pvr2_v4l2_dev_destroy(vp->dev_radio); - vp->dev_radio = NULL; - } - - pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp); - pvr2_channel_done(&vp->channel); - kfree(vp); -} - - -static void pvr2_video_device_release(struct video_device *vdev) -{ - struct pvr2_v4l2_dev *dev; - dev = container_of(vdev,struct pvr2_v4l2_dev,devbase); - kfree(dev); -} - - -static void pvr2_v4l2_internal_check(struct pvr2_channel *chp) -{ - struct pvr2_v4l2 *vp; - vp = container_of(chp,struct pvr2_v4l2,channel); - if (!vp->channel.mc_head->disconnect_flag) return; - pvr2_v4l2_dev_disassociate_parent(vp->dev_video); - pvr2_v4l2_dev_disassociate_parent(vp->dev_radio); - if (vp->vfirst) return; - pvr2_v4l2_destroy_no_lock(vp); -} - - -static long pvr2_v4l2_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_v4l2 *vp = fh->vhead; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - long ret = -EINVAL; - - if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) - v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd); - - if (!pvr2_hdw_dev_ok(hdw)) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "ioctl failed - bad or no context"); - return -EFAULT; - } - - /* check priority */ - switch (cmd) { - case VIDIOC_S_CTRL: - case VIDIOC_S_STD: - case VIDIOC_S_INPUT: - case VIDIOC_S_TUNER: - case VIDIOC_S_FREQUENCY: - ret = v4l2_prio_check(&vp->prio, fh->prio); - if (ret) - return ret; - } - - ret = video_ioctl2(file, cmd, arg); - - pvr2_hdw_commit_ctl(hdw); - - if (ret < 0) { - if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { - pvr2_trace(PVR2_TRACE_V4LIOCTL, - "pvr2_v4l2_do_ioctl failure, ret=%ld", ret); - } else { - if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { - pvr2_trace(PVR2_TRACE_V4LIOCTL, - "pvr2_v4l2_do_ioctl failure, ret=%ld" - " command was:", ret); - v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), - cmd); - } - } - } else { - pvr2_trace(PVR2_TRACE_V4LIOCTL, - "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)", - ret, ret); - } - return ret; - -} - - -static int pvr2_v4l2_release(struct file *file) -{ - struct pvr2_v4l2_fh *fhp = file->private_data; - struct pvr2_v4l2 *vp = fhp->vhead; - struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw; - - pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release"); - - if (fhp->rhp) { - struct pvr2_stream *sp; - pvr2_hdw_set_streaming(hdw,0); - sp = pvr2_ioread_get_stream(fhp->rhp); - if (sp) pvr2_stream_set_callback(sp,NULL,NULL); - pvr2_ioread_destroy(fhp->rhp); - fhp->rhp = NULL; - } - - v4l2_prio_close(&vp->prio, fhp->prio); - file->private_data = NULL; - - if (fhp->vnext) { - fhp->vnext->vprev = fhp->vprev; - } else { - vp->vlast = fhp->vprev; - } - if (fhp->vprev) { - fhp->vprev->vnext = fhp->vnext; - } else { - vp->vfirst = fhp->vnext; - } - fhp->vnext = NULL; - fhp->vprev = NULL; - fhp->vhead = NULL; - pvr2_channel_done(&fhp->channel); - pvr2_trace(PVR2_TRACE_STRUCT, - "Destroying pvr_v4l2_fh id=%p",fhp); - if (fhp->input_map) { - kfree(fhp->input_map); - fhp->input_map = NULL; - } - kfree(fhp); - if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) { - pvr2_v4l2_destroy_no_lock(vp); - } - return 0; -} - - -static int pvr2_v4l2_open(struct file *file) -{ - struct pvr2_v4l2_dev *dip; /* Our own context pointer */ - struct pvr2_v4l2_fh *fhp; - struct pvr2_v4l2 *vp; - struct pvr2_hdw *hdw; - unsigned int input_mask = 0; - unsigned int input_cnt,idx; - int ret = 0; - - dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase); - - vp = dip->v4lp; - hdw = vp->channel.hdw; - - pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open"); - - if (!pvr2_hdw_dev_ok(hdw)) { - pvr2_trace(PVR2_TRACE_OPEN_CLOSE, - "pvr2_v4l2_open: hardware not ready"); - return -EIO; - } - - fhp = kzalloc(sizeof(*fhp),GFP_KERNEL); - if (!fhp) { - return -ENOMEM; - } - - init_waitqueue_head(&fhp->wait_data); - fhp->pdi = dip; - - pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp); - pvr2_channel_init(&fhp->channel,vp->channel.mc_head); - - if (dip->v4l_type == VFL_TYPE_RADIO) { - /* Opening device as a radio, legal input selection subset - is just the radio. */ - input_mask = (1 << PVR2_CVAL_INPUT_RADIO); - } else { - /* Opening the main V4L device, legal input selection - subset includes all analog inputs. */ - input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) | - (1 << PVR2_CVAL_INPUT_TV) | - (1 << PVR2_CVAL_INPUT_COMPOSITE) | - (1 << PVR2_CVAL_INPUT_SVIDEO)); - } - ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask); - if (ret) { - pvr2_channel_done(&fhp->channel); - pvr2_trace(PVR2_TRACE_STRUCT, - "Destroying pvr_v4l2_fh id=%p (input mask error)", - fhp); - - kfree(fhp); - return ret; - } - - input_mask &= pvr2_hdw_get_input_available(hdw); - input_cnt = 0; - for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { - if (input_mask & (1 << idx)) input_cnt++; - } - fhp->input_cnt = input_cnt; - fhp->input_map = kzalloc(input_cnt,GFP_KERNEL); - if (!fhp->input_map) { - pvr2_channel_done(&fhp->channel); - pvr2_trace(PVR2_TRACE_STRUCT, - "Destroying pvr_v4l2_fh id=%p (input map failure)", - fhp); - kfree(fhp); - return -ENOMEM; - } - input_cnt = 0; - for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { - if (!(input_mask & (1 << idx))) continue; - fhp->input_map[input_cnt++] = idx; - } - - fhp->vnext = NULL; - fhp->vprev = vp->vlast; - if (vp->vlast) { - vp->vlast->vnext = fhp; - } else { - vp->vfirst = fhp; - } - vp->vlast = fhp; - fhp->vhead = vp; - - fhp->file = file; - file->private_data = fhp; - v4l2_prio_open(&vp->prio, &fhp->prio); - - fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw); - - return 0; -} - - -static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp) -{ - wake_up(&fhp->wait_data); -} - -static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh) -{ - int ret; - struct pvr2_stream *sp; - struct pvr2_hdw *hdw; - if (fh->rhp) return 0; - - if (!fh->pdi->stream) { - /* No stream defined for this node. This means that we're - not currently allowed to stream from this node. */ - return -EPERM; - } - - /* First read() attempt. Try to claim the stream and start - it... */ - if ((ret = pvr2_channel_claim_stream(&fh->channel, - fh->pdi->stream)) != 0) { - /* Someone else must already have it */ - return ret; - } - - fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream); - if (!fh->rhp) { - pvr2_channel_claim_stream(&fh->channel,NULL); - return -ENOMEM; - } - - hdw = fh->channel.mc_head->hdw; - sp = fh->pdi->stream->stream; - pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh); - pvr2_hdw_set_stream_type(hdw,fh->pdi->config); - if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret; - return pvr2_ioread_set_enabled(fh->rhp,!0); -} - - -static ssize_t pvr2_v4l2_read(struct file *file, - char __user *buff, size_t count, loff_t *ppos) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - int ret; - - if (fh->fw_mode_flag) { - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - char *tbuf; - int c1,c2; - int tcnt = 0; - unsigned int offs = *ppos; - - tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL); - if (!tbuf) return -ENOMEM; - - while (count) { - c1 = count; - if (c1 > PAGE_SIZE) c1 = PAGE_SIZE; - c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1); - if (c2 < 0) { - tcnt = c2; - break; - } - if (!c2) break; - if (copy_to_user(buff,tbuf,c2)) { - tcnt = -EFAULT; - break; - } - offs += c2; - tcnt += c2; - buff += c2; - count -= c2; - *ppos += c2; - } - kfree(tbuf); - return tcnt; - } - - if (!fh->rhp) { - ret = pvr2_v4l2_iosetup(fh); - if (ret) { - return ret; - } - } - - for (;;) { - ret = pvr2_ioread_read(fh->rhp,buff,count); - if (ret >= 0) break; - if (ret != -EAGAIN) break; - if (file->f_flags & O_NONBLOCK) break; - /* Doing blocking I/O. Wait here. */ - ret = wait_event_interruptible( - fh->wait_data, - pvr2_ioread_avail(fh->rhp) >= 0); - if (ret < 0) break; - } - - return ret; -} - - -static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait) -{ - unsigned int mask = 0; - struct pvr2_v4l2_fh *fh = file->private_data; - int ret; - - if (fh->fw_mode_flag) { - mask |= POLLIN | POLLRDNORM; - return mask; - } - - if (!fh->rhp) { - ret = pvr2_v4l2_iosetup(fh); - if (ret) return POLLERR; - } - - poll_wait(file,&fh->wait_data,wait); - - if (pvr2_ioread_avail(fh->rhp) >= 0) { - mask |= POLLIN | POLLRDNORM; - } - - return mask; -} - - -static const struct v4l2_file_operations vdev_fops = { - .owner = THIS_MODULE, - .open = pvr2_v4l2_open, - .release = pvr2_v4l2_release, - .read = pvr2_v4l2_read, - .ioctl = pvr2_v4l2_ioctl, - .poll = pvr2_v4l2_poll, -}; - - -static struct video_device vdev_template = { - .fops = &vdev_fops, -}; - - -static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, - struct pvr2_v4l2 *vp, - int v4l_type) -{ - struct usb_device *usbdev; - int mindevnum; - int unit_number; - struct pvr2_hdw *hdw; - int *nr_ptr = NULL; - dip->v4lp = vp; - - hdw = vp->channel.mc_head->hdw; - usbdev = pvr2_hdw_get_dev(hdw); - dip->v4l_type = v4l_type; - switch (v4l_type) { - case VFL_TYPE_GRABBER: - dip->stream = &vp->channel.mc_head->video_stream; - dip->config = pvr2_config_mpeg; - dip->minor_type = pvr2_v4l_type_video; - nr_ptr = video_nr; - if (!dip->stream) { - pr_err(KBUILD_MODNAME - ": Failed to set up pvrusb2 v4l video dev" - " due to missing stream instance\n"); - return; - } - break; - case VFL_TYPE_VBI: - dip->config = pvr2_config_vbi; - dip->minor_type = pvr2_v4l_type_vbi; - nr_ptr = vbi_nr; - break; - case VFL_TYPE_RADIO: - dip->stream = &vp->channel.mc_head->video_stream; - dip->config = pvr2_config_mpeg; - dip->minor_type = pvr2_v4l_type_radio; - nr_ptr = radio_nr; - break; - default: - /* Bail out (this should be impossible) */ - pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev" - " due to unrecognized config\n"); - return; - } - - memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template)); - dip->devbase.release = pvr2_video_device_release; - dip->devbase.ioctl_ops = &pvr2_ioctl_ops; - { - int val; - pvr2_ctrl_get_value( - pvr2_hdw_get_ctrl_by_id(hdw, - PVR2_CID_STDAVAIL), &val); - dip->devbase.tvnorms = (v4l2_std_id)val; - } - - mindevnum = -1; - unit_number = pvr2_hdw_get_unit_number(hdw); - if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) { - mindevnum = nr_ptr[unit_number]; - } - dip->devbase.parent = &usbdev->dev; - if ((video_register_device(&dip->devbase, - dip->v4l_type, mindevnum) < 0) && - (video_register_device(&dip->devbase, - dip->v4l_type, -1) < 0)) { - pr_err(KBUILD_MODNAME - ": Failed to register pvrusb2 v4l device\n"); - } - - printk(KERN_INFO "pvrusb2: registered device %s [%s]\n", - video_device_node_name(&dip->devbase), - pvr2_config_get_name(dip->config)); - - pvr2_hdw_v4l_store_minor_number(hdw, - dip->minor_type,dip->devbase.minor); -} - - -struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) -{ - struct pvr2_v4l2 *vp; - - vp = kzalloc(sizeof(*vp),GFP_KERNEL); - if (!vp) return vp; - pvr2_channel_init(&vp->channel,mnp); - pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp); - - vp->channel.check_func = pvr2_v4l2_internal_check; - - /* register streams */ - vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL); - if (!vp->dev_video) goto fail; - pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER); - if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) & - (1 << PVR2_CVAL_INPUT_RADIO)) { - vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL); - if (!vp->dev_radio) goto fail; - pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO); - } - - return vp; - fail: - pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp); - pvr2_v4l2_destroy_no_lock(vp); - return NULL; -} - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-v4l2.h deleted file mode 100644 index 34c011a7b107..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __PVRUSB2_V4L2_H -#define __PVRUSB2_V4L2_H - -#include "pvrusb2-context.h" - -struct pvr2_v4l2; - -struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *); - -#endif /* __PVRUSB2_V4L2_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c deleted file mode 100644 index 2e205c99eb96..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* - - This source file is specifically designed to interface with the - saa711x support that is available in the v4l available starting - with linux 2.6.15. - -*/ - -#include "pvrusb2-video-v4l.h" - - - -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-debug.h" -#include <linux/videodev2.h> -#include <media/v4l2-common.h> -#include <media/saa7115.h> -#include <linux/errno.h> - -struct routing_scheme { - const int *def; - unsigned int cnt; -}; - - -static const int routing_scheme0[] = { - [PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4, - /* In radio mode, we mute the video, but point at one - spot just to stay consistent */ - [PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5, - [PVR2_CVAL_INPUT_COMPOSITE] = SAA7115_COMPOSITE5, - [PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2, -}; - -static const struct routing_scheme routing_def0 = { - .def = routing_scheme0, - .cnt = ARRAY_SIZE(routing_scheme0), -}; - -static const int routing_scheme1[] = { - [PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4, - [PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5, - [PVR2_CVAL_INPUT_COMPOSITE] = SAA7115_COMPOSITE3, - [PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2, /* or SVIDEO0, it seems */ -}; - -static const struct routing_scheme routing_def1 = { - .def = routing_scheme1, - .cnt = ARRAY_SIZE(routing_scheme1), -}; - -static const struct routing_scheme *routing_schemes[] = { - [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0, - [PVR2_ROUTING_SCHEME_ONAIR] = &routing_def1, -}; - -void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) -{ - if (hdw->input_dirty || hdw->force_dirty) { - const struct routing_scheme *sp; - unsigned int sid = hdw->hdw_desc->signal_routing_scheme; - u32 input; - - pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", - hdw->input_val); - - sp = (sid < ARRAY_SIZE(routing_schemes)) ? - routing_schemes[sid] : NULL; - if ((sp == NULL) || - (hdw->input_val < 0) || - (hdw->input_val >= sp->cnt)) { - pvr2_trace(PVR2_TRACE_ERROR_LEGS, - "*** WARNING *** subdev v4l2 set_input:" - " Invalid routing scheme (%u)" - " and/or input (%d)", - sid, hdw->input_val); - return; - } - input = sp->def[hdw->input_val]; - sd->ops->video->s_routing(sd, input, 0, 0); - } -} - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h deleted file mode 100644 index 3b0bd5db602b..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef __PVRUSB2_VIDEO_V4L_H -#define __PVRUSB2_VIDEO_V4L_H - -/* - - This module connects the pvrusb2 driver to the I2C chip level - driver which handles device video processing. This interface is - used internally by the driver; higher level code should only - interact through the interface provided by pvrusb2-hdw.h. - -*/ - - -#include "pvrusb2-hdw-internal.h" -void pvr2_saa7115_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); - -#endif /* __PVRUSB2_VIDEO_V4L_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c deleted file mode 100644 index 3ac8d751a5c0..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* - - This source file is specifically designed to interface with the - wm8775. - -*/ - -#include "pvrusb2-wm8775.h" - - -#include "pvrusb2-hdw-internal.h" -#include "pvrusb2-debug.h" -#include <linux/videodev2.h> -#include <media/v4l2-common.h> -#include <linux/errno.h> - -void pvr2_wm8775_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) -{ - if (hdw->input_dirty || hdw->force_dirty) { - u32 input; - - switch (hdw->input_val) { - case PVR2_CVAL_INPUT_RADIO: - input = 1; - break; - default: - /* All other cases just use the second input */ - input = 2; - break; - } - pvr2_trace(PVR2_TRACE_CHIPS, "subdev wm8775" - " set_input(val=%d route=0x%x)", - hdw->input_val, input); - - sd->ops->audio->s_routing(sd, input, 0, 0); - } -} - - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h deleted file mode 100644 index 0577bc7246fb..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef __PVRUSB2_WM8775_H -#define __PVRUSB2_WM8775_H - -/* - - This module connects the pvrusb2 driver to the I2C chip level - driver which performs analog -> digital audio conversion for - external audio inputs. This interface is used internally by the - driver; higher level code should only interact through the - interface provided by pvrusb2-hdw.h. - -*/ - - - -#include "pvrusb2-hdw-internal.h" - -void pvr2_wm8775_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd); - - -#endif /* __PVRUSB2_WM8775_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pvrusb2/pvrusb2.h b/drivers/media/video/pvrusb2/pvrusb2.h deleted file mode 100644 index 240de9b35661..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * - * Copyright (C) 2005 Mike Isely <isely@pobox.com> - * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> - * - * 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 - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef __PVRUSB2_H -#define __PVRUSB2_H - -/* Maximum number of pvrusb2 instances we can track at once. You - might want to increase this - however the driver operation will not - be impaired if it is too small. Instead additional units just - won't have an ID assigned and it might not be possible to specify - module parameters for those extra units. */ -#define PVR_NUM 20 - -#endif /* __PVRUSB2_H */ - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 70 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig deleted file mode 100644 index d63d0a850035..000000000000 --- a/drivers/media/video/pwc/Kconfig +++ /dev/null @@ -1,48 +0,0 @@ -config USB_PWC - tristate "USB Philips Cameras" - depends on VIDEO_V4L2 - select VIDEOBUF2_VMALLOC - ---help--- - Say Y or M here if you want to use one of these Philips & OEM - webcams: - * Philips PCA645, PCA646 - * Philips PCVC675, PCVC680, PCVC690 - * Philips PCVC720/40, PCVC730, PCVC740, PCVC750 - * Philips SPC900NC - * Askey VC010 - * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro' - and 'Orbit'/'Sphere' - * Samsung MPC-C10, MPC-C30 - * Creative Webcam 5, Pro Ex - * SOTEC Afina Eye - * Visionite VCS-UC300, VCS-UM100 - - The PCA635, PCVC665 and PCVC720/20 are not supported by this driver - and never will be, but the 665 and 720/20 are supported by other - drivers. - - Some newer logitech webcams are not handled by this driver but by the - Usb Video Class driver (linux-uvc). - - The built-in microphone is enabled by selecting USB Audio support. - - To compile this driver as a module, choose M here: the - module will be called pwc. - -config USB_PWC_DEBUG - bool "USB Philips Cameras verbose debug" - depends on USB_PWC - help - Say Y here in order to have the pwc driver generate verbose debugging - messages. - A special module options 'trace' is used to control the verbosity. - -config USB_PWC_INPUT_EVDEV - bool "USB Philips Cameras input events device support" - default y - depends on USB_PWC && (USB_PWC=INPUT || INPUT=y) - ---help--- - This option makes USB Philips cameras register the snapshot button as - an input device to report button events. - - If you are in doubt, say Y. diff --git a/drivers/media/video/pwc/Makefile b/drivers/media/video/pwc/Makefile deleted file mode 100644 index f5c8ec261e87..000000000000 --- a/drivers/media/video/pwc/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-v4l.o pwc-uncompress.o -pwc-objs += pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o - -obj-$(CONFIG_USB_PWC) += pwc.o diff --git a/drivers/media/video/pwc/philips.txt b/drivers/media/video/pwc/philips.txt deleted file mode 100644 index d38dd791511e..000000000000 --- a/drivers/media/video/pwc/philips.txt +++ /dev/null @@ -1,236 +0,0 @@ -This file contains some additional information for the Philips and OEM webcams. -E-mail: webcam@smcc.demon.nl Last updated: 2004-01-19 -Site: http://www.smcc.demon.nl/webcam/ - -As of this moment, the following cameras are supported: - * Philips PCA645 - * Philips PCA646 - * Philips PCVC675 - * Philips PCVC680 - * Philips PCVC690 - * Philips PCVC720/40 - * Philips PCVC730 - * Philips PCVC740 - * Philips PCVC750 - * Askey VC010 - * Creative Labs Webcam 5 - * Creative Labs Webcam Pro Ex - * Logitech QuickCam 3000 Pro - * Logitech QuickCam 4000 Pro - * Logitech QuickCam Notebook Pro - * Logitech QuickCam Zoom - * Logitech QuickCam Orbit - * Logitech QuickCam Sphere - * Samsung MPC-C10 - * Samsung MPC-C30 - * Sotec Afina Eye - * AME CU-001 - * Visionite VCS-UM100 - * Visionite VCS-UC300 - -The main webpage for the Philips driver is at the address above. It contains -a lot of extra information, a FAQ, and the binary plugin 'PWCX'. This plugin -contains decompression routines that allow you to use higher image sizes and -framerates; in addition the webcam uses less bandwidth on the USB bus (handy -if you want to run more than 1 camera simultaneously). These routines fall -under a NDA, and may therefore not be distributed as source; however, its use -is completely optional. - -You can build this code either into your kernel, or as a module. I recommend -the latter, since it makes troubleshooting a lot easier. The built-in -microphone is supported through the USB Audio class. - -When you load the module you can set some default settings for the -camera; some programs depend on a particular image-size or -format and -don't know how to set it properly in the driver. The options are: - -size - Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or - 'vga', for an image size of resp. 128x96, 160x120, 176x144, - 320x240, 352x288 and 640x480 (of course, only for those cameras that - support these resolutions). - -fps - Specifies the desired framerate. Is an integer in the range of 4-30. - -fbufs - 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 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. - -mbufs - This is an integer between 1 and 10. It will tell the module the number of - buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends. - The default is 2, which is adequate for most applications (double - buffering). - - Should you experience a lot of 'Dumping frame...' messages during - grabbing with a tool that uses mmap(), you might want to increase if. - However, it doesn't really buffer images, it just gives you a bit more - slack when your program is behind. But you need a multi-threaded or - forked program to really take advantage of these buffers. - - The absolute maximum is 10, but don't set it too high! Every buffer takes - up 460 KB of RAM, so unless you have a lot of memory setting this to - something more than 4 is an absolute waste. This memory is only - allocated during open(), so nothing is wasted when the camera is not in - use. - -power_save - When power_save is enabled (set to 1), the module will try to shut down - the cam on close() and re-activate on open(). This will save power and - turn off the LED. Not all cameras support this though (the 645 and 646 - don't have power saving at all), and some models don't work either (they - will shut down, but never wake up). Consider this experimental. By - default this option is disabled. - -compression (only useful with the plugin) - With this option you can control the compression factor that the camera - uses to squeeze the image through the USB bus. You can set the - parameter between 0 and 3: - 0 = prefer uncompressed images; if the requested mode is not available - in an uncompressed format, the driver will silently switch to low - compression. - 1 = low compression. - 2 = medium compression. - 3 = high compression. - - High compression takes less bandwidth of course, but it could also - introduce some unwanted artefacts. The default is 2, medium compression. - See the FAQ on the website for an overview of which modes require - compression. - - The compression parameter does not apply to the 645 and 646 cameras - and OEM models derived from those (only a few). Most cams honour this - parameter. - -leds - This settings takes 2 integers, that define the on/off time for the LED - (in milliseconds). One of the interesting things that you can do with - this is let the LED blink while the camera is in use. This: - - leds=500,500 - - will blink the LED once every second. But with: - - leds=0,0 - - the LED never goes on, making it suitable for silent surveillance. - - By default the camera's LED is on solid while in use, and turned off - when the camera is not used anymore. - - This parameter works only with the ToUCam range of cameras (720, 730, 740, - 750) and OEMs. For other cameras this command is silently ignored, and - the LED cannot be controlled. - - Finally: this parameters does not take effect UNTIL the first time you - open the camera device. Until then, the LED remains on. - -dev_hint - A long standing problem with USB devices is their dynamic nature: you - never know what device a camera gets assigned; it depends on module load - order, the hub configuration, the order in which devices are plugged in, - and the phase of the moon (i.e. it can be random). With this option you - can give the driver a hint as to what video device node (/dev/videoX) it - should use with a specific camera. This is also handy if you have two - cameras of the same model. - - A camera is specified by its type (the number from the camera model, - like PCA645, PCVC750VC, etc) and optionally the serial number (visible - in /proc/bus/usb/devices). A hint consists of a string with the following - format: - - [type[.serialnumber]:]node - - The square brackets mean that both the type and the serialnumber are - optional, but a serialnumber cannot be specified without a type (which - would be rather pointless). The serialnumber is separated from the type - by a '.'; the node number by a ':'. - - This somewhat cryptic syntax is best explained by a few examples: - - dev_hint=3,5 The first detected cam gets assigned - /dev/video3, the second /dev/video5. Any - other cameras will get the first free - available slot (see below). - - dev_hint=645:1,680:2 The PCA645 camera will get /dev/video1, - and a PCVC680 /dev/video2. - - dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber - 0123 goes to /dev/video3, the same - camera model with the 4567 serial - gets /dev/video0. - - dev_hint=750:1,4,5,6 The PCVC750 camera will get /dev/video1, the - next 3 Philips cams will use /dev/video4 - through /dev/video6. - - Some points worth knowing: - - Serialnumbers are case sensitive and must be written full, including - leading zeroes (it's treated as a string). - - If a device node is already occupied, registration will fail and - the webcam is not available. - - You can have up to 64 video devices; be sure to make enough device - nodes in /dev if you want to spread the numbers. - After /dev/video9 comes /dev/video10 (not /dev/videoA). - - If a camera does not match any dev_hint, it will simply get assigned - the first available device node, just as it used to be. - -trace - In order to better detect problems, it is now possible to turn on a - 'trace' of some of the calls the module makes; it logs all items in your - kernel log at debug level. - - The trace variable is a bitmask; each bit represents a certain feature. - If you want to trace something, look up the bit value(s) in the table - below, add the values together and supply that to the trace variable. - - Value Value Description Default - (dec) (hex) - 1 0x1 Module initialization; this will log messages On - while loading and unloading the module - - 2 0x2 probe() and disconnect() traces On - - 4 0x4 Trace open() and close() calls Off - - 8 0x8 read(), mmap() and associated ioctl() calls Off - - 16 0x10 Memory allocation of buffers, etc. Off - - 32 0x20 Showing underflow, overflow and Dumping frame On - messages - - 64 0x40 Show viewport and image sizes Off - - 128 0x80 PWCX debugging Off - - 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). - - - -Example: - - # modprobe pwc size=cif fps=15 power_save=1 - -The fbufs, mbufs and trace parameters are global and apply to all connected -cameras. Each camera has its own set of buffers. - -size and fps only specify defaults when you open() the device; this is to -accommodate some tools that don't set the size. You can change these -settings after open() with the Video4Linux ioctl() calls. The default of -defaults is QCIF size at 10 fps. - -The compression parameter is semiglobal; it sets the initial compression -preference for all camera's, but this parameter can be set per camera with -the VIDIOCPWCSCQUAL ioctl() call. - -All parameters are optional. - diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c deleted file mode 100644 index 1f506fde97d0..000000000000 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ /dev/null @@ -1,553 +0,0 @@ -/* Driver for Philips webcam - Functions that send various control messages to the webcam, including - video modes. - (C) 1999-2003 Nemosoft Unv. - (C) 2004-2006 Luc Saillard (luc@saillard.org) - (C) 2011 Hans de Goede <hdegoede@redhat.com> - - 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. - Please send bug reports and support requests to <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. - Please send bug reports and support requests to <luc@saillard.org>. - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - Changes - 2001/08/03 Alvarado Added methods for changing white balance and - red/green gains - */ - -/* Control functions for the cam; brightness, contrast, video mode, etc. */ - -#ifdef __KERNEL__ -#include <asm/uaccess.h> -#endif -#include <asm/errno.h> - -#include "pwc.h" -#include "pwc-kiara.h" -#include "pwc-timon.h" -#include "pwc-dec1.h" -#include "pwc-dec23.h" - -/* Selectors for status controls used only in this file */ -#define GET_STATUS_B00 0x0B00 -#define SENSOR_TYPE_FORMATTER1 0x0C00 -#define GET_STATUS_3000 0x3000 -#define READ_RAW_Y_MEAN_FORMATTER 0x3100 -#define SET_POWER_SAVE_MODE_FORMATTER 0x3200 -#define MIRROR_IMAGE_FORMATTER 0x3300 -#define LED_FORMATTER 0x3400 -#define LOWLIGHT 0x3500 -#define GET_STATUS_3600 0x3600 -#define SENSOR_TYPE_FORMATTER2 0x3700 -#define GET_STATUS_3800 0x3800 -#define GET_STATUS_4000 0x4000 -#define GET_STATUS_4100 0x4100 /* Get */ -#define CTL_STATUS_4200 0x4200 /* [GS] 1 */ - -/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */ -#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100 - -static const char *size2name[PSZ_MAX] = -{ - "subQCIF", - "QSIF", - "QCIF", - "SIF", - "CIF", - "VGA", -}; - -/********/ - -/* Entries for the Nala (645/646) camera; the Nala doesn't have compression - preferences, so you either get compressed or non-compressed streams. - - 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 */ - - unsigned char mode[3]; /* precomputed mode table */ -}; - -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" -}; - -/****************************************************************************/ - -static int recv_control_msg(struct pwc_device *pdev, - u8 request, u16 value, int recv_count) -{ - int rc; - - rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), - request, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, pdev->vcinterface, - pdev->ctrl_buf, recv_count, USB_CTRL_GET_TIMEOUT); - if (rc < 0) - PWC_ERROR("recv_control_msg error %d req %02x val %04x\n", - rc, request, value); - return rc; -} - -static inline int send_video_command(struct pwc_device *pdev, - int index, const unsigned char *buf, int buflen) -{ - int rc; - - memcpy(pdev->ctrl_buf, buf, buflen); - - rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), - SET_EP_STREAM_CTL, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - VIDEO_OUTPUT_CONTROL_FORMATTER, index, - pdev->ctrl_buf, buflen, USB_CTRL_SET_TIMEOUT); - if (rc >= 0) - memcpy(pdev->cmd_buf, buf, buflen); - else - PWC_ERROR("send_video_command error %d\n", rc); - - return rc; -} - -int send_control_msg(struct pwc_device *pdev, - u8 request, u16 value, void *buf, int buflen) -{ - return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), - request, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, pdev->vcinterface, - buf, buflen, USB_CTRL_SET_TIMEOUT); -} - -static int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt, - int frames, int *compression, int send_to_cam) -{ - int fps, ret = 0; - struct Nala_table_entry *pEntry; - int frames2frames[31] = - { /* closest match of framerate */ - 0, 0, 0, 0, 4, /* 0-4 */ - 5, 5, 7, 7, 10, /* 5-9 */ - 10, 10, 12, 12, 15, /* 10-14 */ - 15, 15, 15, 20, 20, /* 15-19 */ - 20, 20, 20, 24, 24, /* 20-24 */ - 24, 24, 24, 24, 24, /* 25-29 */ - 24 /* 30 */ - }; - int frames2table[31] = - { 0, 0, 0, 0, 0, /* 0-4 */ - 1, 1, 1, 2, 2, /* 5-9 */ - 3, 3, 4, 4, 4, /* 10-14 */ - 5, 5, 5, 5, 5, /* 15-19 */ - 6, 6, 6, 6, 7, /* 20-24 */ - 7, 7, 7, 7, 7, /* 25-29 */ - 7 /* 30 */ - }; - - if (size < 0 || size > PSZ_CIF) - return -EINVAL; - if (frames < 4) - frames = 4; - else if (frames > 25) - frames = 25; - frames = frames2frames[frames]; - fps = frames2table[frames]; - pEntry = &Nala_table[size][fps]; - if (pEntry->alternate == 0) - return -EINVAL; - - if (send_to_cam) - ret = send_video_command(pdev, pdev->vendpoint, - pEntry->mode, 3); - if (ret < 0) - return ret; - - if (pEntry->compressed && pixfmt == V4L2_PIX_FMT_YUV420) - pwc_dec1_init(pdev, pEntry->mode); - - /* Set various parameters */ - pdev->pixfmt = pixfmt; - pdev->vframes = frames; - pdev->valternate = pEntry->alternate; - pdev->width = pwc_image_sizes[size][0]; - pdev->height = pwc_image_sizes[size][1]; - pdev->frame_size = (pdev->width * pdev->height * 3) / 2; - if (pEntry->compressed) { - if (pdev->release < 5) { /* 4 fold compression */ - pdev->vbandlength = 528; - pdev->frame_size /= 4; - } - else { - pdev->vbandlength = 704; - pdev->frame_size /= 3; - } - } - else - pdev->vbandlength = 0; - - /* Let pwc-if.c:isoc_init know we don't support higher compression */ - *compression = 3; - - return 0; -} - - -static int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt, - int frames, int *compression, int send_to_cam) -{ - const struct Timon_table_entry *pChoose; - int fps, ret = 0; - - if (size >= PSZ_MAX || *compression < 0 || *compression > 3) - return -EINVAL; - if (frames < 5) - frames = 5; - else if (size == PSZ_VGA && frames > 15) - frames = 15; - else if (frames > 30) - frames = 30; - fps = (frames / 5) - 1; - - /* Find a supported framerate with progressively higher compression */ - pChoose = NULL; - while (*compression <= 3) { - pChoose = &Timon_table[size][fps][*compression]; - if (pChoose->alternate != 0) - break; - (*compression)++; - } - if (pChoose == NULL || pChoose->alternate == 0) - return -ENOENT; /* Not supported. */ - - if (send_to_cam) - ret = send_video_command(pdev, pdev->vendpoint, - pChoose->mode, 13); - if (ret < 0) - return ret; - - if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420) - pwc_dec23_init(pdev, pChoose->mode); - - /* Set various parameters */ - pdev->pixfmt = pixfmt; - pdev->vframes = (fps + 1) * 5; - pdev->valternate = pChoose->alternate; - pdev->width = pwc_image_sizes[size][0]; - pdev->height = pwc_image_sizes[size][1]; - pdev->vbandlength = pChoose->bandlength; - if (pChoose->bandlength > 0) - pdev->frame_size = (pChoose->bandlength * pdev->height) / 4; - else - pdev->frame_size = (pdev->width * pdev->height * 12) / 8; - return 0; -} - - -static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt, - int frames, int *compression, int send_to_cam) -{ - const struct Kiara_table_entry *pChoose = NULL; - int fps, ret = 0; - - if (size >= PSZ_MAX || *compression < 0 || *compression > 3) - return -EINVAL; - if (frames < 5) - frames = 5; - else if (size == PSZ_VGA && frames > 15) - frames = 15; - else if (frames > 30) - frames = 30; - fps = (frames / 5) - 1; - - /* Find a supported framerate with progressively higher compression */ - while (*compression <= 3) { - pChoose = &Kiara_table[size][fps][*compression]; - if (pChoose->alternate != 0) - break; - (*compression)++; - } - if (pChoose == NULL || pChoose->alternate == 0) - return -ENOENT; /* Not supported. */ - - /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */ - if (send_to_cam) - ret = send_video_command(pdev, 4, pChoose->mode, 12); - if (ret < 0) - return ret; - - if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420) - pwc_dec23_init(pdev, pChoose->mode); - - /* All set and go */ - pdev->pixfmt = pixfmt; - pdev->vframes = (fps + 1) * 5; - pdev->valternate = pChoose->alternate; - pdev->width = pwc_image_sizes[size][0]; - pdev->height = pwc_image_sizes[size][1]; - pdev->vbandlength = pChoose->bandlength; - if (pdev->vbandlength > 0) - pdev->frame_size = (pdev->vbandlength * pdev->height) / 4; - else - pdev->frame_size = (pdev->width * pdev->height * 12) / 8; - PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n", - pdev->frame_size, pdev->vframes, size, pdev->vbandlength); - return 0; -} - -int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, - int pixfmt, int frames, int *compression, int send_to_cam) -{ - int ret, size; - - PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", - width, height, frames, pixfmt); - size = pwc_get_size(pdev, width, height); - PWC_TRACE("decode_size = %d.\n", size); - - if (DEVICE_USE_CODEC1(pdev->type)) { - ret = set_video_mode_Nala(pdev, size, pixfmt, frames, - compression, send_to_cam); - } else if (DEVICE_USE_CODEC3(pdev->type)) { - ret = set_video_mode_Kiara(pdev, size, pixfmt, frames, - compression, send_to_cam); - } else { - ret = set_video_mode_Timon(pdev, size, pixfmt, frames, - compression, send_to_cam); - } - if (ret < 0) { - PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); - return ret; - } - pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size; - PWC_DEBUG_SIZE("Set resolution to %dx%d\n", pdev->width, pdev->height); - 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; -} - -int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data) -{ - int ret; - - ret = recv_control_msg(pdev, request, value, 1); - if (ret < 0) - return ret; - - *data = pdev->ctrl_buf[0]; - return 0; -} - -int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data) -{ - int ret; - - pdev->ctrl_buf[0] = data; - ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 1); - if (ret < 0) - return ret; - - return 0; -} - -int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data) -{ - int ret; - - ret = recv_control_msg(pdev, request, value, 1); - if (ret < 0) - return ret; - - *data = ((s8 *)pdev->ctrl_buf)[0]; - return 0; -} - -int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data) -{ - int ret; - - ret = recv_control_msg(pdev, request, value, 2); - if (ret < 0) - return ret; - - *data = (pdev->ctrl_buf[1] << 8) | pdev->ctrl_buf[0]; - return 0; -} - -int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data) -{ - int ret; - - pdev->ctrl_buf[0] = data & 0xff; - pdev->ctrl_buf[1] = data >> 8; - ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 2); - if (ret < 0) - return ret; - - return 0; -} - -int pwc_button_ctrl(struct pwc_device *pdev, u16 value) -{ - int ret; - - ret = send_control_msg(pdev, SET_STATUS_CTL, value, NULL, 0); - if (ret < 0) - return ret; - - return 0; -} - -/* POWER */ -void pwc_camera_power(struct pwc_device *pdev, int power) -{ - int r; - - if (!pdev->power_save) - return; - - if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6)) - return; /* Not supported by Nala or Timon < release 6 */ - - if (power) - pdev->ctrl_buf[0] = 0x00; /* active */ - else - pdev->ctrl_buf[0] = 0xFF; /* power save */ - r = send_control_msg(pdev, SET_STATUS_CTL, - SET_POWER_SAVE_MODE_FORMATTER, pdev->ctrl_buf, 1); - if (r < 0) - PWC_ERROR("Failed to power %s camera (%d)\n", - power ? "on" : "off", r); -} - -int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value) -{ - int r; - - if (pdev->type < 730) - return 0; - on_value /= 100; - off_value /= 100; - if (on_value < 0) - on_value = 0; - if (on_value > 0xff) - on_value = 0xff; - if (off_value < 0) - off_value = 0; - if (off_value > 0xff) - off_value = 0xff; - - pdev->ctrl_buf[0] = on_value; - pdev->ctrl_buf[1] = off_value; - - r = send_control_msg(pdev, - SET_STATUS_CTL, LED_FORMATTER, pdev->ctrl_buf, 2); - if (r < 0) - PWC_ERROR("Failed to set LED on/off time (%d)\n", r); - - return r; -} - -#ifdef CONFIG_USB_PWC_DEBUG -int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) -{ - int ret = -1, request; - - if (pdev->type < 675) - request = SENSOR_TYPE_FORMATTER1; - else if (pdev->type < 730) - return -1; /* The Vesta series doesn't have this call */ - else - request = SENSOR_TYPE_FORMATTER2; - - ret = recv_control_msg(pdev, GET_STATUS_CTL, request, 1); - if (ret < 0) - return ret; - if (pdev->type < 675) - *sensor = pdev->ctrl_buf[0] | 0x100; - else - *sensor = pdev->ctrl_buf[0]; - return 0; -} -#endif diff --git a/drivers/media/video/pwc/pwc-dec1.c b/drivers/media/video/pwc/pwc-dec1.c deleted file mode 100644 index e899036aadf4..000000000000 --- a/drivers/media/video/pwc/pwc-dec1.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Linux driver for Philips webcam - Decompression for chipset version 1 - (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. - Please send bug reports and support requests to <luc@saillard.org>. - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include "pwc.h" - -void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd) -{ - struct pwc_dec1_private *pdec = &pdev->dec1; - - pdec->version = pdev->release; -} diff --git a/drivers/media/video/pwc/pwc-dec1.h b/drivers/media/video/pwc/pwc-dec1.h deleted file mode 100644 index c565ef8f52fb..000000000000 --- a/drivers/media/video/pwc/pwc-dec1.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Linux driver for Philips webcam - (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. - Please send bug reports and support requests to <luc@saillard.org>. - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef PWC_DEC1_H -#define PWC_DEC1_H - -#include <linux/mutex.h> - -struct pwc_device; - -struct pwc_dec1_private -{ - int version; -}; - -void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd); - -#endif diff --git a/drivers/media/video/pwc/pwc-dec23.c b/drivers/media/video/pwc/pwc-dec23.c deleted file mode 100644 index 3792fedff951..000000000000 --- a/drivers/media/video/pwc/pwc-dec23.c +++ /dev/null @@ -1,691 +0,0 @@ -/* Linux driver for Philips webcam - Decompression for chipset version 2 et 3 - (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. - Please send bug reports and support requests to <luc@saillard.org>. - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "pwc-timon.h" -#include "pwc-kiara.h" -#include "pwc-dec23.h" - -#include <linux/string.h> -#include <linux/slab.h> - -/* - * USE_LOOKUP_TABLE_TO_CLAMP - * 0: use a C version of this tests: { a<0?0:(a>255?255:a) } - * 1: use a faster lookup table for cpu with a big cache (intel) - */ -#define USE_LOOKUP_TABLE_TO_CLAMP 1 -/* - * UNROLL_LOOP_FOR_COPYING_BLOCK - * 0: use a loop for a smaller code (but little slower) - * 1: when unrolling the loop, gcc produces some faster code (perhaps only - * valid for intel processor class). Activating this option, automaticaly - * activate USE_LOOKUP_TABLE_TO_CLAMP - */ -#define UNROLL_LOOP_FOR_COPY 1 -#if UNROLL_LOOP_FOR_COPY -# undef USE_LOOKUP_TABLE_TO_CLAMP -# define USE_LOOKUP_TABLE_TO_CLAMP 1 -#endif - -static void build_subblock_pattern(struct pwc_dec23_private *pdec) -{ - static const unsigned int initial_values[12] = { - -0x526500, -0x221200, 0x221200, 0x526500, - -0x3de200, 0x3de200, - -0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480, - -0x12c200, 0x12c200 - - }; - static const unsigned int values_derivated[12] = { - 0xa4ca, 0x4424, -0x4424, -0xa4ca, - 0x7bc4, -0x7bc4, - 0xdb69, 0x5aba, -0x5aba, -0xdb69, - 0x2584, -0x2584 - }; - unsigned int temp_values[12]; - int i, j; - - memcpy(temp_values, initial_values, sizeof(initial_values)); - for (i = 0; i < 256; i++) { - for (j = 0; j < 12; j++) { - pdec->table_subblock[i][j] = temp_values[j]; - temp_values[j] += values_derivated[j]; - } - } -} - -static void build_bit_powermask_table(struct pwc_dec23_private *pdec) -{ - unsigned char *p; - unsigned int bit, byte, mask, val; - unsigned int bitpower = 1; - - for (bit = 0; bit < 8; bit++) { - mask = bitpower - 1; - p = pdec->table_bitpowermask[bit]; - for (byte = 0; byte < 256; byte++) { - val = (byte & mask); - if (byte & bitpower) - val = -val; - *p++ = val; - } - bitpower<<=1; - } -} - - -static void build_table_color(const unsigned int romtable[16][8], - unsigned char p0004[16][1024], - unsigned char p8004[16][256]) -{ - int compression_mode, j, k, bit, pw; - unsigned char *p0, *p8; - const unsigned int *r; - - /* We have 16 compressions tables */ - for (compression_mode = 0; compression_mode < 16; compression_mode++) { - p0 = p0004[compression_mode]; - p8 = p8004[compression_mode]; - r = romtable[compression_mode]; - - for (j = 0; j < 8; j++, r++, p0 += 128) { - - for (k = 0; k < 16; k++) { - if (k == 0) - bit = 1; - else if (k >= 1 && k < 3) - bit = (r[0] >> 15) & 7; - else if (k >= 3 && k < 6) - bit = (r[0] >> 12) & 7; - else if (k >= 6 && k < 10) - bit = (r[0] >> 9) & 7; - else if (k >= 10 && k < 13) - bit = (r[0] >> 6) & 7; - else if (k >= 13 && k < 15) - bit = (r[0] >> 3) & 7; - else - bit = (r[0]) & 7; - if (k == 0) - *p8++ = 8; - else - *p8++ = j - bit; - *p8++ = bit; - - pw = 1 << bit; - p0[k + 0x00] = (1 * pw) + 0x80; - p0[k + 0x10] = (2 * pw) + 0x80; - p0[k + 0x20] = (3 * pw) + 0x80; - p0[k + 0x30] = (4 * pw) + 0x80; - p0[k + 0x40] = (-1 * pw) + 0x80; - p0[k + 0x50] = (-2 * pw) + 0x80; - p0[k + 0x60] = (-3 * pw) + 0x80; - p0[k + 0x70] = (-4 * pw) + 0x80; - } /* end of for (k=0; k<16; k++, p8++) */ - } /* end of for (j=0; j<8; j++ , table++) */ - } /* end of foreach compression_mode */ -} - -/* - * - */ -static void fill_table_dc00_d800(struct pwc_dec23_private *pdec) -{ -#define SCALEBITS 15 -#define ONE_HALF (1UL << (SCALEBITS - 1)) - int i; - unsigned int offset1 = ONE_HALF; - unsigned int offset2 = 0x0000; - - for (i=0; i<256; i++) { - pdec->table_dc00[i] = offset1 & ~(ONE_HALF); - pdec->table_d800[i] = offset2; - - offset1 += 0x7bc4; - offset2 += 0x7bc4; - } -} - -/* - * To decode the stream: - * if look_bits(2) == 0: # op == 2 in the lookup table - * skip_bits(2) - * end of the stream - * elif look_bits(3) == 7: # op == 1 in the lookup table - * skip_bits(3) - * yyyy = get_bits(4) - * xxxx = get_bits(8) - * else: # op == 0 in the lookup table - * skip_bits(x) - * - * For speedup processing, we build a lookup table and we takes the first 6 bits. - * - * struct { - * unsigned char op; // operation to execute - * unsigned char bits; // bits use to perform operation - * unsigned char offset1; // offset to add to access in the table_0004 % 16 - * unsigned char offset2; // offset to add to access in the table_0004 - * } - * - * How to build this table ? - * op == 2 when (i%4)==0 - * op == 1 when (i%8)==7 - * op == 0 otherwise - * - */ -static const unsigned char hash_table_ops[64*4] = { - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x00, - 0x00, 0x04, 0x01, 0x10, - 0x00, 0x06, 0x01, 0x30, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x40, - 0x00, 0x05, 0x01, 0x20, - 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x00, - 0x00, 0x04, 0x01, 0x50, - 0x00, 0x05, 0x02, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x40, - 0x00, 0x05, 0x03, 0x00, - 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x00, - 0x00, 0x04, 0x01, 0x10, - 0x00, 0x06, 0x02, 0x10, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x40, - 0x00, 0x05, 0x01, 0x60, - 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x00, - 0x00, 0x04, 0x01, 0x50, - 0x00, 0x05, 0x02, 0x40, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x40, - 0x00, 0x05, 0x03, 0x40, - 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x00, - 0x00, 0x04, 0x01, 0x10, - 0x00, 0x06, 0x01, 0x70, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x40, - 0x00, 0x05, 0x01, 0x20, - 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x00, - 0x00, 0x04, 0x01, 0x50, - 0x00, 0x05, 0x02, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x40, - 0x00, 0x05, 0x03, 0x00, - 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x00, - 0x00, 0x04, 0x01, 0x10, - 0x00, 0x06, 0x02, 0x50, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x40, - 0x00, 0x05, 0x01, 0x60, - 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x00, - 0x00, 0x04, 0x01, 0x50, - 0x00, 0x05, 0x02, 0x40, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x01, 0x40, - 0x00, 0x05, 0x03, 0x40, - 0x01, 0x00, 0x00, 0x00 -}; - -/* - * - */ -static const unsigned int MulIdx[16][16] = { - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, - {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,}, - {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,}, - {4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,}, - {6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,}, - {4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,}, - {1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,}, - {0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,}, - {0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,}, - {1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,}, - {7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,}, - {4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,}, - {7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,}, - {1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,}, - {1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,}, - {10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10} -}; - -#if USE_LOOKUP_TABLE_TO_CLAMP -#define MAX_OUTER_CROP_VALUE (512) -static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE]; -#define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)]) -#else -#define CLAMP(x) ((x)>255?255:((x)<0?0:x)) -#endif - - -/* If the type or the command change, we rebuild the lookup table */ -void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd) -{ - int flags, version, shift, i; - struct pwc_dec23_private *pdec = &pdev->dec23; - - mutex_init(&pdec->lock); - - if (pdec->last_cmd_valid && pdec->last_cmd == cmd[2]) - return; - - if (DEVICE_USE_CODEC3(pdev->type)) { - flags = cmd[2] & 0x18; - if (flags == 8) - pdec->nbits = 7; /* More bits, mean more bits to encode the stream, but better quality */ - else if (flags == 0x10) - pdec->nbits = 8; - else - pdec->nbits = 6; - - version = cmd[2] >> 5; - build_table_color(KiaraRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1); - build_table_color(KiaraRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2); - - } else { - - flags = cmd[2] & 6; - if (flags == 2) - pdec->nbits = 7; - else if (flags == 4) - pdec->nbits = 8; - else - pdec->nbits = 6; - - version = cmd[2] >> 3; - build_table_color(TimonRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1); - build_table_color(TimonRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2); - } - - /* Informations can be coded on a variable number of bits but never less than 8 */ - shift = 8 - pdec->nbits; - pdec->scalebits = SCALEBITS - shift; - pdec->nbitsmask = 0xFF >> shift; - - fill_table_dc00_d800(pdec); - build_subblock_pattern(pdec); - build_bit_powermask_table(pdec); - -#if USE_LOOKUP_TABLE_TO_CLAMP - /* Build the static table to clamp value [0-255] */ - for (i=0;i<MAX_OUTER_CROP_VALUE;i++) - pwc_crop_table[i] = 0; - for (i=0; i<256; i++) - pwc_crop_table[MAX_OUTER_CROP_VALUE+i] = i; - for (i=0; i<MAX_OUTER_CROP_VALUE; i++) - pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255; -#endif - - pdec->last_cmd = cmd[2]; - pdec->last_cmd_valid = 1; -} - -/* - * Copy the 4x4 image block to Y plane buffer - */ -static void copy_image_block_Y(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) -{ -#if UNROLL_LOOP_FOR_COPY - const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; - const int *c = src; - unsigned char *d = dst; - - *d++ = cm[c[0] >> scalebits]; - *d++ = cm[c[1] >> scalebits]; - *d++ = cm[c[2] >> scalebits]; - *d++ = cm[c[3] >> scalebits]; - - d = dst + bytes_per_line; - *d++ = cm[c[4] >> scalebits]; - *d++ = cm[c[5] >> scalebits]; - *d++ = cm[c[6] >> scalebits]; - *d++ = cm[c[7] >> scalebits]; - - d = dst + bytes_per_line*2; - *d++ = cm[c[8] >> scalebits]; - *d++ = cm[c[9] >> scalebits]; - *d++ = cm[c[10] >> scalebits]; - *d++ = cm[c[11] >> scalebits]; - - d = dst + bytes_per_line*3; - *d++ = cm[c[12] >> scalebits]; - *d++ = cm[c[13] >> scalebits]; - *d++ = cm[c[14] >> scalebits]; - *d++ = cm[c[15] >> scalebits]; -#else - int i; - const int *c = src; - unsigned char *d = dst; - for (i = 0; i < 4; i++, c++) - *d++ = CLAMP((*c) >> scalebits); - - d = dst + bytes_per_line; - for (i = 0; i < 4; i++, c++) - *d++ = CLAMP((*c) >> scalebits); - - d = dst + bytes_per_line*2; - for (i = 0; i < 4; i++, c++) - *d++ = CLAMP((*c) >> scalebits); - - d = dst + bytes_per_line*3; - for (i = 0; i < 4; i++, c++) - *d++ = CLAMP((*c) >> scalebits); -#endif -} - -/* - * Copy the 4x4 image block to a CrCb plane buffer - * - */ -static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) -{ -#if UNROLL_LOOP_FOR_COPY - /* Unroll all loops */ - const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; - const int *c = src; - unsigned char *d = dst; - - *d++ = cm[c[0] >> scalebits]; - *d++ = cm[c[4] >> scalebits]; - *d++ = cm[c[1] >> scalebits]; - *d++ = cm[c[5] >> scalebits]; - *d++ = cm[c[2] >> scalebits]; - *d++ = cm[c[6] >> scalebits]; - *d++ = cm[c[3] >> scalebits]; - *d++ = cm[c[7] >> scalebits]; - - d = dst + bytes_per_line; - *d++ = cm[c[12] >> scalebits]; - *d++ = cm[c[8] >> scalebits]; - *d++ = cm[c[13] >> scalebits]; - *d++ = cm[c[9] >> scalebits]; - *d++ = cm[c[14] >> scalebits]; - *d++ = cm[c[10] >> scalebits]; - *d++ = cm[c[15] >> scalebits]; - *d++ = cm[c[11] >> scalebits]; -#else - int i; - const int *c1 = src; - const int *c2 = src + 4; - unsigned char *d = dst; - - for (i = 0; i < 4; i++, c1++, c2++) { - *d++ = CLAMP((*c1) >> scalebits); - *d++ = CLAMP((*c2) >> scalebits); - } - c1 = src + 12; - d = dst + bytes_per_line; - for (i = 0; i < 4; i++, c1++, c2++) { - *d++ = CLAMP((*c1) >> scalebits); - *d++ = CLAMP((*c2) >> scalebits); - } -#endif -} - -/* - * To manage the stream, we keep bits in a 32 bits register. - * fill_nbits(n): fill the reservoir with at least n bits - * skip_bits(n): discard n bits from the reservoir - * get_bits(n): fill the reservoir, returns the first n bits and discard the - * bits from the reservoir. - * __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir - * contains at least n bits. bits returned is discarded. - */ -#define fill_nbits(pdec, nbits_wanted) do { \ - while (pdec->nbits_in_reservoir<(nbits_wanted)) \ - { \ - pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \ - pdec->nbits_in_reservoir += 8; \ - } \ -} while(0); - -#define skip_nbits(pdec, nbits_to_skip) do { \ - pdec->reservoir >>= (nbits_to_skip); \ - pdec->nbits_in_reservoir -= (nbits_to_skip); \ -} while(0); - -#define get_nbits(pdec, nbits_wanted, result) do { \ - fill_nbits(pdec, nbits_wanted); \ - result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \ - skip_nbits(pdec, nbits_wanted); \ -} while(0); - -#define __get_nbits(pdec, nbits_wanted, result) do { \ - result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \ - skip_nbits(pdec, nbits_wanted); \ -} while(0); - -#define look_nbits(pdec, nbits_wanted) \ - ((pdec->reservoir) & ((1U<<(nbits_wanted))-1)) - -/* - * Decode a 4x4 pixel block - */ -static void decode_block(struct pwc_dec23_private *pdec, - const unsigned char *ptable0004, - const unsigned char *ptable8004) -{ - unsigned int primary_color; - unsigned int channel_v, offset1, op; - int i; - - fill_nbits(pdec, 16); - __get_nbits(pdec, pdec->nbits, primary_color); - - if (look_nbits(pdec,2) == 0) { - skip_nbits(pdec, 2); - /* Very simple, the color is the same for all pixels of the square */ - for (i = 0; i < 16; i++) - pdec->temp_colors[i] = pdec->table_dc00[primary_color]; - - return; - } - - /* This block is encoded with small pattern */ - for (i = 0; i < 16; i++) - pdec->temp_colors[i] = pdec->table_d800[primary_color]; - - __get_nbits(pdec, 3, channel_v); - channel_v = ((channel_v & 1) << 2) | (channel_v & 2) | ((channel_v & 4) >> 2); - - ptable0004 += (channel_v * 128); - ptable8004 += (channel_v * 32); - - offset1 = 0; - do - { - unsigned int htable_idx, rows = 0; - const unsigned int *block; - - /* [ zzzz y x x ] - * xx == 00 :=> end of the block def, remove the two bits from the stream - * yxx == 111 - * yxx == any other value - * - */ - fill_nbits(pdec, 16); - htable_idx = look_nbits(pdec, 6); - op = hash_table_ops[htable_idx * 4]; - - if (op == 2) { - skip_nbits(pdec, 2); - - } else if (op == 1) { - /* 15bits [ xxxx xxxx yyyy 111 ] - * yyy => offset in the table8004 - * xxx => offset in the tabled004 (tree) - */ - unsigned int mask, shift; - unsigned int nbits, col1; - unsigned int yyyy; - - skip_nbits(pdec, 3); - /* offset1 += yyyy */ - __get_nbits(pdec, 4, yyyy); - offset1 += 1 + yyyy; - offset1 &= 0x0F; - nbits = ptable8004[offset1 * 2]; - - /* col1 = xxxx xxxx */ - __get_nbits(pdec, nbits+1, col1); - - /* Bit mask table */ - mask = pdec->table_bitpowermask[nbits][col1]; - shift = ptable8004[offset1 * 2 + 1]; - rows = ((mask << shift) + 0x80) & 0xFF; - - block = pdec->table_subblock[rows]; - for (i = 0; i < 16; i++) - pdec->temp_colors[i] += block[MulIdx[offset1][i]]; - - } else { - /* op == 0 - * offset1 is coded on 3 bits - */ - unsigned int shift; - - offset1 += hash_table_ops [htable_idx * 4 + 2]; - offset1 &= 0x0F; - - rows = ptable0004[offset1 + hash_table_ops [htable_idx * 4 + 3]]; - block = pdec->table_subblock[rows]; - for (i = 0; i < 16; i++) - pdec->temp_colors[i] += block[MulIdx[offset1][i]]; - - shift = hash_table_ops[htable_idx * 4 + 1]; - skip_nbits(pdec, shift); - } - - } while (op != 2); - -} - -static void DecompressBand23(struct pwc_dec23_private *pdec, - const unsigned char *rawyuv, - unsigned char *planar_y, - unsigned char *planar_u, - unsigned char *planar_v, - unsigned int compressed_image_width, - unsigned int real_image_width) -{ - int compression_index, nblocks; - const unsigned char *ptable0004; - const unsigned char *ptable8004; - - pdec->reservoir = 0; - pdec->nbits_in_reservoir = 0; - pdec->stream = rawyuv + 1; /* The first byte of the stream is skipped */ - - get_nbits(pdec, 4, compression_index); - - /* pass 1: uncompress Y component */ - nblocks = compressed_image_width / 4; - - ptable0004 = pdec->table_0004_pass1[compression_index]; - ptable8004 = pdec->table_8004_pass1[compression_index]; - - /* Each block decode a square of 4x4 */ - while (nblocks) { - decode_block(pdec, ptable0004, ptable8004); - copy_image_block_Y(pdec->temp_colors, planar_y, real_image_width, pdec->scalebits); - planar_y += 4; - nblocks--; - } - - /* pass 2: uncompress UV component */ - nblocks = compressed_image_width / 8; - - ptable0004 = pdec->table_0004_pass2[compression_index]; - ptable8004 = pdec->table_8004_pass2[compression_index]; - - /* Each block decode a square of 4x4 */ - while (nblocks) { - decode_block(pdec, ptable0004, ptable8004); - copy_image_block_CrCb(pdec->temp_colors, planar_u, real_image_width/2, pdec->scalebits); - - decode_block(pdec, ptable0004, ptable8004); - copy_image_block_CrCb(pdec->temp_colors, planar_v, real_image_width/2, pdec->scalebits); - - planar_v += 8; - planar_u += 8; - nblocks -= 2; - } - -} - -/** - * - * Uncompress a pwc23 buffer. - * - * src: raw data - * dst: image output - */ -void pwc_dec23_decompress(struct pwc_device *pdev, - const void *src, - void *dst) -{ - int bandlines_left, bytes_per_block; - struct pwc_dec23_private *pdec = &pdev->dec23; - - /* YUV420P image format */ - unsigned char *pout_planar_y; - unsigned char *pout_planar_u; - unsigned char *pout_planar_v; - unsigned int plane_size; - - mutex_lock(&pdec->lock); - - bandlines_left = pdev->height / 4; - bytes_per_block = pdev->width * 4; - plane_size = pdev->height * pdev->width; - - pout_planar_y = dst; - pout_planar_u = dst + plane_size; - pout_planar_v = dst + plane_size + plane_size / 4; - - while (bandlines_left--) { - DecompressBand23(pdec, src, - pout_planar_y, pout_planar_u, pout_planar_v, - pdev->width, pdev->width); - src += pdev->vbandlength; - pout_planar_y += bytes_per_block; - pout_planar_u += pdev->width; - pout_planar_v += pdev->width; - } - mutex_unlock(&pdec->lock); -} diff --git a/drivers/media/video/pwc/pwc-dec23.h b/drivers/media/video/pwc/pwc-dec23.h deleted file mode 100644 index c655b1c1e6a9..000000000000 --- a/drivers/media/video/pwc/pwc-dec23.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Linux driver for Philips webcam - (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. - Please send bug reports and support requests to <luc@saillard.org>. - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef PWC_DEC23_H -#define PWC_DEC23_H - -struct pwc_device; - -struct pwc_dec23_private -{ - struct mutex lock; - - unsigned char last_cmd, last_cmd_valid; - - unsigned int scalebits; - unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */ - - unsigned int reservoir; - unsigned int nbits_in_reservoir; - - const unsigned char *stream; - int temp_colors[16]; - - unsigned char table_0004_pass1[16][1024]; - unsigned char table_0004_pass2[16][1024]; - unsigned char table_8004_pass1[16][256]; - unsigned char table_8004_pass2[16][256]; - unsigned int table_subblock[256][12]; - - unsigned char table_bitpowermask[8][256]; - unsigned int table_d800[256]; - unsigned int table_dc00[256]; - -}; - -void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd); -void pwc_dec23_decompress(struct pwc_device *pdev, - const void *src, - void *dst); -#endif diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c deleted file mode 100644 index de7c7ba99ef4..000000000000 --- a/drivers/media/video/pwc/pwc-if.c +++ /dev/null @@ -1,1165 +0,0 @@ -/* Linux driver for Philips webcam - USB and Video4Linux interface part. - (C) 1999-2004 Nemosoft Unv. - (C) 2004-2006 Luc Saillard (luc@saillard.org) - (C) 2011 Hans de Goede <hdegoede@redhat.com> - - 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. - Please send bug reports and support requests to <luc@saillard.org>. - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -/* - This code forms the interface between the USB layers and the Philips - specific stuff. Some adanved stuff of the driver falls under an - NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and - is thus not distributed in source form. The binary pwcx.o module - contains the code that falls under the NDA. - - In case you're wondering: 'pwc' stands for "Philips WebCam", but - I really didn't want to type 'philips_web_cam' every time (I'm lazy as - any Linux kernel hacker, but I don't like uncomprehensible abbreviations - without explanation). - - Oh yes, convention: to disctinguish between all the various pointers to - device-structures, I use these names for the pointer variables: - udev: struct usb_device * - vdev: struct video_device (member of pwc_dev) - pdev: struct pwc_devive * -*/ - -/* Contributors: - - Alvarado: adding whitebalance code - - Alistar Moire: QuickCam 3000 Pro device/product ID - - Tony Hoyle: Creative Labs Webcam 5 device/product ID - - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged - - Jk Fang: Sotec Afina Eye ID - - Xavier Roche: QuickCam Pro 4000 ID - - Jens Knudsen: QuickCam Zoom ID - - J. Debert: QuickCam for Notebooks ID - - Pham Thanh Nam: webcam snapshot button as an event input device -*/ - -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/poll.h> -#include <linux/slab.h> -#ifdef CONFIG_USB_PWC_INPUT_EVDEV -#include <linux/usb/input.h> -#endif -#include <linux/vmalloc.h> -#include <asm/io.h> -#include <linux/kernel.h> /* simple_strtol() */ - -#include "pwc.h" -#include "pwc-kiara.h" -#include "pwc-timon.h" -#include "pwc-dec23.h" -#include "pwc-dec1.h" - -/* Function prototypes and driver templates */ - -/* hotplug device table support */ -static const struct usb_device_id pwc_device_table [] = { - { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */ - { USB_DEVICE(0x0471, 0x0303) }, - { USB_DEVICE(0x0471, 0x0304) }, - { USB_DEVICE(0x0471, 0x0307) }, - { USB_DEVICE(0x0471, 0x0308) }, - { USB_DEVICE(0x0471, 0x030C) }, - { USB_DEVICE(0x0471, 0x0310) }, - { USB_DEVICE(0x0471, 0x0311) }, /* Philips ToUcam PRO II */ - { USB_DEVICE(0x0471, 0x0312) }, - { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */ - { USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC PC Camera */ - { USB_DEVICE(0x069A, 0x0001) }, /* Askey */ - { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */ - { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */ - { USB_DEVICE(0x046D, 0x08B2) }, /* Logitech QuickCam Pro 4000 */ - { 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) }, /* 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 */ - { USB_DEVICE(0x055D, 0x9002) }, /* Samsung SNC-35E (Ver3.0) */ - { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */ - { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */ - { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */ - { USB_DEVICE(0x06BE, 0x8116) }, /* new Afina Eye */ - { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */ - { USB_DEVICE(0x0d81, 0x1900) }, - { } -}; -MODULE_DEVICE_TABLE(usb, pwc_device_table); - -static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id); -static void usb_pwc_disconnect(struct usb_interface *intf); -static void pwc_isoc_cleanup(struct pwc_device *pdev); - -static struct usb_driver pwc_driver = { - .name = "Philips webcam", /* name */ - .id_table = pwc_device_table, - .probe = usb_pwc_probe, /* probe() */ - .disconnect = usb_pwc_disconnect, /* disconnect() */ -}; - -#define MAX_DEV_HINTS 20 -#define MAX_ISOC_ERRORS 20 - -#ifdef CONFIG_USB_PWC_DEBUG - int pwc_trace = PWC_DEBUG_LEVEL; -#endif -static int power_save = -1; -static int leds[2] = { 100, 0 }; - -/***/ - -static const struct v4l2_file_operations pwc_fops = { - .owner = THIS_MODULE, - .open = v4l2_fh_open, - .release = vb2_fop_release, - .read = vb2_fop_read, - .poll = vb2_fop_poll, - .mmap = vb2_fop_mmap, - .unlocked_ioctl = video_ioctl2, -}; -static struct video_device pwc_template = { - .name = "Philips Webcam", /* Filled in later */ - .release = video_device_release_empty, - .fops = &pwc_fops, - .ioctl_ops = &pwc_ioctl_ops, -}; - -/***************************************************************************/ -/* Private functions */ - -struct pwc_frame_buf *pwc_get_next_fill_buf(struct pwc_device *pdev) -{ - unsigned long flags = 0; - struct pwc_frame_buf *buf = NULL; - - spin_lock_irqsave(&pdev->queued_bufs_lock, flags); - if (list_empty(&pdev->queued_bufs)) - goto leave; - - buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf, list); - list_del(&buf->list); -leave: - spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags); - return buf; -} - -static void pwc_snapshot_button(struct pwc_device *pdev, int down) -{ - if (down) { - PWC_TRACE("Snapshot button pressed.\n"); - } else { - PWC_TRACE("Snapshot button released.\n"); - } - -#ifdef CONFIG_USB_PWC_INPUT_EVDEV - if (pdev->button_dev) { - input_report_key(pdev->button_dev, KEY_CAMERA, down); - input_sync(pdev->button_dev); - } -#endif -} - -static void pwc_frame_complete(struct pwc_device *pdev) -{ - struct pwc_frame_buf *fbuf = pdev->fill_buf; - - /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus - frames on the USB wire after an exposure change. This conditition is - however detected in the cam and a bit is set in the header. - */ - if (pdev->type == 730) { - unsigned char *ptr = (unsigned char *)fbuf->data; - - if (ptr[1] == 1 && ptr[0] & 0x10) { - PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n"); - pdev->drop_frames += 2; - } - if ((ptr[0] ^ pdev->vmirror) & 0x01) { - pwc_snapshot_button(pdev, ptr[0] & 0x01); - } - if ((ptr[0] ^ pdev->vmirror) & 0x02) { - if (ptr[0] & 0x02) - PWC_TRACE("Image is mirrored.\n"); - else - PWC_TRACE("Image is normal.\n"); - } - pdev->vmirror = ptr[0] & 0x03; - /* Sometimes the trailer of the 730 is still sent as a 4 byte packet - after a short frame; this condition is filtered out specifically. A 4 byte - frame doesn't make sense anyway. - So we get either this sequence: - drop_bit set -> 4 byte frame -> short frame -> good frame - Or this one: - drop_bit set -> short frame -> good frame - So we drop either 3 or 2 frames in all! - */ - if (fbuf->filled == 4) - pdev->drop_frames++; - } else if (pdev->type == 740 || pdev->type == 720) { - unsigned char *ptr = (unsigned char *)fbuf->data; - if ((ptr[0] ^ pdev->vmirror) & 0x01) { - pwc_snapshot_button(pdev, ptr[0] & 0x01); - } - pdev->vmirror = ptr[0] & 0x03; - } - - /* In case we were instructed to drop the frame, do so silently. */ - if (pdev->drop_frames > 0) { - pdev->drop_frames--; - } else { - /* Check for underflow first */ - if (fbuf->filled < pdev->frame_total_size) { - PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);" - " discarded.\n", fbuf->filled); - } else { - fbuf->vb.v4l2_buf.field = V4L2_FIELD_NONE; - fbuf->vb.v4l2_buf.sequence = pdev->vframe_count; - vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE); - pdev->fill_buf = NULL; - pdev->vsync = 0; - } - } /* !drop_frames */ - pdev->vframe_count++; -} - -/* This gets called for the Isochronous pipe (video). This is done in - * interrupt time, so it has to be fast, not crash, and not stall. Neat. - */ -static void pwc_isoc_handler(struct urb *urb) -{ - struct pwc_device *pdev = (struct pwc_device *)urb->context; - int i, fst, flen; - unsigned char *iso_buf = NULL; - - if (urb->status == -ENOENT || urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN) { - PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a"); - return; - } - - if (pdev->fill_buf == NULL) - pdev->fill_buf = pwc_get_next_fill_buf(pdev); - - if (urb->status != 0) { - const char *errmsg; - - errmsg = "Unknown"; - switch(urb->status) { - case -ENOSR: errmsg = "Buffer error (overrun)"; break; - case -EPIPE: errmsg = "Stalled (device not responding)"; break; - case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break; - case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break; - case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break; - case -ETIME: errmsg = "Device does not respond"; break; - } - PWC_ERROR("pwc_isoc_handler() called with status %d [%s].\n", - urb->status, errmsg); - /* Give up after a number of contiguous errors */ - if (++pdev->visoc_errors > MAX_ISOC_ERRORS) - { - PWC_ERROR("Too many ISOC errors, bailing out.\n"); - if (pdev->fill_buf) { - vb2_buffer_done(&pdev->fill_buf->vb, - VB2_BUF_STATE_ERROR); - pdev->fill_buf = NULL; - } - } - pdev->vsync = 0; /* Drop the current frame */ - goto handler_end; - } - - /* Reset ISOC error counter. We did get here, after all. */ - pdev->visoc_errors = 0; - - /* vsync: 0 = don't copy data - 1 = sync-hunt - 2 = synched - */ - /* Compact data */ - for (i = 0; i < urb->number_of_packets; i++) { - fst = urb->iso_frame_desc[i].status; - flen = urb->iso_frame_desc[i].actual_length; - iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - if (fst != 0) { - PWC_ERROR("Iso frame %d has error %d\n", i, fst); - continue; - } - if (flen > 0 && pdev->vsync) { - struct pwc_frame_buf *fbuf = pdev->fill_buf; - - if (pdev->vsync == 1) { - do_gettimeofday(&fbuf->vb.v4l2_buf.timestamp); - pdev->vsync = 2; - } - - if (flen + fbuf->filled > pdev->frame_total_size) { - PWC_ERROR("Frame overflow (%d > %d)\n", - flen + fbuf->filled, - pdev->frame_total_size); - pdev->vsync = 0; /* Let's wait for an EOF */ - } else { - memcpy(fbuf->data + fbuf->filled, iso_buf, - flen); - fbuf->filled += flen; - } - } - if (flen < pdev->vlast_packet_size) { - /* Shorter packet... end of frame */ - if (pdev->vsync == 2) - pwc_frame_complete(pdev); - if (pdev->fill_buf == NULL) - pdev->fill_buf = pwc_get_next_fill_buf(pdev); - if (pdev->fill_buf) { - pdev->fill_buf->filled = 0; - pdev->vsync = 1; - } - } - pdev->vlast_packet_size = flen; - } - -handler_end: - i = usb_submit_urb(urb, GFP_ATOMIC); - if (i != 0) - PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i); -} - -/* Both v4l2_lock and vb_queue_lock should be locked when calling this */ -static int pwc_isoc_init(struct pwc_device *pdev) -{ - struct usb_device *udev; - struct urb *urb; - int i, j, ret; - struct usb_interface *intf; - struct usb_host_interface *idesc = NULL; - int compression = 0; /* 0..3 = uncompressed..high */ - - pdev->vsync = 0; - pdev->vlast_packet_size = 0; - pdev->fill_buf = NULL; - pdev->vframe_count = 0; - pdev->visoc_errors = 0; - udev = pdev->udev; - -retry: - /* We first try with low compression and then retry with a higher - compression setting if there is not enough bandwidth. */ - ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt, - pdev->vframes, &compression, 1); - - /* Get the current alternate interface, adjust packet size */ - intf = usb_ifnum_to_if(udev, 0); - if (intf) - idesc = usb_altnum_to_altsetting(intf, pdev->valternate); - if (!idesc) - return -EIO; - - /* Search video endpoint */ - pdev->vmax_packet_size = -1; - for (i = 0; i < idesc->desc.bNumEndpoints; i++) { - if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) { - pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize); - break; - } - } - - if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) { - PWC_ERROR("Failed to find packet size for video endpoint in current alternate setting.\n"); - return -ENFILE; /* Odd error, that should be noticeable */ - } - - /* Set alternate interface */ - PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate); - ret = usb_set_interface(pdev->udev, 0, pdev->valternate); - if (ret == -ENOSPC && compression < 3) { - compression++; - goto retry; - } - if (ret < 0) - return ret; - - /* Allocate and init Isochronuous urbs */ - for (i = 0; i < MAX_ISO_BUFS; i++) { - urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL); - if (urb == NULL) { - PWC_ERROR("Failed to allocate urb %d\n", i); - pwc_isoc_cleanup(pdev); - return -ENOMEM; - } - pdev->urbs[i] = urb; - PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb); - - urb->interval = 1; // devik - urb->dev = udev; - urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint); - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - urb->transfer_buffer = usb_alloc_coherent(udev, - ISO_BUFFER_SIZE, - GFP_KERNEL, - &urb->transfer_dma); - if (urb->transfer_buffer == NULL) { - PWC_ERROR("Failed to allocate urb buffer %d\n", i); - pwc_isoc_cleanup(pdev); - return -ENOMEM; - } - urb->transfer_buffer_length = ISO_BUFFER_SIZE; - urb->complete = pwc_isoc_handler; - urb->context = pdev; - urb->start_frame = 0; - urb->number_of_packets = ISO_FRAMES_PER_DESC; - for (j = 0; j < ISO_FRAMES_PER_DESC; j++) { - urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE; - urb->iso_frame_desc[j].length = pdev->vmax_packet_size; - } - } - - /* link */ - for (i = 0; i < MAX_ISO_BUFS; i++) { - ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL); - if (ret == -ENOSPC && compression < 3) { - compression++; - pwc_isoc_cleanup(pdev); - goto retry; - } - if (ret) { - PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret); - pwc_isoc_cleanup(pdev); - return ret; - } - PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->urbs[i]); - } - - /* All is done... */ - PWC_DEBUG_OPEN("<< pwc_isoc_init()\n"); - return 0; -} - -static void pwc_iso_stop(struct pwc_device *pdev) -{ - int i; - - /* Unlinking ISOC buffers one by one */ - for (i = 0; i < MAX_ISO_BUFS; i++) { - if (pdev->urbs[i]) { - PWC_DEBUG_MEMORY("Unlinking URB %p\n", pdev->urbs[i]); - usb_kill_urb(pdev->urbs[i]); - } - } -} - -static void pwc_iso_free(struct pwc_device *pdev) -{ - int i; - - /* Freeing ISOC buffers one by one */ - for (i = 0; i < MAX_ISO_BUFS; i++) { - if (pdev->urbs[i]) { - PWC_DEBUG_MEMORY("Freeing URB\n"); - if (pdev->urbs[i]->transfer_buffer) { - usb_free_coherent(pdev->udev, - pdev->urbs[i]->transfer_buffer_length, - pdev->urbs[i]->transfer_buffer, - pdev->urbs[i]->transfer_dma); - } - usb_free_urb(pdev->urbs[i]); - pdev->urbs[i] = NULL; - } - } -} - -/* Both v4l2_lock and vb_queue_lock should be locked when calling this */ -static void pwc_isoc_cleanup(struct pwc_device *pdev) -{ - PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n"); - - pwc_iso_stop(pdev); - pwc_iso_free(pdev); - usb_set_interface(pdev->udev, 0, 0); - - PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n"); -} - -/* Must be called with vb_queue_lock hold */ -static void pwc_cleanup_queued_bufs(struct pwc_device *pdev) -{ - unsigned long flags = 0; - - spin_lock_irqsave(&pdev->queued_bufs_lock, flags); - while (!list_empty(&pdev->queued_bufs)) { - struct pwc_frame_buf *buf; - - buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf, - list); - list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); - } - spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags); -} - -#ifdef CONFIG_USB_PWC_DEBUG -static const char *pwc_sensor_type_to_string(unsigned int sensor_type) -{ - switch(sensor_type) { - case 0x00: - return "Hyundai CMOS sensor"; - case 0x20: - return "Sony CCD sensor + TDA8787"; - case 0x2E: - return "Sony CCD sensor + Exas 98L59"; - case 0x2F: - return "Sony CCD sensor + ADI 9804"; - case 0x30: - return "Sharp CCD sensor + TDA8787"; - case 0x3E: - return "Sharp CCD sensor + Exas 98L59"; - case 0x3F: - return "Sharp CCD sensor + ADI 9804"; - case 0x40: - return "UPA 1021 sensor"; - case 0x100: - return "VGA sensor"; - case 0x101: - return "PAL MR sensor"; - default: - return "unknown type of sensor"; - } -} -#endif - -/***************************************************************************/ -/* Video4Linux functions */ - -static void pwc_video_release(struct v4l2_device *v) -{ - struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev); - - v4l2_ctrl_handler_free(&pdev->ctrl_handler); - v4l2_device_unregister(&pdev->v4l2_dev); - kfree(pdev->ctrl_buf); - kfree(pdev); -} - -/***************************************************************************/ -/* Videobuf2 operations */ - -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, - unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], void *alloc_ctxs[]) -{ - struct pwc_device *pdev = vb2_get_drv_priv(vq); - int size; - - if (*nbuffers < MIN_FRAMES) - *nbuffers = MIN_FRAMES; - else if (*nbuffers > MAX_FRAMES) - *nbuffers = MAX_FRAMES; - - *nplanes = 1; - - size = pwc_get_size(pdev, MAX_WIDTH, MAX_HEIGHT); - sizes[0] = PAGE_ALIGN(pwc_image_sizes[size][0] * - pwc_image_sizes[size][1] * 3 / 2); - - return 0; -} - -static int buffer_init(struct vb2_buffer *vb) -{ - struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb); - - /* need vmalloc since frame buffer > 128K */ - buf->data = vzalloc(PWC_FRAME_SIZE); - if (buf->data == NULL) - return -ENOMEM; - - return 0; -} - -static int buffer_prepare(struct vb2_buffer *vb) -{ - struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue); - - /* Don't allow queing new buffers after device disconnection */ - if (!pdev->udev) - return -ENODEV; - - return 0; -} - -static int buffer_finish(struct vb2_buffer *vb) -{ - struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue); - struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb); - - /* - * Application has called dqbuf and is getting back a buffer we've - * filled, take the pwc data we've stored in buf->data and decompress - * it into a usable format, storing the result in the vb2_buffer - */ - return pwc_decompress(pdev, buf); -} - -static void buffer_cleanup(struct vb2_buffer *vb) -{ - struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb); - - vfree(buf->data); -} - -static void buffer_queue(struct vb2_buffer *vb) -{ - struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue); - struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb); - unsigned long flags = 0; - - /* Check the device has not disconnected between prep and queuing */ - if (!pdev->udev) { - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); - return; - } - - spin_lock_irqsave(&pdev->queued_bufs_lock, flags); - list_add_tail(&buf->list, &pdev->queued_bufs); - spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags); -} - -static int start_streaming(struct vb2_queue *vq, unsigned int count) -{ - struct pwc_device *pdev = vb2_get_drv_priv(vq); - int r; - - if (!pdev->udev) - return -ENODEV; - - if (mutex_lock_interruptible(&pdev->v4l2_lock)) - return -ERESTARTSYS; - /* Turn on camera and set LEDS on */ - pwc_camera_power(pdev, 1); - pwc_set_leds(pdev, leds[0], leds[1]); - - r = pwc_isoc_init(pdev); - if (r) { - /* If we failed turn camera and LEDS back off */ - pwc_set_leds(pdev, 0, 0); - pwc_camera_power(pdev, 0); - /* And cleanup any queued bufs!! */ - pwc_cleanup_queued_bufs(pdev); - } - mutex_unlock(&pdev->v4l2_lock); - - return r; -} - -static int stop_streaming(struct vb2_queue *vq) -{ - struct pwc_device *pdev = vb2_get_drv_priv(vq); - - if (mutex_lock_interruptible(&pdev->v4l2_lock)) - return -ERESTARTSYS; - if (pdev->udev) { - pwc_set_leds(pdev, 0, 0); - pwc_camera_power(pdev, 0); - pwc_isoc_cleanup(pdev); - } - - pwc_cleanup_queued_bufs(pdev); - mutex_unlock(&pdev->v4l2_lock); - - return 0; -} - -static struct vb2_ops pwc_vb_queue_ops = { - .queue_setup = queue_setup, - .buf_init = buffer_init, - .buf_prepare = buffer_prepare, - .buf_finish = buffer_finish, - .buf_cleanup = buffer_cleanup, - .buf_queue = buffer_queue, - .start_streaming = start_streaming, - .stop_streaming = stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, -}; - -/***************************************************************************/ -/* USB functions */ - -/* This function gets called when a new device is plugged in or the usb core - * is loaded. - */ - -static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct pwc_device *pdev = NULL; - int vendor_id, product_id, type_id; - int rc; - int features = 0; - int compression = 0; - int my_power_save = power_save; - char serial_number[30], *name; - - vendor_id = le16_to_cpu(udev->descriptor.idVendor); - product_id = le16_to_cpu(udev->descriptor.idProduct); - - /* Check if we can handle this device */ - PWC_DEBUG_PROBE("probe() called [%04X %04X], if %d\n", - vendor_id, product_id, - intf->altsetting->desc.bInterfaceNumber); - - /* the interfaces are probed one by one. We are only interested in the - video interface (0) now. - Interface 1 is the Audio Control, and interface 2 Audio itself. - */ - if (intf->altsetting->desc.bInterfaceNumber > 0) - return -ENODEV; - - if (vendor_id == 0x0471) { - switch (product_id) { - case 0x0302: - PWC_INFO("Philips PCA645VC USB webcam detected.\n"); - name = "Philips 645 webcam"; - type_id = 645; - break; - case 0x0303: - PWC_INFO("Philips PCA646VC USB webcam detected.\n"); - name = "Philips 646 webcam"; - type_id = 646; - break; - case 0x0304: - PWC_INFO("Askey VC010 type 2 USB webcam detected.\n"); - name = "Askey VC010 webcam"; - type_id = 646; - break; - case 0x0307: - PWC_INFO("Philips PCVC675K (Vesta) USB webcam detected.\n"); - name = "Philips 675 webcam"; - type_id = 675; - break; - case 0x0308: - PWC_INFO("Philips PCVC680K (Vesta Pro) USB webcam detected.\n"); - name = "Philips 680 webcam"; - type_id = 680; - break; - case 0x030C: - PWC_INFO("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n"); - name = "Philips 690 webcam"; - type_id = 690; - break; - case 0x0310: - PWC_INFO("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n"); - name = "Philips 730 webcam"; - type_id = 730; - break; - case 0x0311: - PWC_INFO("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n"); - name = "Philips 740 webcam"; - type_id = 740; - break; - case 0x0312: - PWC_INFO("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n"); - name = "Philips 750 webcam"; - type_id = 750; - break; - case 0x0313: - PWC_INFO("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n"); - name = "Philips 720K/40 webcam"; - type_id = 720; - break; - case 0x0329: - PWC_INFO("Philips SPC 900NC USB webcam detected.\n"); - name = "Philips SPC 900NC webcam"; - type_id = 740; - break; - default: - return -ENODEV; - break; - } - } - else if (vendor_id == 0x069A) { - switch(product_id) { - case 0x0001: - PWC_INFO("Askey VC010 type 1 USB webcam detected.\n"); - name = "Askey VC010 webcam"; - type_id = 645; - break; - default: - return -ENODEV; - break; - } - } - else if (vendor_id == 0x046d) { - switch(product_id) { - case 0x08b0: - PWC_INFO("Logitech QuickCam Pro 3000 USB webcam detected.\n"); - name = "Logitech QuickCam Pro 3000"; - type_id = 740; /* CCD sensor */ - break; - case 0x08b1: - PWC_INFO("Logitech QuickCam Notebook Pro USB webcam detected.\n"); - name = "Logitech QuickCam Notebook Pro"; - type_id = 740; /* CCD sensor */ - break; - case 0x08b2: - PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n"); - name = "Logitech QuickCam Pro 4000"; - type_id = 740; /* CCD sensor */ - if (my_power_save == -1) - my_power_save = 1; - break; - case 0x08b3: - PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n"); - name = "Logitech QuickCam Zoom"; - type_id = 740; /* CCD sensor */ - break; - case 0x08B4: - PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n"); - name = "Logitech QuickCam Zoom"; - type_id = 740; /* CCD sensor */ - if (my_power_save == -1) - my_power_save = 1; - break; - case 0x08b5: - PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n"); - name = "Logitech QuickCam Orbit"; - type_id = 740; /* CCD sensor */ - if (my_power_save == -1) - my_power_save = 1; - 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: - 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 */ - break; - default: - return -ENODEV; - break; - } - } - else if (vendor_id == 0x055d) { - /* I don't know the difference between the C10 and the C30; - I suppose the difference is the sensor, but both cameras - work equally well with a type_id of 675 - */ - switch(product_id) { - case 0x9000: - PWC_INFO("Samsung MPC-C10 USB webcam detected.\n"); - name = "Samsung MPC-C10"; - type_id = 675; - break; - case 0x9001: - PWC_INFO("Samsung MPC-C30 USB webcam detected.\n"); - name = "Samsung MPC-C30"; - type_id = 675; - break; - case 0x9002: - PWC_INFO("Samsung SNC-35E (v3.0) USB webcam detected.\n"); - name = "Samsung MPC-C30"; - type_id = 740; - break; - default: - return -ENODEV; - break; - } - } - else if (vendor_id == 0x041e) { - switch(product_id) { - case 0x400c: - PWC_INFO("Creative Labs Webcam 5 detected.\n"); - name = "Creative Labs Webcam 5"; - type_id = 730; - if (my_power_save == -1) - my_power_save = 1; - break; - case 0x4011: - PWC_INFO("Creative Labs Webcam Pro Ex detected.\n"); - name = "Creative Labs Webcam Pro Ex"; - type_id = 740; - break; - default: - return -ENODEV; - break; - } - } - else if (vendor_id == 0x04cc) { - switch(product_id) { - case 0x8116: - PWC_INFO("Sotec Afina Eye USB webcam detected.\n"); - name = "Sotec Afina Eye"; - type_id = 730; - break; - default: - return -ENODEV; - break; - } - } - else if (vendor_id == 0x06be) { - switch(product_id) { - case 0x8116: - /* This is essentially the same cam as the Sotec Afina Eye */ - PWC_INFO("AME Co. Afina Eye USB webcam detected.\n"); - name = "AME Co. Afina Eye"; - type_id = 750; - break; - default: - return -ENODEV; - break; - } - - } - else if (vendor_id == 0x0d81) { - switch(product_id) { - case 0x1900: - PWC_INFO("Visionite VCS-UC300 USB webcam detected.\n"); - name = "Visionite VCS-UC300"; - type_id = 740; /* CCD sensor */ - break; - case 0x1910: - PWC_INFO("Visionite VCS-UM100 USB webcam detected.\n"); - name = "Visionite VCS-UM100"; - type_id = 730; /* CMOS sensor */ - break; - default: - return -ENODEV; - break; - } - } - else - return -ENODEV; /* Not any of the know types; but the list keeps growing. */ - - if (my_power_save == -1) - my_power_save = 0; - - memset(serial_number, 0, 30); - usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29); - PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number); - - if (udev->descriptor.bNumConfigurations > 1) - PWC_WARNING("Warning: more than 1 configuration available.\n"); - - /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */ - pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL); - if (pdev == NULL) { - PWC_ERROR("Oops, could not allocate memory for pwc_device.\n"); - return -ENOMEM; - } - pdev->type = type_id; - pdev->features = features; - pwc_construct(pdev); /* set min/max sizes correct */ - - mutex_init(&pdev->v4l2_lock); - mutex_init(&pdev->vb_queue_lock); - spin_lock_init(&pdev->queued_bufs_lock); - INIT_LIST_HEAD(&pdev->queued_bufs); - - pdev->udev = udev; - pdev->power_save = my_power_save; - - /* Init videobuf2 queue structure */ - memset(&pdev->vb_queue, 0, sizeof(pdev->vb_queue)); - pdev->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - pdev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; - pdev->vb_queue.drv_priv = pdev; - pdev->vb_queue.buf_struct_size = sizeof(struct pwc_frame_buf); - pdev->vb_queue.ops = &pwc_vb_queue_ops; - pdev->vb_queue.mem_ops = &vb2_vmalloc_memops; - vb2_queue_init(&pdev->vb_queue); - - /* Init video_device structure */ - memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template)); - strcpy(pdev->vdev.name, name); - pdev->vdev.queue = &pdev->vb_queue; - pdev->vdev.queue->lock = &pdev->vb_queue_lock; - set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags); - video_set_drvdata(&pdev->vdev, pdev); - - pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); - PWC_DEBUG_PROBE("Release: %04x\n", pdev->release); - - /* Allocate USB command buffers */ - pdev->ctrl_buf = kmalloc(sizeof(pdev->cmd_buf), GFP_KERNEL); - if (!pdev->ctrl_buf) { - PWC_ERROR("Oops, could not allocate memory for pwc_device.\n"); - rc = -ENOMEM; - goto err_free_mem; - } - -#ifdef CONFIG_USB_PWC_DEBUG - /* Query sensor type */ - if (pwc_get_cmos_sensor(pdev, &rc) >= 0) { - PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n", - pdev->vdev.name, - pwc_sensor_type_to_string(rc), rc); - } -#endif - - /* Set the leds off */ - pwc_set_leds(pdev, 0, 0); - - /* Setup intial videomode */ - rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT, - V4L2_PIX_FMT_YUV420, 30, &compression, 1); - if (rc) - goto err_free_mem; - - /* Register controls (and read default values from camera */ - rc = pwc_init_controls(pdev); - if (rc) { - PWC_ERROR("Failed to register v4l2 controls (%d).\n", rc); - goto err_free_mem; - } - - /* And powerdown the camera until streaming starts */ - pwc_camera_power(pdev, 0); - - /* Register the v4l2_device structure */ - pdev->v4l2_dev.release = pwc_video_release; - rc = v4l2_device_register(&intf->dev, &pdev->v4l2_dev); - if (rc) { - PWC_ERROR("Failed to register v4l2-device (%d).\n", rc); - goto err_free_controls; - } - - pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler; - pdev->vdev.v4l2_dev = &pdev->v4l2_dev; - pdev->vdev.lock = &pdev->v4l2_lock; - - rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, -1); - if (rc < 0) { - PWC_ERROR("Failed to register as video device (%d).\n", rc); - goto err_unregister_v4l2_dev; - } - PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev)); - -#ifdef CONFIG_USB_PWC_INPUT_EVDEV - /* register webcam snapshot button input device */ - pdev->button_dev = input_allocate_device(); - if (!pdev->button_dev) { - PWC_ERROR("Err, insufficient memory for webcam snapshot button device."); - rc = -ENOMEM; - goto err_video_unreg; - } - - usb_make_path(udev, pdev->button_phys, sizeof(pdev->button_phys)); - strlcat(pdev->button_phys, "/input0", sizeof(pdev->button_phys)); - - pdev->button_dev->name = "PWC snapshot button"; - pdev->button_dev->phys = pdev->button_phys; - usb_to_input_id(pdev->udev, &pdev->button_dev->id); - pdev->button_dev->dev.parent = &pdev->udev->dev; - pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY); - pdev->button_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA); - - rc = input_register_device(pdev->button_dev); - if (rc) { - input_free_device(pdev->button_dev); - pdev->button_dev = NULL; - goto err_video_unreg; - } -#endif - - return 0; - -err_video_unreg: - video_unregister_device(&pdev->vdev); -err_unregister_v4l2_dev: - v4l2_device_unregister(&pdev->v4l2_dev); -err_free_controls: - v4l2_ctrl_handler_free(&pdev->ctrl_handler); -err_free_mem: - kfree(pdev->ctrl_buf); - kfree(pdev); - return rc; -} - -/* The user yanked out the cable... */ -static void usb_pwc_disconnect(struct usb_interface *intf) -{ - struct v4l2_device *v = usb_get_intfdata(intf); - struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev); - - mutex_lock(&pdev->vb_queue_lock); - mutex_lock(&pdev->v4l2_lock); - /* No need to keep the urbs around after disconnection */ - if (pdev->vb_queue.streaming) - pwc_isoc_cleanup(pdev); - pdev->udev = NULL; - pwc_cleanup_queued_bufs(pdev); - - v4l2_device_disconnect(&pdev->v4l2_dev); - video_unregister_device(&pdev->vdev); - mutex_unlock(&pdev->v4l2_lock); - mutex_unlock(pdev->vb_queue.lock); - -#ifdef CONFIG_USB_PWC_INPUT_EVDEV - if (pdev->button_dev) - input_unregister_device(pdev->button_dev); -#endif - - v4l2_device_put(&pdev->v4l2_dev); -} - - -/* - * Initialization code & module stuff - */ - -static unsigned int leds_nargs; - -#ifdef CONFIG_USB_PWC_DEBUG -module_param_named(trace, pwc_trace, int, 0644); -#endif -module_param(power_save, int, 0644); -module_param_array(leds, int, &leds_nargs, 0444); - -#ifdef CONFIG_USB_PWC_DEBUG -MODULE_PARM_DESC(trace, "For debugging purposes"); -#endif -MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off"); -MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); - -MODULE_DESCRIPTION("Philips & OEM USB webcam driver"); -MODULE_AUTHOR("Luc Saillard <luc@saillard.org>"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("pwcx"); -MODULE_VERSION( PWC_VERSION ); - -module_usb_driver(pwc_driver); diff --git a/drivers/media/video/pwc/pwc-kiara.c b/drivers/media/video/pwc/pwc-kiara.c deleted file mode 100644 index e5f4fd817125..000000000000 --- a/drivers/media/video/pwc/pwc-kiara.c +++ /dev/null @@ -1,892 +0,0 @@ -/* Linux driver for Philips webcam - (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. - Please send bug reports and support requests to <luc@saillard.org>. - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - -/* This tables contains entries for the 730/740/750 (Kiara) camera, with - 4 different qualities (no compression, low, medium, high). - It lists the bandwidth requirements for said mode by its alternate interface - number. An alternate of 0 means that the mode is unavailable. - - There are 6 * 4 * 4 entries: - 6 different resolutions subqcif, qsif, qcif, sif, cif, vga - 6 framerates: 5, 10, 15, 20, 25, 30 - 4 compression modi: none, low, medium, high - - When an uncompressed mode is not available, the next available compressed mode - will be chosen (unless the decompressor is absent). Sometimes there are only - 1 or 2 compressed modes available; in that case entries are duplicated. -*/ - - -#include "pwc-kiara.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 */ - { - /* 5 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 10 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 15 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 20 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 25 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 30 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - }, - /* QSIF */ - { - /* 5 fps */ - { - {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, - {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, - {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, - {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}}, - }, - /* 10 fps */ - { - {2, 291, 0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}}, - {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}}, - {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}}, - {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}}, - }, - /* 15 fps */ - { - {3, 437, 0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}}, - {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}}, - {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}}, - {1, 192, 420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}}, - }, - /* 20 fps */ - { - {4, 589, 0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}}, - {3, 448, 730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}}, - {2, 292, 476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}}, - {1, 192, 312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}}, - }, - /* 25 fps */ - { - {5, 703, 0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}}, - {3, 447, 610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}}, - {2, 292, 398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}}, - {1, 193, 262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}}, - }, - /* 30 fps */ - { - {8, 874, 0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}}, - {5, 704, 730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}}, - {3, 448, 492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}}, - {2, 292, 320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}}, - }, - }, - /* QCIF */ - { - /* 5 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 10 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 15 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 20 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 25 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 30 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - }, - /* SIF */ - { - /* 5 fps */ - { - {4, 582, 0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}}, - {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}}, - {2, 291, 960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}}, - {1, 191, 630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}}, - }, - /* 10 fps */ - { - {0, }, - {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}}, - {3, 447, 736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}}, - {2, 292, 480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}}, - }, - /* 15 fps */ - { - {0, }, - {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}}, - {4, 592, 650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}}, - {3, 448, 492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}}, - }, - /* 20 fps */ - { - {0, }, - {9, 958, 782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}}, - {5, 703, 574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}}, - {3, 446, 364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}}, - }, - /* 25 fps */ - { - {0, }, - {9, 958, 654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}}, - {6, 776, 530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}}, - {4, 592, 404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}}, - }, - /* 30 fps */ - { - {0, }, - {9, 957, 526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}}, - {6, 775, 426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}}, - {4, 590, 324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}}, - }, - }, - /* CIF */ - { - /* 5 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 10 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 15 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 20 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 25 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 30 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - }, - /* VGA */ - { - /* 5 fps */ - { - {0, }, - {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}}, - {4, 592, 976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}}, - {3, 448, 738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}}, - }, - /* 10 fps */ - { - {0, }, - {9, 956, 788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}}, - {6, 776, 640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}}, - {4, 592, 488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}}, - }, - /* 15 fps */ - { - {0, }, - {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}}, - {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}}, - {8, 895, 492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}}, - }, - /* 20 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 25 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 30 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - }, -}; - - -/* - * Rom table for kiara chips - * - * 32 roms tables (one for each resolution ?) - * 2 tables per roms (one for each passes) (Y, and U&V) - * 128 bytes per passes - */ - -const unsigned int KiaraRomTable [8][2][16][8] = -{ - { /* version 0 */ - { /* version 0, passes 0 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000001,0x00000001}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000009,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000249,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000249,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x00000249,0x0000124a,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x0000124a,0x00009252,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00009252,0x00009292,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009292,0x00009292,0x00009493,0x000124db}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x0000a493,0x000124db,0x000124db,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x000124db,0x000126dc,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000124db,0x000136e4,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b925,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 0, passes 1 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000001,0x00000009, - 0x00000009,0x00000009,0x00000009,0x00000001}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000249,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00001252}, - {0x00000000,0x00000000,0x00000049,0x00001249, - 0x0000124a,0x0000124a,0x00001252,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009252,0x00009292,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009292,0x00009292,0x00009292,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x00009292, - 0x00009492,0x00009493,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00009252,0x00009493, - 0x000126dc,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000136e4,0x000136e4,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 1 */ - { /* version 1, passes 0 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000001}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00001252}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009252,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009252,0x00009493,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009292,0x00009493,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x00009252, - 0x00009492,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x000124db,0x000124db,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000126dc,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 1, passes 1 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000049,0x00000009, - 0x00000049,0x00000009,0x00000001,0x00000000}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000000}, - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000249,0x00000049,0x0000024a,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x0000024a,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x0000024a,0x00000009}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00009252,0x00001252,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00009292,0x00001252,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00009292,0x00001252,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009292,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x0000924a,0x0000924a, - 0x00009492,0x00009493,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 2 */ - { /* version 2, passes 0 */ - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x00009252,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009493,0x00009493,0x0000a49b}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009292,0x00009493,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x000124db,0x000124db,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x00009252,0x000124db, - 0x000126dc,0x0001b724,0x0001b725,0x0001b925}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 2, passes 1 */ - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00000249, - 0x0000124a,0x0000124a,0x00001252,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00009292,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x0000a49b,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x0000a49b,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x00009252,0x0000a49b, - 0x0001249b,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 3 */ - { /* version 3, passes 0 */ - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000136e4,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x0001b725,0x0001b925}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x000136e4,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x000136e4,0x0001b925,0x00025bb6,0x00024b77}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 3, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00000249, - 0x0000124a,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x00009493,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x000126dc,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000136e4,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001b724,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 4 */ - { /* version 4, passes 0 */ - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000249,0x00000249,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x00009252,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009292,0x00009493,0x00009493,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0001249b,0x000126dc,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00009252,0x00009493, - 0x000124db,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009252,0x0000a49b, - 0x000124db,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x000136e4,0x0001b925,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 4, passes 1 */ - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000009,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000049,0x00000049,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00000249,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x0000124a,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009252,0x0000124a,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x00009252,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x00009292,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x00009292,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x00009493,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000124db,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009252,0x000124db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 5 */ - { /* version 5, passes 0 */ - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000126dc,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b725,0x000136e4}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b925,0x0001c96e,0x0001b925}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001c924,0x0002496d,0x00025bb6,0x00024b77}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 5, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009252,0x00009252,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000124db,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000124db,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000126dc,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009292,0x000124db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 6 */ - { /* version 6, passes 0 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000126dc,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b725,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b92d,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b925,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001c92d,0x00024b76,0x0002496e}, - {0x00000000,0x00000000,0x00012492,0x000126db, - 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 6, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x00009252,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x00009292,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000124db,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000126dc,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 7 */ - { /* version 7, passes 0 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x0000a49b, - 0x0001249b,0x000126dc,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x0001b725,0x000124db}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b725,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x000124db, - 0x000136e4,0x0001b724,0x0001b725,0x000126dc}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b724,0x0001c96e,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b924,0x0001c92d,0x00024b76,0x0002496e}, - {0x00000000,0x00000000,0x00012492,0x000136db, - 0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 7, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x00009492,0x00009292,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000124db,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000136db, - 0x0001b724,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000136db, - 0x0001b724,0x000126dc,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00009292,0x000136db, - 0x0001b724,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000136db, - 0x0001b724,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00012492,0x0001b6db, - 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - } -}; - diff --git a/drivers/media/video/pwc/pwc-kiara.h b/drivers/media/video/pwc/pwc-kiara.h deleted file mode 100644 index 8e02b7ac2139..000000000000 --- a/drivers/media/video/pwc/pwc-kiara.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Linux driver for Philips webcam - (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. - Please send bug reports and support requests to <luc@saillard.org>. - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* Entries for the Kiara (730/740/750) camera */ - -#ifndef PWC_KIARA_H -#define PWC_KIARA_H - -#include "pwc.h" - -#define PWC_FPS_MAX_KIARA 6 - -struct Kiara_table_entry -{ - char alternate; /* USB alternate interface */ - unsigned short packetsize; /* Normal packet size */ - unsigned short bandlength; /* Bandlength when decompressing */ - unsigned char mode[12]; /* precomputed mode settings for cam */ -}; - -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/drivers/media/video/pwc/pwc-misc.c b/drivers/media/video/pwc/pwc-misc.c deleted file mode 100644 index 9be5adffa874..000000000000 --- a/drivers/media/video/pwc/pwc-misc.c +++ /dev/null @@ -1,93 +0,0 @@ -/* Linux driver for Philips webcam - Various miscellaneous functions and tables. - (C) 1999-2003 Nemosoft Unv. - (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. - Please send bug reports and support requests to <luc@saillard.org>. - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - -#include "pwc.h" - -const int pwc_image_sizes[PSZ_MAX][2] = -{ - { 128, 96 }, /* sqcif */ - { 160, 120 }, /* qsif */ - { 176, 144 }, /* qcif */ - { 320, 240 }, /* sif */ - { 352, 288 }, /* cif */ - { 640, 480 }, /* vga */ -}; - -/* x,y -> PSZ_ */ -int pwc_get_size(struct pwc_device *pdev, int width, int height) -{ - int i; - - /* Find the largest size supported by the camera that fits into the - requested size. */ - for (i = PSZ_MAX - 1; i >= 0; i--) { - if (!(pdev->image_mask & (1 << i))) - continue; - - if (pwc_image_sizes[i][0] <= width && - pwc_image_sizes[i][1] <= height) - return i; - } - - /* No mode found, return the smallest mode we have */ - for (i = 0; i < PSZ_MAX; i++) { - if (pdev->image_mask & (1 << i)) - return i; - } - - /* Never reached there always is atleast one supported mode */ - return 0; -} - -/* initialize variables depending on type and decompressor */ -void pwc_construct(struct pwc_device *pdev) -{ - if (DEVICE_USE_CODEC1(pdev->type)) { - - pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF; - pdev->vcinterface = 2; - pdev->vendpoint = 4; - pdev->frame_header_size = 0; - pdev->frame_trailer_size = 0; - - } else if (DEVICE_USE_CODEC3(pdev->type)) { - - pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA; - pdev->vcinterface = 3; - pdev->vendpoint = 5; - pdev->frame_header_size = TOUCAM_HEADER_SIZE; - pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE; - - } else /* if (DEVICE_USE_CODEC2(pdev->type)) */ { - - pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA; - pdev->vcinterface = 3; - pdev->vendpoint = 4; - pdev->frame_header_size = 0; - pdev->frame_trailer_size = 0; - } -} diff --git a/drivers/media/video/pwc/pwc-nala.h b/drivers/media/video/pwc/pwc-nala.h deleted file mode 100644 index 168c73ef75d8..000000000000 --- a/drivers/media/video/pwc/pwc-nala.h +++ /dev/null @@ -1,66 +0,0 @@ - /* SQCIF */ - { - {0, 0, {0x04, 0x01, 0x03}}, - {8, 0, {0x05, 0x01, 0x03}}, - {7, 0, {0x08, 0x01, 0x03}}, - {7, 0, {0x0A, 0x01, 0x03}}, - {6, 0, {0x0C, 0x01, 0x03}}, - {5, 0, {0x0F, 0x01, 0x03}}, - {4, 0, {0x14, 0x01, 0x03}}, - {3, 0, {0x18, 0x01, 0x03}}, - }, - /* QSIF */ - { - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - }, - /* QCIF */ - { - {0, 0, {0x04, 0x01, 0x02}}, - {8, 0, {0x05, 0x01, 0x02}}, - {7, 0, {0x08, 0x01, 0x02}}, - {6, 0, {0x0A, 0x01, 0x02}}, - {5, 0, {0x0C, 0x01, 0x02}}, - {4, 0, {0x0F, 0x01, 0x02}}, - {1, 0, {0x14, 0x01, 0x02}}, - {1, 0, {0x18, 0x01, 0x02}}, - }, - /* SIF */ - { - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - }, - /* CIF */ - { - {4, 0, {0x04, 0x01, 0x01}}, - {7, 1, {0x05, 0x03, 0x01}}, - {6, 1, {0x08, 0x03, 0x01}}, - {4, 1, {0x0A, 0x03, 0x01}}, - {3, 1, {0x0C, 0x03, 0x01}}, - {2, 1, {0x0F, 0x03, 0x01}}, - {0}, - {0}, - }, - /* VGA */ - { - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - }, diff --git a/drivers/media/video/pwc/pwc-timon.c b/drivers/media/video/pwc/pwc-timon.c deleted file mode 100644 index c56c174b161c..000000000000 --- a/drivers/media/video/pwc/pwc-timon.c +++ /dev/null @@ -1,1448 +0,0 @@ -/* Linux driver for Philips webcam - (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. - Please send bug reports and support requests to <luc@saillard.org>. - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - -/* This tables contains entries for the 675/680/690 (Timon) camera, with - 4 different qualities (no compression, low, medium, high). - It lists the bandwidth requirements for said mode by its alternate interface - number. An alternate of 0 means that the mode is unavailable. - - There are 6 * 4 * 4 entries: - 6 different resolutions subqcif, qsif, qcif, sif, cif, vga - 6 framerates: 5, 10, 15, 20, 25, 30 - 4 compression modi: none, low, medium, high - - When an uncompressed mode is not available, the next available compressed mode - will be chosen (unless the decompressor is absent). Sometimes there are only - 1 or 2 compressed modes available; in that case entries are duplicated. -*/ - -#include "pwc-timon.h" - -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 */ - { - /* 5 fps */ - { - {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, - {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, - {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, - {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}}, - }, - /* 10 fps */ - { - {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, - {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, - {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, - {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}}, - }, - /* 15 fps */ - { - {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, - {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, - {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, - {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}}, - }, - /* 20 fps */ - { - {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, - {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, - {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, - {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}}, - }, - /* 25 fps */ - { - {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, - {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, - {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, - {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}}, - }, - /* 30 fps */ - { - {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, - {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, - {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, - {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}}, - }, - }, - /* QSIF */ - { - /* 5 fps */ - { - {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, - {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, - {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, - {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}}, - }, - /* 10 fps */ - { - {2, 291, 0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}}, - {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, - {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, - {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, - }, - /* 15 fps */ - { - {3, 437, 0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}}, - {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, - {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, - {1, 191, 420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}}, - }, - /* 20 fps */ - { - {4, 588, 0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}}, - {3, 447, 730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, - {2, 292, 476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}}, - {1, 192, 312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}}, - }, - /* 25 fps */ - { - {5, 703, 0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}}, - {3, 447, 610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, - {2, 292, 398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}}, - {1, 192, 262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}}, - }, - /* 30 fps */ - { - {8, 873, 0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}}, - {5, 704, 774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}}, - {3, 448, 492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}}, - {2, 291, 320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}}, - }, - }, - /* QCIF */ - { - /* 5 fps */ - { - {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, - {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, - {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, - {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}}, - }, - /* 10 fps */ - { - {3, 385, 0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}}, - {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, - {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}}, - {1, 194, 532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}}, - }, - /* 15 fps */ - { - {4, 577, 0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}}, - {3, 447, 818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}}, - {2, 292, 534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}}, - {1, 195, 356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}}, - }, - /* 20 fps */ - { - {6, 776, 0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}}, - {4, 591, 804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}}, - {3, 447, 608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, - {2, 291, 396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}}, - }, - /* 25 fps */ - { - {9, 928, 0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}}, - {5, 703, 800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}}, - {3, 447, 508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}}, - {2, 292, 332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}}, - }, - /* 30 fps */ - { - {0, }, - {9, 956, 876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}}, - {4, 592, 542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}}, - {2, 291, 266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}}, - }, - }, - /* SIF */ - { - /* 5 fps */ - { - {4, 582, 0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}}, - {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}}, - {2, 291, 960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}}, - {1, 191, 630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}}, - }, - /* 10 fps */ - { - {0, }, - {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}}, - {3, 447, 736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}}, - {2, 291, 480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}}, - }, - /* 15 fps */ - { - {0, }, - {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}}, - {4, 591, 650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}}, - {3, 448, 492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}}, - }, - /* 20 fps */ - { - {0, }, - {9, 958, 782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}}, - {5, 703, 574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}}, - {3, 446, 364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}}, - }, - /* 25 fps */ - { - {0, }, - {9, 958, 654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}}, - {6, 776, 530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}}, - {4, 592, 404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}}, - }, - /* 30 fps */ - { - {0, }, - {9, 957, 526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}}, - {6, 775, 426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}}, - {4, 590, 324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}}, - }, - }, - /* CIF */ - { - /* 5 fps */ - { - {6, 771, 0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}}, - {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}}, - {2, 291, 800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}}, - {1, 193, 528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}}, - }, - /* 10 fps */ - { - {0, }, - {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}}, - {4, 591, 812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}}, - {2, 291, 400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}}, - }, - /* 15 fps */ - { - {0, }, - {9, 956, 876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}}, - {5, 703, 644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}}, - {3, 448, 410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}}, - }, - /* 20 fps */ - { - {0, }, - {9, 956, 650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}}, - {6, 776, 528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}}, - {4, 591, 402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}}, - }, - /* 25 fps */ - { - {0, }, - {9, 956, 544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}}, - {7, 840, 478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}}, - {5, 703, 400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}}, - }, - /* 30 fps */ - { - {0, }, - {9, 956, 438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}}, - {7, 838, 384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}}, - {6, 773, 354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}}, - }, - }, - /* VGA */ - { - /* 5 fps */ - { - {0, }, - {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}}, - {4, 592, 976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}}, - {3, 448, 738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}}, - }, - /* 10 fps */ - { - {0, }, - {9, 956, 788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}}, - {6, 776, 640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}}, - {4, 592, 488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}}, - }, - /* 15 fps */ - { - {0, }, - {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}}, - {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}}, - {8, 895, 492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}}, - }, - /* 20 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 25 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - /* 30 fps */ - { - {0, }, - {0, }, - {0, }, - {0, }, - }, - }, -}; - -/* - * 16 versions: - * 2 tables (one for Y, and one for U&V) - * 16 levels of details per tables - * 8 blocs - */ - -const unsigned int TimonRomTable [16][2][16][8] = -{ - { /* version 0 */ - { /* version 0, passes 0 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000001}, - {0x00000000,0x00000000,0x00000001,0x00000001, - 0x00000001,0x00000001,0x00000001,0x00000001}, - {0x00000000,0x00000000,0x00000001,0x00000001, - 0x00000001,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000009,0x00000001, - 0x00000009,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000009,0x00000049,0x00000009}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000009,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000249,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000249,0x00000249,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000249,0x0000124a,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009252,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 0, passes 1 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000001,0x00000001, - 0x00000001,0x00000001,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000009,0x00000001, - 0x00000001,0x00000009,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000009,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000009,0x00000001,0x00000000}, - {0x00000000,0x00000000,0x00000049,0x00000009, - 0x00000009,0x00000049,0x00000001,0x00000001}, - {0x00000000,0x00000000,0x00000049,0x00000009, - 0x00000009,0x00000049,0x00000001,0x00000001}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000009,0x00000001}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000009,0x00000001}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000009,0x00000001}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000249,0x00000049,0x00000009}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000249,0x00000049,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000249,0x00000249,0x00000049,0x00000009}, - {0x00000000,0x00000000,0x00001249,0x00000249, - 0x0000124a,0x0000124a,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 1 */ - { /* version 1, passes 0 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000001}, - {0x00000000,0x00000000,0x00000001,0x00000001, - 0x00000001,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000009,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000249,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00001252}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x0000124a,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009252,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009252,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009292,0x00009493,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 1, passes 1 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000001,0x00000001,0x00000000}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000009,0x00000001,0x00000000}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000009,0x00000001,0x00000000}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000001,0x00000001}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000009,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000049,0x00000249,0x00000009,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000249,0x00000249,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x00000049,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00000049,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00000049,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009252,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 2 */ - { /* version 2, passes 0 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000001}, - {0x00000000,0x00000000,0x00000009,0x00000009, - 0x00000009,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00001252}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009252,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009252,0x00009493,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009292,0x00009493,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x00009252, - 0x00009492,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x000124db,0x000124db,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000126dc,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 2, passes 1 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000049,0x00000009, - 0x00000049,0x00000009,0x00000001,0x00000000}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000000}, - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000249,0x00000049,0x0000024a,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x0000024a,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x0000024a,0x00000009}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00009252,0x00001252,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00009292,0x00001252,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00009292,0x00001252,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009292,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x0000924a,0x0000924a, - 0x00009492,0x00009493,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 3 */ - { /* version 3, passes 0 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000001}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000049,0x00000249, - 0x00000249,0x00000249,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x00009252,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009292,0x00009292,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009292,0x00009493,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x00009252, - 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009292,0x0000a49b,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x000124db,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x0000a49b,0x000124db,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0001249b,0x000126dc,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x0001b725,0x000136e4}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 3, passes 1 */ - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000}, - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000001,0x00000000}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x00000049,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x00000001}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x00001252,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009252,0x00009292,0x00000009}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00009252,0x00009292,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009252,0x00009292,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009493,0x00009292,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009493,0x00009292,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009493,0x00009493,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009292,0x00009493,0x00009493,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x00009493,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x00009292, - 0x0000a493,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 4 */ - { /* version 4, passes 0 */ - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x00009252,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009493,0x00009493,0x0000a49b}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009292,0x00009493,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x000124db,0x000124db,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x00009252,0x000124db, - 0x000126dc,0x0001b724,0x0001b725,0x0001b925}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 4, passes 1 */ - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00000249, - 0x0000124a,0x0000124a,0x00001252,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00009292,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x0000a49b,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x0000a49b,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x00009252,0x0000a49b, - 0x0001249b,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 5 */ - { /* version 5, passes 0 */ - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x0000124a,0x00001252,0x00009292}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x0000124a,0x00009292,0x00009292,0x00009493}, - {0x00000000,0x00000000,0x00000249,0x0000924a, - 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x000124db,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x000124db,0x000124db,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0001249b,0x000126dc,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000126dc,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x000136e4,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b724,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 5, passes 1 */ - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x00009493,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x00009493,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x00009493,0x000124db,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x00009493,0x000124db,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x000124db,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x000124db,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009252,0x000124db, - 0x000126dc,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 6 */ - { /* version 6, passes 0 */ - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x0000124a,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x0000a49b,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000136e4,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x0001b725,0x0001b925}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x000136e4,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x000136e4,0x0001b925,0x00025bb6,0x00024b77}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 6, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00000249, - 0x0000124a,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x00009493,0x0000a49b,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x000126dc,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000136e4,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001b724,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 7 */ - { /* version 7, passes 0 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x0000a49b,0x000124db,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0001249b,0x000126dc,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x0001b725,0x0001b925}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x00009292,0x000124db, - 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b724,0x0001c96e,0x0002496e}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x000136e4,0x0001b925,0x0001c96e,0x0002496e}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x0002496d,0x00025bb6,0x00025bbf}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 7, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x00009493,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x000136e4,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x000136e4,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000124db,0x000136e4,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x000136e4,0x0001b724,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00012492,0x000126db, - 0x0001b724,0x0001b925,0x0001b725,0x000136e4}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 8 */ - { /* version 8, passes 0 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009292,0x00009493,0x0000a49b,0x000124db}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x000124db,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x000136e4}, - {0x00000000,0x00000000,0x00001249,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000136e4,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x0001b725,0x0001b925}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d}, - {0x00000000,0x00000000,0x00009252,0x000124db, - 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d}, - {0x00000000,0x00000000,0x00009292,0x000124db, - 0x000126dc,0x0001b925,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b925,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b925,0x00024b76,0x00024b77}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x000136e4,0x0001b925,0x00024b76,0x00025bbf}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x000136e4,0x0001c92d,0x00024b76,0x00025bbf}, - {0x00000000,0x00000000,0x00012492,0x000136db, - 0x0001b724,0x00024b6d,0x0002ddb6,0x0002efff}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 8, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009493,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000126dc,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000136e4,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00009292,0x000124db, - 0x000136e4,0x0001b724,0x0001b725,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x000136e4,0x0001b925,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x000136e4,0x0001b925,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x0002496d,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 9 */ - { /* version 9, passes 0 */ - {0x00000000,0x00000000,0x00000049,0x00000049, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000249,0x00000249,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x0000124a,0x00009252,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009292,0x00009493,0x00009493,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0001249b,0x000126dc,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00009252,0x00009493, - 0x000124db,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009252,0x0000a49b, - 0x000124db,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x000136e4,0x0001b925,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 9, passes 1 */ - {0x00000000,0x00000000,0x00000249,0x00000049, - 0x00000009,0x00000009,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000049,0x00000049,0x00000009,0x00000009}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00000249,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x0000124a,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009252,0x0000124a,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x00009252,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x00009292,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x00009292,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x00009493,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000124db,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009252,0x000124db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 10 */ - { /* version 10, passes 0 */ - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00000249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x00009493,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x000124db,0x000124db,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0001249b,0x000126dc,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000126dc,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009252,0x0000a49b, - 0x000124db,0x000136e4,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000126dc,0x0001b925,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x000136e4,0x0002496d,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 10, passes 1 */ - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000049,0x00000049,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00000249,0x00000049,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x00009252,0x0000024a,0x00000049}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009493,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00009252, - 0x00009492,0x00009493,0x00001252,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x00009493,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x00009492,0x00009493,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x00009493,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009252,0x000126db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 11 */ - { /* version 11, passes 0 */ - {0x00000000,0x00000000,0x00000249,0x00000249, - 0x00000249,0x00000249,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009492,0x0000a49b,0x0000a49b,0x00009292}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x000124db,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000126dc,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b725,0x000136e4}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b925,0x0001c96e,0x0001b925}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001c924,0x0002496d,0x00025bb6,0x00024b77}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 11, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00000249, - 0x00000249,0x00000249,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009252,0x00009252,0x0000024a,0x0000024a}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x0000a49b,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x0000a49b,0x00009292,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000124db,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000124db,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000126dc,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009292,0x000124db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 12 */ - { /* version 12, passes 0 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x0000a493,0x0000a49b,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x000126dc,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b725,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b92d,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b724,0x0001b92d,0x0001b724}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b925,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001c92d,0x00024b76,0x0002496e}, - {0x00000000,0x00000000,0x00012492,0x000126db, - 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 12, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x00001249,0x00009292, - 0x00009492,0x00009252,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x00009292,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000124db,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000124db,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000126dc,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x000136e4,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00009492,0x000126db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 13 */ - { /* version 13, passes 0 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x00009252,0x00009292,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x000124db,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x0000a49b, - 0x0001249b,0x000126dc,0x000126dc,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x000136e4,0x0001b725,0x000124db}, - {0x00000000,0x00000000,0x00009292,0x0000a49b, - 0x000136e4,0x0001b724,0x0001b725,0x000126dc}, - {0x00000000,0x00000000,0x00009292,0x000124db, - 0x000136e4,0x0001b724,0x0001b725,0x000126dc}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b724,0x0001c96e,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b924,0x0001c92d,0x00024b76,0x0002496e}, - {0x00000000,0x00000000,0x00012492,0x000136db, - 0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 13, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x00009492,0x00009292,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x0000a49b,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000124db,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000136db, - 0x0001b724,0x000124db,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000136db, - 0x0001b724,0x000126dc,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00009292,0x000136db, - 0x0001b724,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000136db, - 0x0001b724,0x000126dc,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00012492,0x0001b6db, - 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 14 */ - { /* version 14, passes 0 */ - {0x00000000,0x00000000,0x00001249,0x0000924a, - 0x00009292,0x00009493,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00001249,0x0000a49b, - 0x0000a493,0x000124db,0x000126dc,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x0000a49b}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x000136e4,0x0001b725,0x000124db}, - {0x00000000,0x00000000,0x00009292,0x000124db, - 0x000126dc,0x0001b724,0x0001b92d,0x000126dc}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b724,0x0001b92d,0x000126dc}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001c92d,0x0001c96e,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001c92d,0x00024b76,0x0001b925}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x0001c92d,0x00024b76,0x0002496e}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b924,0x0002496d,0x00024b76,0x00024b77}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b924,0x00024b6d,0x0002ddb6,0x00025bbf}, - {0x00000000,0x00000000,0x00012492,0x0001b6db, - 0x00024924,0x0002db6d,0x00036db6,0x0002efff}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 14, passes 1 */ - {0x00000000,0x00000000,0x00001249,0x00001249, - 0x0000124a,0x0000124a,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x00009493, - 0x0000a493,0x00009292,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x0000a49b,0x00001252,0x00001252}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000136e4,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000136e4,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x000136e4,0x00009493,0x00009292}, - {0x00000000,0x00000000,0x00009492,0x000136db, - 0x0001b724,0x000136e4,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x00009492,0x000136db, - 0x0001b724,0x000136e4,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x00009492,0x000136db, - 0x0001b724,0x000136e4,0x0000a49b,0x00009493}, - {0x00000000,0x00000000,0x00009492,0x000136db, - 0x0001b724,0x000136e4,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x000136e4,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x000136e4,0x000124db,0x0000a49b}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b724,0x000136e4,0x000126dc,0x000124db}, - {0x00000000,0x00000000,0x00012492,0x0001b6db, - 0x0001c924,0x0001b724,0x000136e4,0x000126dc}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - }, - { /* version 15 */ - { /* version 15, passes 0 */ - {0x00000000,0x00000000,0x00001249,0x00009493, - 0x0000a493,0x0000a49b,0x000124db,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0001249b,0x000126dc,0x000136e4,0x000124db}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x000126dc,0x0001b724,0x0001b725,0x000126dc}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x0001b724,0x0001b92d,0x000126dc}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x000136e4,0x0001b925,0x0001c96e,0x000136e4}, - {0x00000000,0x00000000,0x00009492,0x000124db, - 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000124db, - 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925}, - {0x00000000,0x00000000,0x0000a492,0x000126db, - 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001b924,0x0002496d,0x00024b76,0x0002496e}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x0002496d,0x00025bb6,0x00024b77}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x00024b6d,0x00025bb6,0x00024b77}, - {0x00000000,0x00000000,0x00012492,0x000136db, - 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf}, - {0x00000000,0x00000000,0x00012492,0x0001b6db, - 0x00024924,0x0002db6d,0x00036db6,0x0002efff}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - }, - { /* version 15, passes 1 */ - {0x00000000,0x00000000,0x0000924a,0x0000924a, - 0x00009292,0x00009292,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x0000a49b, - 0x0000a493,0x000124db,0x00009292,0x00009292}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000124db,0x0001b724,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000126dc,0x0001b724,0x00009493,0x00009493}, - {0x00000000,0x00000000,0x0000924a,0x000124db, - 0x000136e4,0x0001b724,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00009292,0x000136db, - 0x0001b724,0x0001b724,0x0000a49b,0x0000a49b}, - {0x00000000,0x00000000,0x00009492,0x000136db, - 0x0001c924,0x0001b724,0x000124db,0x000124db}, - {0x00000000,0x00000000,0x00009492,0x000136db, - 0x0001c924,0x0001b724,0x000124db,0x000124db}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x0001b724,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x0001b925,0x000126dc,0x000126dc}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x0001b925,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x0001b925,0x000136e4,0x000136e4}, - {0x00000000,0x00000000,0x0000a492,0x000136db, - 0x0001c924,0x0001b925,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x00012492,0x000136db, - 0x0001c924,0x0001b925,0x0001b725,0x0001b724}, - {0x00000000,0x00000000,0x00012492,0x0001b6db, - 0x00024924,0x0002496d,0x0001b92d,0x0001b925}, - {0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000} - } - } -}; diff --git a/drivers/media/video/pwc/pwc-timon.h b/drivers/media/video/pwc/pwc-timon.h deleted file mode 100644 index 270c5b9010f6..000000000000 --- a/drivers/media/video/pwc/pwc-timon.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Linux driver for Philips webcam - (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. - Please send bug reports and support requests to <luc@saillard.org>. - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - - -/* This tables contains entries for the 675/680/690 (Timon) camera, with - 4 different qualities (no compression, low, medium, high). - It lists the bandwidth requirements for said mode by its alternate interface - number. An alternate of 0 means that the mode is unavailable. - - There are 6 * 4 * 4 entries: - 6 different resolutions subqcif, qsif, qcif, sif, cif, vga - 6 framerates: 5, 10, 15, 20, 25, 30 - 4 compression modi: none, low, medium, high - - When an uncompressed mode is not available, the next available compressed mode - will be chosen (unless the decompressor is absent). Sometimes there are only - 1 or 2 compressed modes available; in that case entries are duplicated. -*/ - -#ifndef PWC_TIMON_H -#define PWC_TIMON_H - -#include "pwc.h" - -#define PWC_FPS_MAX_TIMON 6 - -struct Timon_table_entry -{ - char alternate; /* USB alternate interface */ - unsigned short packetsize; /* Normal packet size */ - unsigned short bandlength; /* Bandlength when decompressing */ - unsigned char mode[13]; /* precomputed mode settings for cam */ -}; - -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/drivers/media/video/pwc/pwc-uncompress.c b/drivers/media/video/pwc/pwc-uncompress.c deleted file mode 100644 index b65903fbcf0d..000000000000 --- a/drivers/media/video/pwc/pwc-uncompress.c +++ /dev/null @@ -1,107 +0,0 @@ -/* Linux driver for Philips webcam - Decompression frontend. - (C) 1999-2003 Nemosoft Unv. - (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. - Please send bug reports and support requests to <luc@saillard.org>. - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - vim: set ts=8: -*/ - -#include <asm/current.h> -#include <asm/types.h> - -#include "pwc.h" -#include "pwc-dec1.h" -#include "pwc-dec23.h" - -int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) -{ - int n, line, col; - void *yuv, *image; - u16 *src; - u16 *dsty, *dstu, *dstv; - - image = vb2_plane_vaddr(&fbuf->vb, 0); - - yuv = fbuf->data + pdev->frame_header_size; /* Skip header */ - - /* Raw format; that's easy... */ - if (pdev->pixfmt != V4L2_PIX_FMT_YUV420) - { - struct pwc_raw_frame *raw_frame = image; - raw_frame->type = cpu_to_le16(pdev->type); - raw_frame->vbandlength = cpu_to_le16(pdev->vbandlength); - /* cmd_buf is always 4 bytes, but sometimes, only the - * first 3 bytes is filled (Nala case). We can - * determine this using the type of the webcam */ - memcpy(raw_frame->cmd, pdev->cmd_buf, 4); - memcpy(raw_frame+1, yuv, pdev->frame_size); - vb2_set_plane_payload(&fbuf->vb, 0, - pdev->frame_size + sizeof(struct pwc_raw_frame)); - return 0; - } - - vb2_set_plane_payload(&fbuf->vb, 0, - pdev->width * pdev->height * 3 / 2); - - if (pdev->vbandlength == 0) { - /* Uncompressed mode. - * - * We do some byte shuffling here to go from the - * native format to YUV420P. - */ - src = (u16 *)yuv; - n = pdev->width * pdev->height; - dsty = (u16 *)(image); - dstu = (u16 *)(image + n); - dstv = (u16 *)(image + n + n / 4); - - for (line = 0; line < pdev->height; line++) { - for (col = 0; col < pdev->width; col += 4) { - *dsty++ = *src++; - *dsty++ = *src++; - if (line & 1) - *dstv++ = *src++; - else - *dstu++ = *src++; - } - } - - return 0; - } - - /* - * Compressed; - * the decompressor routines will write the data in planar format - * immediately. - */ - if (DEVICE_USE_CODEC1(pdev->type)) { - - /* TODO & FIXME */ - PWC_ERROR("This chipset is not supported for now\n"); - return -ENXIO; /* No such device or address: missing decompressor */ - - } else { - pwc_dec23_decompress(pdev, yuv, image); - } - return 0; -} diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c deleted file mode 100644 index 545e9bbdeede..000000000000 --- a/drivers/media/video/pwc/pwc-v4l.c +++ /dev/null @@ -1,1053 +0,0 @@ -/* Linux driver for Philips webcam - USB and Video4Linux interface part. - (C) 1999-2004 Nemosoft Unv. - (C) 2004-2006 Luc Saillard (luc@saillard.org) - (C) 2011 Hans de Goede <hdegoede@redhat.com> - - 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. - Please send bug reports and support requests to <luc@saillard.org>. - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/poll.h> -#include <linux/vmalloc.h> -#include <linux/jiffies.h> -#include <asm/io.h> - -#include "pwc.h" - -#define PWC_CID_CUSTOM(ctrl) ((V4L2_CID_USER_BASE | 0xf000) + custom_ ## ctrl) - -static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl); -static int pwc_s_ctrl(struct v4l2_ctrl *ctrl); - -static const struct v4l2_ctrl_ops pwc_ctrl_ops = { - .g_volatile_ctrl = pwc_g_volatile_ctrl, - .s_ctrl = pwc_s_ctrl, -}; - -enum { awb_indoor, awb_outdoor, awb_fl, awb_manual, awb_auto }; -enum { custom_autocontour, custom_contour, custom_noise_reduction, - custom_awb_speed, custom_awb_delay, - custom_save_user, custom_restore_user, custom_restore_factory }; - -const char * const pwc_auto_whitebal_qmenu[] = { - "Indoor (Incandescant Lighting) Mode", - "Outdoor (Sunlight) Mode", - "Indoor (Fluorescent Lighting) Mode", - "Manual Mode", - "Auto Mode", - NULL -}; - -static const struct v4l2_ctrl_config pwc_auto_white_balance_cfg = { - .ops = &pwc_ctrl_ops, - .id = V4L2_CID_AUTO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_MENU, - .max = awb_auto, - .qmenu = pwc_auto_whitebal_qmenu, -}; - -static const struct v4l2_ctrl_config pwc_autocontour_cfg = { - .ops = &pwc_ctrl_ops, - .id = PWC_CID_CUSTOM(autocontour), - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Auto contour", - .min = 0, - .max = 1, - .step = 1, -}; - -static const struct v4l2_ctrl_config pwc_contour_cfg = { - .ops = &pwc_ctrl_ops, - .id = PWC_CID_CUSTOM(contour), - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contour", - .flags = V4L2_CTRL_FLAG_SLIDER, - .min = 0, - .max = 63, - .step = 1, -}; - -static const struct v4l2_ctrl_config pwc_backlight_cfg = { - .ops = &pwc_ctrl_ops, - .id = V4L2_CID_BACKLIGHT_COMPENSATION, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .min = 0, - .max = 1, - .step = 1, -}; - -static const struct v4l2_ctrl_config pwc_flicker_cfg = { - .ops = &pwc_ctrl_ops, - .id = V4L2_CID_BAND_STOP_FILTER, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .min = 0, - .max = 1, - .step = 1, -}; - -static const struct v4l2_ctrl_config pwc_noise_reduction_cfg = { - .ops = &pwc_ctrl_ops, - .id = PWC_CID_CUSTOM(noise_reduction), - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Dynamic Noise Reduction", - .min = 0, - .max = 3, - .step = 1, -}; - -static const struct v4l2_ctrl_config pwc_save_user_cfg = { - .ops = &pwc_ctrl_ops, - .id = PWC_CID_CUSTOM(save_user), - .type = V4L2_CTRL_TYPE_BUTTON, - .name = "Save User Settings", -}; - -static const struct v4l2_ctrl_config pwc_restore_user_cfg = { - .ops = &pwc_ctrl_ops, - .id = PWC_CID_CUSTOM(restore_user), - .type = V4L2_CTRL_TYPE_BUTTON, - .name = "Restore User Settings", -}; - -static const struct v4l2_ctrl_config pwc_restore_factory_cfg = { - .ops = &pwc_ctrl_ops, - .id = PWC_CID_CUSTOM(restore_factory), - .type = V4L2_CTRL_TYPE_BUTTON, - .name = "Restore Factory Settings", -}; - -static const struct v4l2_ctrl_config pwc_awb_speed_cfg = { - .ops = &pwc_ctrl_ops, - .id = PWC_CID_CUSTOM(awb_speed), - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Auto White Balance Speed", - .min = 1, - .max = 32, - .step = 1, -}; - -static const struct v4l2_ctrl_config pwc_awb_delay_cfg = { - .ops = &pwc_ctrl_ops, - .id = PWC_CID_CUSTOM(awb_delay), - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Auto White Balance Delay", - .min = 0, - .max = 63, - .step = 1, -}; - -int pwc_init_controls(struct pwc_device *pdev) -{ - struct v4l2_ctrl_handler *hdl; - struct v4l2_ctrl_config cfg; - int r, def; - - hdl = &pdev->ctrl_handler; - r = v4l2_ctrl_handler_init(hdl, 20); - if (r) - return r; - - /* Brightness, contrast, saturation, gamma */ - r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, BRIGHTNESS_FORMATTER, &def); - if (r || def > 127) - def = 63; - pdev->brightness = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops, - V4L2_CID_BRIGHTNESS, 0, 127, 1, def); - - r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, CONTRAST_FORMATTER, &def); - if (r || def > 63) - def = 31; - pdev->contrast = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops, - V4L2_CID_CONTRAST, 0, 63, 1, def); - - if (pdev->type >= 675) { - if (pdev->type < 730) - pdev->saturation_fmt = SATURATION_MODE_FORMATTER2; - else - pdev->saturation_fmt = SATURATION_MODE_FORMATTER1; - r = pwc_get_s8_ctrl(pdev, GET_CHROM_CTL, pdev->saturation_fmt, - &def); - if (r || def < -100 || def > 100) - def = 0; - pdev->saturation = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops, - V4L2_CID_SATURATION, -100, 100, 1, def); - } - - r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, GAMMA_FORMATTER, &def); - if (r || def > 31) - def = 15; - pdev->gamma = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops, - V4L2_CID_GAMMA, 0, 31, 1, def); - - /* auto white balance, red gain, blue gain */ - r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, WB_MODE_FORMATTER, &def); - if (r || def > awb_auto) - def = awb_auto; - cfg = pwc_auto_white_balance_cfg; - cfg.name = v4l2_ctrl_get_name(cfg.id); - cfg.def = def; - pdev->auto_white_balance = v4l2_ctrl_new_custom(hdl, &cfg, NULL); - /* check auto controls to avoid NULL deref in v4l2_ctrl_auto_cluster */ - if (!pdev->auto_white_balance) - return hdl->error; - - r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, - PRESET_MANUAL_RED_GAIN_FORMATTER, &def); - if (r) - def = 127; - pdev->red_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops, - V4L2_CID_RED_BALANCE, 0, 255, 1, def); - - r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, - PRESET_MANUAL_BLUE_GAIN_FORMATTER, &def); - if (r) - def = 127; - pdev->blue_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops, - V4L2_CID_BLUE_BALANCE, 0, 255, 1, def); - - v4l2_ctrl_auto_cluster(3, &pdev->auto_white_balance, awb_manual, true); - - /* autogain, gain */ - r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, AGC_MODE_FORMATTER, &def); - if (r || (def != 0 && def != 0xff)) - def = 0; - /* Note a register value if 0 means auto gain is on */ - pdev->autogain = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops, - V4L2_CID_AUTOGAIN, 0, 1, 1, def == 0); - if (!pdev->autogain) - return hdl->error; - - r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, PRESET_AGC_FORMATTER, &def); - if (r || def > 63) - def = 31; - pdev->gain = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops, - V4L2_CID_GAIN, 0, 63, 1, def); - - /* auto exposure, exposure */ - if (DEVICE_USE_CODEC2(pdev->type)) { - r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, SHUTTER_MODE_FORMATTER, - &def); - if (r || (def != 0 && def != 0xff)) - def = 0; - /* - * def = 0 auto, def = ff manual - * menu idx 0 = auto, idx 1 = manual - */ - pdev->exposure_auto = v4l2_ctrl_new_std_menu(hdl, - &pwc_ctrl_ops, - V4L2_CID_EXPOSURE_AUTO, - 1, 0, def != 0); - if (!pdev->exposure_auto) - return hdl->error; - - /* GET_LUM_CTL, PRESET_SHUTTER_FORMATTER is unreliable */ - r = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL, - READ_SHUTTER_FORMATTER, &def); - if (r || def > 655) - def = 655; - pdev->exposure = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 655, 1, def); - /* CODEC2: separate auto gain & auto exposure */ - v4l2_ctrl_auto_cluster(2, &pdev->autogain, 0, true); - v4l2_ctrl_auto_cluster(2, &pdev->exposure_auto, - V4L2_EXPOSURE_MANUAL, true); - } else if (DEVICE_USE_CODEC3(pdev->type)) { - /* GET_LUM_CTL, PRESET_SHUTTER_FORMATTER is unreliable */ - r = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL, - READ_SHUTTER_FORMATTER, &def); - if (r || def > 255) - def = 255; - pdev->exposure = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 255, 1, def); - /* CODEC3: both gain and exposure controlled by autogain */ - pdev->autogain_expo_cluster[0] = pdev->autogain; - pdev->autogain_expo_cluster[1] = pdev->gain; - pdev->autogain_expo_cluster[2] = pdev->exposure; - v4l2_ctrl_auto_cluster(3, pdev->autogain_expo_cluster, - 0, true); - } - - /* color / bw setting */ - r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, COLOUR_MODE_FORMATTER, - &def); - if (r || (def != 0 && def != 0xff)) - def = 0xff; - /* def = 0 bw, def = ff color, menu idx 0 = color, idx 1 = bw */ - pdev->colorfx = v4l2_ctrl_new_std_menu(hdl, &pwc_ctrl_ops, - V4L2_CID_COLORFX, 1, 0, def == 0); - - /* autocontour, contour */ - r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &def); - if (r || (def != 0 && def != 0xff)) - def = 0; - cfg = pwc_autocontour_cfg; - cfg.def = def == 0; - pdev->autocontour = v4l2_ctrl_new_custom(hdl, &cfg, NULL); - if (!pdev->autocontour) - return hdl->error; - - r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, &def); - if (r || def > 63) - def = 31; - cfg = pwc_contour_cfg; - cfg.def = def; - pdev->contour = v4l2_ctrl_new_custom(hdl, &cfg, NULL); - - v4l2_ctrl_auto_cluster(2, &pdev->autocontour, 0, false); - - /* backlight */ - r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, - BACK_LIGHT_COMPENSATION_FORMATTER, &def); - if (r || (def != 0 && def != 0xff)) - def = 0; - cfg = pwc_backlight_cfg; - cfg.name = v4l2_ctrl_get_name(cfg.id); - cfg.def = def == 0; - pdev->backlight = v4l2_ctrl_new_custom(hdl, &cfg, NULL); - - /* flikker rediction */ - r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, - FLICKERLESS_MODE_FORMATTER, &def); - if (r || (def != 0 && def != 0xff)) - def = 0; - cfg = pwc_flicker_cfg; - cfg.name = v4l2_ctrl_get_name(cfg.id); - cfg.def = def == 0; - pdev->flicker = v4l2_ctrl_new_custom(hdl, &cfg, NULL); - - /* Dynamic noise reduction */ - r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, - DYNAMIC_NOISE_CONTROL_FORMATTER, &def); - if (r || def > 3) - def = 2; - cfg = pwc_noise_reduction_cfg; - cfg.def = def; - pdev->noise_reduction = v4l2_ctrl_new_custom(hdl, &cfg, NULL); - - /* Save / Restore User / Factory Settings */ - pdev->save_user = v4l2_ctrl_new_custom(hdl, &pwc_save_user_cfg, NULL); - pdev->restore_user = v4l2_ctrl_new_custom(hdl, &pwc_restore_user_cfg, - NULL); - if (pdev->restore_user) - pdev->restore_user->flags |= V4L2_CTRL_FLAG_UPDATE; - pdev->restore_factory = v4l2_ctrl_new_custom(hdl, - &pwc_restore_factory_cfg, - NULL); - if (pdev->restore_factory) - pdev->restore_factory->flags |= V4L2_CTRL_FLAG_UPDATE; - - /* Auto White Balance speed & delay */ - r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, - AWB_CONTROL_SPEED_FORMATTER, &def); - if (r || def < 1 || def > 32) - def = 1; - cfg = pwc_awb_speed_cfg; - cfg.def = def; - pdev->awb_speed = v4l2_ctrl_new_custom(hdl, &cfg, NULL); - - r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, - AWB_CONTROL_DELAY_FORMATTER, &def); - if (r || def > 63) - def = 0; - cfg = pwc_awb_delay_cfg; - cfg.def = def; - pdev->awb_delay = v4l2_ctrl_new_custom(hdl, &cfg, NULL); - - if (!(pdev->features & FEATURE_MOTOR_PANTILT)) - return hdl->error; - - /* Motor pan / tilt / reset */ - pdev->motor_pan = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops, - V4L2_CID_PAN_RELATIVE, -4480, 4480, 64, 0); - if (!pdev->motor_pan) - return hdl->error; - pdev->motor_tilt = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops, - V4L2_CID_TILT_RELATIVE, -1920, 1920, 64, 0); - pdev->motor_pan_reset = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops, - V4L2_CID_PAN_RESET, 0, 0, 0, 0); - pdev->motor_tilt_reset = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops, - V4L2_CID_TILT_RESET, 0, 0, 0, 0); - v4l2_ctrl_cluster(4, &pdev->motor_pan); - - return hdl->error; -} - -static void pwc_vidioc_fill_fmt(struct v4l2_format *f, - int width, int height, u32 pixfmt) -{ - memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); - f->fmt.pix.width = width; - f->fmt.pix.height = height; - f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.pixelformat = pixfmt; - f->fmt.pix.bytesperline = f->fmt.pix.width; - f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.width * 3 / 2; - f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; - PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() " - "width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n", - f->fmt.pix.width, - f->fmt.pix.height, - f->fmt.pix.bytesperline, - f->fmt.pix.sizeimage, - (f->fmt.pix.pixelformat)&255, - (f->fmt.pix.pixelformat>>8)&255, - (f->fmt.pix.pixelformat>>16)&255, - (f->fmt.pix.pixelformat>>24)&255); -} - -/* ioctl(VIDIOC_TRY_FMT) */ -static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f) -{ - int size; - - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); - return -EINVAL; - } - - switch (f->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_YUV420: - break; - case V4L2_PIX_FMT_PWC1: - if (DEVICE_USE_CODEC23(pdev->type)) { - PWC_DEBUG_IOCTL("codec1 is only supported for old pwc webcam\n"); - return -EINVAL; - } - break; - case V4L2_PIX_FMT_PWC2: - if (DEVICE_USE_CODEC1(pdev->type)) { - PWC_DEBUG_IOCTL("codec23 is only supported for new pwc webcam\n"); - return -EINVAL; - } - break; - default: - PWC_DEBUG_IOCTL("Unsupported pixel format\n"); - return -EINVAL; - - } - - size = pwc_get_size(pdev, f->fmt.pix.width, f->fmt.pix.height); - pwc_vidioc_fill_fmt(f, - pwc_image_sizes[size][0], - pwc_image_sizes[size][1], - f->fmt.pix.pixelformat); - - return 0; -} - -/* ioctl(VIDIOC_SET_FMT) */ - -static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) -{ - struct pwc_device *pdev = video_drvdata(file); - int ret, pixelformat, compression = 0; - - ret = pwc_vidioc_try_fmt(pdev, f); - if (ret < 0) - return ret; - - if (vb2_is_busy(&pdev->vb_queue)) - return -EBUSY; - - pixelformat = f->fmt.pix.pixelformat; - - PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d " - "format=%c%c%c%c\n", - f->fmt.pix.width, f->fmt.pix.height, pdev->vframes, - (pixelformat)&255, - (pixelformat>>8)&255, - (pixelformat>>16)&255, - (pixelformat>>24)&255); - - ret = pwc_set_video_mode(pdev, f->fmt.pix.width, f->fmt.pix.height, - pixelformat, 30, &compression, 0); - - PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret); - - pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt); - return ret; -} - -static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) -{ - struct pwc_device *pdev = video_drvdata(file); - - strcpy(cap->driver, PWC_NAME); - strlcpy(cap->card, pdev->vdev.name, sizeof(cap->card)); - usb_make_path(pdev->udev, cap->bus_info, sizeof(cap->bus_info)); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | - V4L2_CAP_READWRITE; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -static int pwc_enum_input(struct file *file, void *fh, struct v4l2_input *i) -{ - if (i->index) /* Only one INPUT is supported */ - return -EINVAL; - - strlcpy(i->name, "Camera", sizeof(i->name)); - i->type = V4L2_INPUT_TYPE_CAMERA; - return 0; -} - -static int pwc_g_input(struct file *file, void *fh, unsigned int *i) -{ - *i = 0; - return 0; -} - -static int pwc_s_input(struct file *file, void *fh, unsigned int i) -{ - return i ? -EINVAL : 0; -} - -static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl) -{ - struct pwc_device *pdev = - container_of(ctrl->handler, struct pwc_device, ctrl_handler); - int ret = 0; - - switch (ctrl->id) { - case V4L2_CID_AUTO_WHITE_BALANCE: - if (pdev->color_bal_valid && - (pdev->auto_white_balance->val != awb_auto || - time_before(jiffies, - pdev->last_color_bal_update + HZ / 4))) { - pdev->red_balance->val = pdev->last_red_balance; - pdev->blue_balance->val = pdev->last_blue_balance; - break; - } - ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL, - READ_RED_GAIN_FORMATTER, - &pdev->red_balance->val); - if (ret) - break; - ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL, - READ_BLUE_GAIN_FORMATTER, - &pdev->blue_balance->val); - if (ret) - break; - pdev->last_red_balance = pdev->red_balance->val; - pdev->last_blue_balance = pdev->blue_balance->val; - pdev->last_color_bal_update = jiffies; - pdev->color_bal_valid = true; - break; - case V4L2_CID_AUTOGAIN: - if (pdev->gain_valid && time_before(jiffies, - pdev->last_gain_update + HZ / 4)) { - pdev->gain->val = pdev->last_gain; - break; - } - ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL, - READ_AGC_FORMATTER, &pdev->gain->val); - if (ret) - break; - pdev->last_gain = pdev->gain->val; - pdev->last_gain_update = jiffies; - pdev->gain_valid = true; - if (!DEVICE_USE_CODEC3(pdev->type)) - break; - /* Fall through for CODEC3 where autogain also controls expo */ - case V4L2_CID_EXPOSURE_AUTO: - if (pdev->exposure_valid && time_before(jiffies, - pdev->last_exposure_update + HZ / 4)) { - pdev->exposure->val = pdev->last_exposure; - break; - } - ret = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL, - READ_SHUTTER_FORMATTER, - &pdev->exposure->val); - if (ret) - break; - pdev->last_exposure = pdev->exposure->val; - pdev->last_exposure_update = jiffies; - pdev->exposure_valid = true; - break; - default: - ret = -EINVAL; - } - - if (ret) - PWC_ERROR("g_ctrl %s error %d\n", ctrl->name, ret); - - return ret; -} - -static int pwc_set_awb(struct pwc_device *pdev) -{ - int ret; - - if (pdev->auto_white_balance->is_new) { - ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL, - WB_MODE_FORMATTER, - pdev->auto_white_balance->val); - if (ret) - return ret; - - if (pdev->auto_white_balance->val != awb_manual) - pdev->color_bal_valid = false; /* Force cache update */ - - /* - * If this is a preset, update our red / blue balance values - * so that events get generated for the new preset values - */ - if (pdev->auto_white_balance->val == awb_indoor || - pdev->auto_white_balance->val == awb_outdoor || - pdev->auto_white_balance->val == awb_fl) - pwc_g_volatile_ctrl(pdev->auto_white_balance); - } - if (pdev->auto_white_balance->val != awb_manual) - return 0; - - if (pdev->red_balance->is_new) { - ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL, - PRESET_MANUAL_RED_GAIN_FORMATTER, - pdev->red_balance->val); - if (ret) - return ret; - } - - if (pdev->blue_balance->is_new) { - ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL, - PRESET_MANUAL_BLUE_GAIN_FORMATTER, - pdev->blue_balance->val); - if (ret) - return ret; - } - return 0; -} - -/* For CODEC2 models which have separate autogain and auto exposure */ -static int pwc_set_autogain(struct pwc_device *pdev) -{ - int ret; - - if (pdev->autogain->is_new) { - ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, - AGC_MODE_FORMATTER, - pdev->autogain->val ? 0 : 0xff); - if (ret) - return ret; - - if (pdev->autogain->val) - pdev->gain_valid = false; /* Force cache update */ - } - - if (pdev->autogain->val) - return 0; - - if (pdev->gain->is_new) { - ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, - PRESET_AGC_FORMATTER, - pdev->gain->val); - if (ret) - return ret; - } - return 0; -} - -/* For CODEC2 models which have separate autogain and auto exposure */ -static int pwc_set_exposure_auto(struct pwc_device *pdev) -{ - int ret; - int is_auto = pdev->exposure_auto->val == V4L2_EXPOSURE_AUTO; - - if (pdev->exposure_auto->is_new) { - ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, - SHUTTER_MODE_FORMATTER, - is_auto ? 0 : 0xff); - if (ret) - return ret; - - if (is_auto) - pdev->exposure_valid = false; /* Force cache update */ - } - - if (is_auto) - return 0; - - if (pdev->exposure->is_new) { - ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL, - PRESET_SHUTTER_FORMATTER, - pdev->exposure->val); - if (ret) - return ret; - } - return 0; -} - -/* For CODEC3 models which have autogain controlling both gain and exposure */ -static int pwc_set_autogain_expo(struct pwc_device *pdev) -{ - int ret; - - if (pdev->autogain->is_new) { - ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, - AGC_MODE_FORMATTER, - pdev->autogain->val ? 0 : 0xff); - if (ret) - return ret; - - if (pdev->autogain->val) { - pdev->gain_valid = false; /* Force cache update */ - pdev->exposure_valid = false; /* Force cache update */ - } - } - - if (pdev->autogain->val) - return 0; - - if (pdev->gain->is_new) { - ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, - PRESET_AGC_FORMATTER, - pdev->gain->val); - if (ret) - return ret; - } - - if (pdev->exposure->is_new) { - ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL, - PRESET_SHUTTER_FORMATTER, - pdev->exposure->val); - if (ret) - return ret; - } - return 0; -} - -static int pwc_set_motor(struct pwc_device *pdev) -{ - int ret; - - pdev->ctrl_buf[0] = 0; - if (pdev->motor_pan_reset->is_new) - pdev->ctrl_buf[0] |= 0x01; - if (pdev->motor_tilt_reset->is_new) - pdev->ctrl_buf[0] |= 0x02; - if (pdev->motor_pan_reset->is_new || pdev->motor_tilt_reset->is_new) { - ret = send_control_msg(pdev, SET_MPT_CTL, - PT_RESET_CONTROL_FORMATTER, - pdev->ctrl_buf, 1); - if (ret < 0) - return ret; - } - - memset(pdev->ctrl_buf, 0, 4); - if (pdev->motor_pan->is_new) { - pdev->ctrl_buf[0] = pdev->motor_pan->val & 0xFF; - pdev->ctrl_buf[1] = (pdev->motor_pan->val >> 8); - } - if (pdev->motor_tilt->is_new) { - pdev->ctrl_buf[2] = pdev->motor_tilt->val & 0xFF; - pdev->ctrl_buf[3] = (pdev->motor_tilt->val >> 8); - } - if (pdev->motor_pan->is_new || pdev->motor_tilt->is_new) { - ret = send_control_msg(pdev, SET_MPT_CTL, - PT_RELATIVE_CONTROL_FORMATTER, - pdev->ctrl_buf, 4); - if (ret < 0) - return ret; - } - - return 0; -} - -static int pwc_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct pwc_device *pdev = - container_of(ctrl->handler, struct pwc_device, ctrl_handler); - int ret = 0; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, - BRIGHTNESS_FORMATTER, ctrl->val); - break; - case V4L2_CID_CONTRAST: - ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, - CONTRAST_FORMATTER, ctrl->val); - break; - case V4L2_CID_SATURATION: - ret = pwc_set_s8_ctrl(pdev, SET_CHROM_CTL, - pdev->saturation_fmt, ctrl->val); - break; - case V4L2_CID_GAMMA: - ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, - GAMMA_FORMATTER, ctrl->val); - break; - case V4L2_CID_AUTO_WHITE_BALANCE: - ret = pwc_set_awb(pdev); - break; - case V4L2_CID_AUTOGAIN: - if (DEVICE_USE_CODEC2(pdev->type)) - ret = pwc_set_autogain(pdev); - else if (DEVICE_USE_CODEC3(pdev->type)) - ret = pwc_set_autogain_expo(pdev); - else - ret = -EINVAL; - break; - case V4L2_CID_EXPOSURE_AUTO: - if (DEVICE_USE_CODEC2(pdev->type)) - ret = pwc_set_exposure_auto(pdev); - else - ret = -EINVAL; - break; - case V4L2_CID_COLORFX: - ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL, - COLOUR_MODE_FORMATTER, - ctrl->val ? 0 : 0xff); - break; - case PWC_CID_CUSTOM(autocontour): - if (pdev->autocontour->is_new) { - ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, - AUTO_CONTOUR_FORMATTER, - pdev->autocontour->val ? 0 : 0xff); - } - if (ret == 0 && pdev->contour->is_new) { - ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, - PRESET_CONTOUR_FORMATTER, - pdev->contour->val); - } - break; - case V4L2_CID_BACKLIGHT_COMPENSATION: - ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, - BACK_LIGHT_COMPENSATION_FORMATTER, - ctrl->val ? 0 : 0xff); - break; - case V4L2_CID_BAND_STOP_FILTER: - ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, - FLICKERLESS_MODE_FORMATTER, - ctrl->val ? 0 : 0xff); - break; - case PWC_CID_CUSTOM(noise_reduction): - ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, - DYNAMIC_NOISE_CONTROL_FORMATTER, - ctrl->val); - break; - case PWC_CID_CUSTOM(save_user): - ret = pwc_button_ctrl(pdev, SAVE_USER_DEFAULTS_FORMATTER); - break; - case PWC_CID_CUSTOM(restore_user): - ret = pwc_button_ctrl(pdev, RESTORE_USER_DEFAULTS_FORMATTER); - break; - case PWC_CID_CUSTOM(restore_factory): - ret = pwc_button_ctrl(pdev, - RESTORE_FACTORY_DEFAULTS_FORMATTER); - break; - case PWC_CID_CUSTOM(awb_speed): - ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL, - AWB_CONTROL_SPEED_FORMATTER, - ctrl->val); - break; - case PWC_CID_CUSTOM(awb_delay): - ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL, - AWB_CONTROL_DELAY_FORMATTER, - ctrl->val); - break; - case V4L2_CID_PAN_RELATIVE: - ret = pwc_set_motor(pdev); - break; - default: - ret = -EINVAL; - } - - if (ret) - PWC_ERROR("s_ctrl %s error %d\n", ctrl->name, ret); - - return ret; -} - -static int pwc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f) -{ - struct pwc_device *pdev = video_drvdata(file); - - /* We only support two format: the raw format, and YUV */ - switch (f->index) { - case 0: - /* RAW format */ - f->pixelformat = pdev->type <= 646 ? V4L2_PIX_FMT_PWC1 : V4L2_PIX_FMT_PWC2; - f->flags = V4L2_FMT_FLAG_COMPRESSED; - strlcpy(f->description, "Raw Philips Webcam", sizeof(f->description)); - break; - case 1: - f->pixelformat = V4L2_PIX_FMT_YUV420; - strlcpy(f->description, "4:2:0, planar, Y-Cb-Cr", sizeof(f->description)); - break; - default: - return -EINVAL; - } - return 0; -} - -static int pwc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) -{ - struct pwc_device *pdev = video_drvdata(file); - - if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n", - pdev->width, pdev->height); - pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt); - return 0; -} - -static int pwc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) -{ - struct pwc_device *pdev = video_drvdata(file); - - return pwc_vidioc_try_fmt(pdev, f); -} - -static int pwc_enum_framesizes(struct file *file, void *fh, - struct v4l2_frmsizeenum *fsize) -{ - struct pwc_device *pdev = video_drvdata(file); - unsigned int i = 0, index = fsize->index; - - if (fsize->pixel_format == V4L2_PIX_FMT_YUV420 || - (fsize->pixel_format == V4L2_PIX_FMT_PWC1 && - DEVICE_USE_CODEC1(pdev->type)) || - (fsize->pixel_format == V4L2_PIX_FMT_PWC2 && - DEVICE_USE_CODEC23(pdev->type))) { - for (i = 0; i < PSZ_MAX; i++) { - if (!(pdev->image_mask & (1UL << i))) - continue; - if (!index--) { - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - fsize->discrete.width = pwc_image_sizes[i][0]; - fsize->discrete.height = pwc_image_sizes[i][1]; - return 0; - } - } - } - return -EINVAL; -} - -static int pwc_enum_frameintervals(struct file *file, void *fh, - struct v4l2_frmivalenum *fival) -{ - struct pwc_device *pdev = video_drvdata(file); - int size = -1; - unsigned int i; - - for (i = 0; i < PSZ_MAX; i++) { - if (pwc_image_sizes[i][0] == fival->width && - pwc_image_sizes[i][1] == 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; -} - -static int pwc_g_parm(struct file *file, void *fh, - struct v4l2_streamparm *parm) -{ - struct pwc_device *pdev = video_drvdata(file); - - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - memset(parm, 0, sizeof(*parm)); - - parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - parm->parm.capture.readbuffers = MIN_FRAMES; - parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME; - parm->parm.capture.timeperframe.denominator = pdev->vframes; - parm->parm.capture.timeperframe.numerator = 1; - - return 0; -} - -static int pwc_s_parm(struct file *file, void *fh, - struct v4l2_streamparm *parm) -{ - struct pwc_device *pdev = video_drvdata(file); - int compression = 0; - int ret, fps; - - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - /* If timeperframe == 0, then reset the framerate to the nominal value. - We pick a high framerate here, and let pwc_set_video_mode() figure - out the best match. */ - if (parm->parm.capture.timeperframe.numerator == 0 || - parm->parm.capture.timeperframe.denominator == 0) - fps = 30; - else - fps = parm->parm.capture.timeperframe.denominator / - parm->parm.capture.timeperframe.numerator; - - if (vb2_is_busy(&pdev->vb_queue)) - return -EBUSY; - - ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt, - fps, &compression, 0); - - pwc_g_parm(file, fh, parm); - - return ret; -} - -const struct v4l2_ioctl_ops pwc_ioctl_ops = { - .vidioc_querycap = pwc_querycap, - .vidioc_enum_input = pwc_enum_input, - .vidioc_g_input = pwc_g_input, - .vidioc_s_input = pwc_s_input, - .vidioc_enum_fmt_vid_cap = pwc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = pwc_g_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = pwc_s_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = pwc_try_fmt_vid_cap, - .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_streamon = vb2_ioctl_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - .vidioc_log_status = v4l2_ctrl_log_status, - .vidioc_enum_framesizes = pwc_enum_framesizes, - .vidioc_enum_frameintervals = pwc_enum_frameintervals, - .vidioc_g_parm = pwc_g_parm, - .vidioc_s_parm = pwc_s_parm, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h deleted file mode 100644 index 7a6a0d39c2c6..000000000000 --- a/drivers/media/video/pwc/pwc.h +++ /dev/null @@ -1,393 +0,0 @@ -/* (C) 1999-2003 Nemosoft Unv. - (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. - Please send bug reports and support requests to <luc@saillard.org>. - The decompression routines have been implemented by reverse-engineering the - Nemosoft binary pwcx module. Caveat emptor. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef PWC_H -#define PWC_H - -#include <linux/module.h> -#include <linux/usb.h> -#include <linux/spinlock.h> -#include <linux/wait.h> -#include <linux/mutex.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <asm/errno.h> -#include <linux/videodev2.h> -#include <media/v4l2-common.h> -#include <media/v4l2-device.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-fh.h> -#include <media/v4l2-event.h> -#include <media/videobuf2-vmalloc.h> -#ifdef CONFIG_USB_PWC_INPUT_EVDEV -#include <linux/input.h> -#endif -#include "pwc-dec1.h" -#include "pwc-dec23.h" - -/* Version block */ -#define PWC_VERSION "10.0.15" -#define PWC_NAME "pwc" -#define PFX PWC_NAME ": " - - -/* Trace certain actions in the driver */ -#define PWC_DEBUG_LEVEL_MODULE (1<<0) -#define PWC_DEBUG_LEVEL_PROBE (1<<1) -#define PWC_DEBUG_LEVEL_OPEN (1<<2) -#define PWC_DEBUG_LEVEL_READ (1<<3) -#define PWC_DEBUG_LEVEL_MEMORY (1<<4) -#define PWC_DEBUG_LEVEL_FLOW (1<<5) -#define PWC_DEBUG_LEVEL_SIZE (1<<6) -#define PWC_DEBUG_LEVEL_IOCTL (1<<7) -#define PWC_DEBUG_LEVEL_TRACE (1<<8) - -#define PWC_DEBUG_MODULE(fmt, args...) PWC_DEBUG(MODULE, fmt, ##args) -#define PWC_DEBUG_PROBE(fmt, args...) PWC_DEBUG(PROBE, fmt, ##args) -#define PWC_DEBUG_OPEN(fmt, args...) PWC_DEBUG(OPEN, fmt, ##args) -#define PWC_DEBUG_READ(fmt, args...) PWC_DEBUG(READ, fmt, ##args) -#define PWC_DEBUG_MEMORY(fmt, args...) PWC_DEBUG(MEMORY, fmt, ##args) -#define PWC_DEBUG_FLOW(fmt, args...) PWC_DEBUG(FLOW, fmt, ##args) -#define PWC_DEBUG_SIZE(fmt, args...) PWC_DEBUG(SIZE, fmt, ##args) -#define PWC_DEBUG_IOCTL(fmt, args...) PWC_DEBUG(IOCTL, fmt, ##args) -#define PWC_DEBUG_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args) - - -#ifdef CONFIG_USB_PWC_DEBUG - -#define PWC_DEBUG_LEVEL (PWC_DEBUG_LEVEL_MODULE) - -#define PWC_DEBUG(level, fmt, args...) do {\ - if ((PWC_DEBUG_LEVEL_ ##level) & pwc_trace) \ - printk(KERN_DEBUG PFX fmt, ##args); \ - } while (0) - -#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args) -#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args) -#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args) -#define PWC_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args) - -#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) -#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args) -#define PWC_TRACE(fmt, args...) do { } while(0) -#define PWC_DEBUG(level, fmt, args...) do { } while(0) - -#define pwc_trace 0 - -#endif - -/* Defines for ToUCam cameras */ -#define TOUCAM_HEADER_SIZE 8 -#define TOUCAM_TRAILER_SIZE 4 - -#define FEATURE_MOTOR_PANTILT 0x0001 -#define FEATURE_CODEC1 0x0002 -#define FEATURE_CODEC2 0x0004 - -#define MAX_WIDTH 640 -#define MAX_HEIGHT 480 - -/* Ignore errors in the first N frames, to allow for startup delays */ -#define FRAME_LOWMARK 5 - -/* Size and number of buffers for the ISO pipe. */ -#define MAX_ISO_BUFS 3 -#define ISO_FRAMES_PER_DESC 10 -#define ISO_MAX_FRAME_SIZE 960 -#define ISO_BUFFER_SIZE (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE) - -/* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */ -#define PWC_FRAME_SIZE (460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE) - -/* Absolute minimum and maximum number of buffers available for mmap() */ -#define MIN_FRAMES 2 -#define MAX_FRAMES 16 - -/* Some macros to quickly find the type of a webcam */ -#define DEVICE_USE_CODEC1(x) ((x)<675) -#define DEVICE_USE_CODEC2(x) ((x)>=675 && (x)<700) -#define DEVICE_USE_CODEC3(x) ((x)>=700) -#define DEVICE_USE_CODEC23(x) ((x)>=675) - -/* Request types: video */ -#define SET_LUM_CTL 0x01 -#define GET_LUM_CTL 0x02 -#define SET_CHROM_CTL 0x03 -#define GET_CHROM_CTL 0x04 -#define SET_STATUS_CTL 0x05 -#define GET_STATUS_CTL 0x06 -#define SET_EP_STREAM_CTL 0x07 -#define GET_EP_STREAM_CTL 0x08 -#define GET_XX_CTL 0x09 -#define SET_XX_CTL 0x0A -#define GET_XY_CTL 0x0B -#define SET_XY_CTL 0x0C -#define SET_MPT_CTL 0x0D -#define GET_MPT_CTL 0x0E - -/* Selectors for the Luminance controls [GS]ET_LUM_CTL */ -#define AGC_MODE_FORMATTER 0x2000 -#define PRESET_AGC_FORMATTER 0x2100 -#define SHUTTER_MODE_FORMATTER 0x2200 -#define PRESET_SHUTTER_FORMATTER 0x2300 -#define PRESET_CONTOUR_FORMATTER 0x2400 -#define AUTO_CONTOUR_FORMATTER 0x2500 -#define BACK_LIGHT_COMPENSATION_FORMATTER 0x2600 -#define CONTRAST_FORMATTER 0x2700 -#define DYNAMIC_NOISE_CONTROL_FORMATTER 0x2800 -#define FLICKERLESS_MODE_FORMATTER 0x2900 -#define AE_CONTROL_SPEED 0x2A00 -#define BRIGHTNESS_FORMATTER 0x2B00 -#define GAMMA_FORMATTER 0x2C00 - -/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */ -#define WB_MODE_FORMATTER 0x1000 -#define AWB_CONTROL_SPEED_FORMATTER 0x1100 -#define AWB_CONTROL_DELAY_FORMATTER 0x1200 -#define PRESET_MANUAL_RED_GAIN_FORMATTER 0x1300 -#define PRESET_MANUAL_BLUE_GAIN_FORMATTER 0x1400 -#define COLOUR_MODE_FORMATTER 0x1500 -#define SATURATION_MODE_FORMATTER1 0x1600 -#define SATURATION_MODE_FORMATTER2 0x1700 - -/* Selectors for the Status controls [GS]ET_STATUS_CTL */ -#define SAVE_USER_DEFAULTS_FORMATTER 0x0200 -#define RESTORE_USER_DEFAULTS_FORMATTER 0x0300 -#define RESTORE_FACTORY_DEFAULTS_FORMATTER 0x0400 -#define READ_AGC_FORMATTER 0x0500 -#define READ_SHUTTER_FORMATTER 0x0600 -#define READ_RED_GAIN_FORMATTER 0x0700 -#define READ_BLUE_GAIN_FORMATTER 0x0800 - -/* Formatters for the motorized pan & tilt [GS]ET_MPT_CTL */ -#define PT_RELATIVE_CONTROL_FORMATTER 0x01 -#define PT_RESET_CONTROL_FORMATTER 0x02 -#define PT_STATUS_FORMATTER 0x03 - -/* Enumeration of image sizes */ -#define PSZ_SQCIF 0x00 -#define PSZ_QSIF 0x01 -#define PSZ_QCIF 0x02 -#define PSZ_SIF 0x03 -#define PSZ_CIF 0x04 -#define PSZ_VGA 0x05 -#define PSZ_MAX 6 - -struct pwc_raw_frame { - __le16 type; /* type of the webcam */ - __le16 vbandlength; /* Size of 4 lines 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 */ -} __packed; - -/* intermediate buffers with raw data from the USB cam */ -struct pwc_frame_buf -{ - struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */ - struct list_head list; - void *data; - int filled; /* number of bytes filled */ -}; - -struct pwc_device -{ - struct video_device vdev; - struct v4l2_device v4l2_dev; - - /* videobuf2 queue and queued buffers list */ - struct vb2_queue vb_queue; - struct list_head queued_bufs; - spinlock_t queued_bufs_lock; /* Protects queued_bufs */ - - /* Note if taking both locks v4l2_lock must always be locked first! */ - struct mutex v4l2_lock; /* Protects everything else */ - struct mutex vb_queue_lock; /* Protects vb_queue and capt_file */ - - /* Pointer to our usb_device, will be NULL after unplug */ - struct usb_device *udev; /* Both mutexes most be hold when setting! */ - - /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */ - int type; - int release; /* release number */ - int features; /* feature bits */ - - /*** Video data ***/ - int vendpoint; /* video isoc endpoint */ - int vcinterface; /* video control interface */ - int valternate; /* alternate interface needed */ - int vframes; /* frames-per-second */ - int pixfmt; /* pixelformat: V4L2_PIX_FMT_YUV420 or _PWCX */ - int vframe_count; /* received frames */ - int vmax_packet_size; /* USB maxpacket size */ - int vlast_packet_size; /* for frame synchronisation */ - int visoc_errors; /* number of contiguous ISOC errors */ - int vbandlength; /* compressed band length; 0 is uncompressed */ - char vsync; /* used by isoc handler */ - char vmirror; /* for ToUCaM series */ - char power_save; /* Do powersaving for this cam */ - - unsigned char cmd_buf[13]; - unsigned char *ctrl_buf; - - struct urb *urbs[MAX_ISO_BUFS]; - - /* - * Frame currently being filled, this only gets touched by the - * isoc urb complete handler, and by stream start / stop since - * start / stop touch it before / after starting / killing the urbs - * no locking is needed around this - */ - struct pwc_frame_buf *fill_buf; - - int frame_header_size, frame_trailer_size; - int frame_size; - int frame_total_size; /* including header & trailer */ - int drop_frames; - - union { /* private data for decompression engine */ - struct pwc_dec1_private dec1; - struct pwc_dec23_private dec23; - }; - - /* - * We have an 'image' and a 'view', where 'image' is the fixed-size img - * as delivered by the camera, and 'view' is the size requested by the - * program. The camera image is centered in this viewport, laced with - * a gray or black border. view_min <= image <= view <= view_max; - */ - int image_mask; /* supported sizes */ - int width, height; /* current resolution */ - -#ifdef CONFIG_USB_PWC_INPUT_EVDEV - struct input_dev *button_dev; /* webcam snapshot button input */ - char button_phys[64]; -#endif - - /* controls */ - struct v4l2_ctrl_handler ctrl_handler; - u16 saturation_fmt; - struct v4l2_ctrl *brightness; - struct v4l2_ctrl *contrast; - struct v4l2_ctrl *saturation; - struct v4l2_ctrl *gamma; - struct { - /* awb / red-blue balance cluster */ - struct v4l2_ctrl *auto_white_balance; - struct v4l2_ctrl *red_balance; - struct v4l2_ctrl *blue_balance; - /* usb ctrl transfers are slow, so we cache things */ - int color_bal_valid; - unsigned long last_color_bal_update; /* In jiffies */ - s32 last_red_balance; - s32 last_blue_balance; - }; - struct { - /* autogain / gain cluster */ - struct v4l2_ctrl *autogain; - struct v4l2_ctrl *gain; - int gain_valid; - unsigned long last_gain_update; /* In jiffies */ - s32 last_gain; - }; - struct { - /* exposure_auto / exposure cluster */ - struct v4l2_ctrl *exposure_auto; - struct v4l2_ctrl *exposure; - int exposure_valid; - unsigned long last_exposure_update; /* In jiffies */ - s32 last_exposure; - }; - struct v4l2_ctrl *colorfx; - struct { - /* autocontour/contour cluster */ - struct v4l2_ctrl *autocontour; - struct v4l2_ctrl *contour; - }; - struct v4l2_ctrl *backlight; - struct v4l2_ctrl *flicker; - struct v4l2_ctrl *noise_reduction; - struct v4l2_ctrl *save_user; - struct v4l2_ctrl *restore_user; - struct v4l2_ctrl *restore_factory; - struct v4l2_ctrl *awb_speed; - struct v4l2_ctrl *awb_delay; - struct { - /* motor control cluster */ - struct v4l2_ctrl *motor_pan; - struct v4l2_ctrl *motor_tilt; - struct v4l2_ctrl *motor_pan_reset; - struct v4l2_ctrl *motor_tilt_reset; - }; - /* CODEC3 models have both gain and exposure controlled by autogain */ - struct v4l2_ctrl *autogain_expo_cluster[3]; -}; - -/* Global variables */ -#ifdef CONFIG_USB_PWC_DEBUG -extern int pwc_trace; -#endif - -/** Functions in pwc-misc.c */ -/* sizes in pixels */ -extern const int pwc_image_sizes[PSZ_MAX][2]; - -int pwc_get_size(struct pwc_device *pdev, int width, int height); -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 pixfmt, int frames, int *compression, int send_to_cam); -extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size); -extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value); -extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor); -extern int send_control_msg(struct pwc_device *pdev, - u8 request, u16 value, void *buf, int buflen); - -/* Control get / set helpers */ -int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data); -int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data); -int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data); -#define pwc_set_s8_ctrl pwc_set_u8_ctrl -int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *dat); -int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data); -int pwc_button_ctrl(struct pwc_device *pdev, u16 value); -int pwc_init_controls(struct pwc_device *pdev); - -/* Power down or up the camera; not supported by all models */ -extern void pwc_camera_power(struct pwc_device *pdev, int power); - -extern const struct v4l2_ioctl_ops pwc_ioctl_ops; - -/** pwc-uncompress.c */ -/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */ -int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf); - -#endif diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/video/sn9c102/Kconfig deleted file mode 100644 index 6ebaf2940d06..000000000000 --- a/drivers/media/video/sn9c102/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -config USB_SN9C102 - tristate "USB SN9C1xx PC Camera Controller support (DEPRECATED)" - depends on VIDEO_V4L2 - ---help--- - This driver is DEPRECATED please use the gspca sonixb and - sonixj modules instead. - - Say Y here if you want support for cameras based on SONiX SN9C101, - SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers. - - See <file:Documentation/video4linux/sn9c102.txt> for more info. - - To compile this driver as a module, choose M here: the - module will be called sn9c102. diff --git a/drivers/media/video/sn9c102/Makefile b/drivers/media/video/sn9c102/Makefile deleted file mode 100644 index 7ecd5a90c7c9..000000000000 --- a/drivers/media/video/sn9c102/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -sn9c102-objs := sn9c102_core.o \ - sn9c102_hv7131d.o \ - sn9c102_hv7131r.o \ - sn9c102_mi0343.o \ - sn9c102_mi0360.o \ - sn9c102_mt9v111.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/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h deleted file mode 100644 index 2bc153e869be..000000000000 --- a/drivers/media/video/sn9c102/sn9c102.h +++ /dev/null @@ -1,211 +0,0 @@ -/*************************************************************************** - * V4L2 driver for SN9C1xx PC Camera Controllers * - * * - * Copyright (C) 2004-2006 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. * - ***************************************************************************/ - -#ifndef _SN9C102_H_ -#define _SN9C102_H_ - -#include <linux/usb.h> -#include <linux/videodev2.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <linux/device.h> -#include <linux/list.h> -#include <linux/spinlock.h> -#include <linux/time.h> -#include <linux/wait.h> -#include <linux/types.h> -#include <linux/param.h> -#include <linux/rwsem.h> -#include <linux/mutex.h> -#include <linux/string.h> -#include <linux/stddef.h> -#include <linux/kref.h> - -#include "sn9c102_config.h" -#include "sn9c102_sensor.h" -#include "sn9c102_devtable.h" - - -enum sn9c102_frame_state { - F_UNUSED, - F_QUEUED, - F_GRABBING, - F_DONE, - F_ERROR, -}; - -struct sn9c102_frame_t { - void* bufmem; - struct v4l2_buffer buf; - enum sn9c102_frame_state state; - struct list_head frame; - unsigned long vma_use_count; -}; - -enum sn9c102_dev_state { - DEV_INITIALIZED = 0x01, - DEV_DISCONNECTED = 0x02, - DEV_MISCONFIGURED = 0x04, -}; - -enum sn9c102_io_method { - IO_NONE, - IO_READ, - IO_MMAP, -}; - -enum sn9c102_stream_state { - STREAM_OFF, - STREAM_INTERRUPT, - STREAM_ON, -}; - -typedef char sn9c102_sof_header_t[62]; - -struct sn9c102_sof_t { - sn9c102_sof_header_t header; - u16 bytesread; -}; - -struct sn9c102_sysfs_attr { - u16 reg, i2c_reg; - sn9c102_sof_header_t frame_header; -}; - -struct sn9c102_module_param { - u8 force_munmap; - u16 frame_timeout; -}; - -static DEFINE_MUTEX(sn9c102_sysfs_lock); -static DECLARE_RWSEM(sn9c102_dev_lock); - -struct sn9c102_device { - struct video_device* v4ldev; - - enum sn9c102_bridge bridge; - struct sn9c102_sensor sensor; - - struct usb_device* usbdev; - struct urb* urb[SN9C102_URBS]; - void* transfer_buffer[SN9C102_URBS]; - u8* control_buffer; - - struct sn9c102_frame_t *frame_current, frame[SN9C102_MAX_FRAMES]; - struct list_head inqueue, outqueue; - u32 frame_count, nbuffers, nreadbuffers; - - enum sn9c102_io_method io; - enum sn9c102_stream_state stream; - - struct v4l2_jpegcompression compression; - - struct sn9c102_sysfs_attr sysfs; - struct sn9c102_sof_t sof; - u16 reg[384]; - - struct sn9c102_module_param module_param; - - struct kref kref; - enum sn9c102_dev_state state; - u8 users; - - struct completion probe; - struct mutex open_mutex, fileop_mutex; - spinlock_t queue_lock; - wait_queue_head_t wait_open, wait_frame, wait_stream; -}; - -/*****************************************************************************/ - -struct sn9c102_device* -sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id) -{ - return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL; -} - - -void -sn9c102_attach_sensor(struct sn9c102_device* cam, - const struct sn9c102_sensor* sensor) -{ - memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor)); -} - - -enum sn9c102_bridge -sn9c102_get_bridge(struct sn9c102_device* cam) -{ - return cam->bridge; -} - - -struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam) -{ - return &cam->sensor; -} - -/*****************************************************************************/ - -#undef DBG -#undef KDBG -#ifdef SN9C102_DEBUG -# define DBG(level, fmt, args...) \ -do { \ - if (debug >= (level)) { \ - if ((level) == 1) \ - dev_err(&cam->usbdev->dev, fmt "\n", ## args); \ - else if ((level) == 2) \ - dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ - else if ((level) >= 3) \ - dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ - __func__, __LINE__ , ## args); \ - } \ -} while (0) -# define V4LDBG(level, name, cmd) \ -do { \ - if (debug >= (level)) \ - v4l_printk_ioctl(name, cmd); \ -} while (0) -# define KDBG(level, fmt, args...) \ -do { \ - if (debug >= (level)) { \ - if ((level) == 1 || (level) == 2) \ - pr_info("sn9c102: " fmt "\n", ## args); \ - else if ((level) == 3) \ - pr_debug("sn9c102: [%s:%d] " fmt "\n", \ - __func__, __LINE__ , ## args); \ - } \ -} while (0) -#else -# define DBG(level, fmt, args...) do {;} while(0) -# define V4LDBG(level, name, cmd) do {;} while(0) -# define KDBG(level, fmt, args...) do {;} while(0) -#endif - -#undef PDBG -#define PDBG(fmt, args...) \ -dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__, \ - __LINE__ , ## args) - -#undef PDBGG -#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ - -#endif /* _SN9C102_H_ */ diff --git a/drivers/media/video/sn9c102/sn9c102_config.h b/drivers/media/video/sn9c102/sn9c102_config.h deleted file mode 100644 index 0f4e0378b071..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_config.h +++ /dev/null @@ -1,86 +0,0 @@ -/*************************************************************************** - * Global parameters for the V4L2 driver for 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. * - ***************************************************************************/ - -#ifndef _SN9C102_CONFIG_H_ -#define _SN9C102_CONFIG_H_ - -#include <linux/types.h> -#include <linux/jiffies.h> - -#define SN9C102_DEBUG -#define SN9C102_DEBUG_LEVEL 2 -#define SN9C102_MAX_DEVICES 64 -#define SN9C102_PRESERVE_IMGSCALE 0 -#define SN9C102_FORCE_MUNMAP 0 -#define SN9C102_MAX_FRAMES 32 -#define SN9C102_URBS 2 -#define SN9C102_ISO_PACKETS 7 -#define SN9C102_ALTERNATE_SETTING 8 -#define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS) -#define SN9C102_CTRL_TIMEOUT 300 -#define SN9C102_FRAME_TIMEOUT 0 - -/*****************************************************************************/ - -static const u8 SN9C102_Y_QTABLE0[64] = { - 8, 5, 5, 8, 12, 20, 25, 30, - 6, 6, 7, 9, 13, 29, 30, 27, - 7, 6, 8, 12, 20, 28, 34, 28, - 7, 8, 11, 14, 25, 43, 40, 31, - 9, 11, 18, 28, 34, 54, 51, 38, - 12, 17, 27, 32, 40, 52, 56, 46, - 24, 32, 39, 43, 51, 60, 60, 50, - 36, 46, 47, 49, 56, 50, 51, 49 -}; - -static const u8 SN9C102_UV_QTABLE0[64] = { - 8, 9, 12, 23, 49, 49, 49, 49, - 9, 10, 13, 33, 49, 49, 49, 49, - 12, 13, 28, 49, 49, 49, 49, 49, - 23, 33, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49 -}; - -static const u8 SN9C102_Y_QTABLE1[64] = { - 16, 11, 10, 16, 24, 40, 51, 61, - 12, 12, 14, 19, 26, 58, 60, 55, - 14, 13, 16, 24, 40, 57, 69, 56, - 14, 17, 22, 29, 51, 87, 80, 62, - 18, 22, 37, 56, 68, 109, 103, 77, - 24, 35, 55, 64, 81, 104, 113, 92, - 49, 64, 78, 87, 103, 121, 120, 101, - 72, 92, 95, 98, 112, 100, 103, 99 -}; - -static const u8 SN9C102_UV_QTABLE1[64] = { - 17, 18, 24, 47, 99, 99, 99, 99, - 18, 21, 26, 66, 99, 99, 99, 99, - 24, 26, 56, 99, 99, 99, 99, 99, - 47, 66, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99 -}; - -#endif /* _SN9C102_CONFIG_H_ */ diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c deleted file mode 100644 index 19ea780b16ff..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ /dev/null @@ -1,3421 +0,0 @@ -/*************************************************************************** - * V4L2 driver for SN9C1xx PC Camera Controllers * - * * - * Copyright (C) 2004-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 <linux/module.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/param.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/device.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <linux/compiler.h> -#include <linux/ioctl.h> -#include <linux/poll.h> -#include <linux/stat.h> -#include <linux/mm.h> -#include <linux/vmalloc.h> -#include <linux/version.h> -#include <linux/page-flags.h> -#include <asm/byteorder.h> -#include <asm/page.h> -#include <asm/uaccess.h> - -#include "sn9c102.h" - -/*****************************************************************************/ - -#define SN9C102_MODULE_NAME "V4L2 driver for SN9C1xx PC Camera Controllers" -#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.48" - -/*****************************************************************************/ - -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); - -static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1}; -module_param_array(video_nr, short, NULL, 0444); -MODULE_PARM_DESC(video_nr, - " <-1|n[,...]>" - "\nSpecify V4L2 minor mode number." - "\n-1 = use next available (default)" - "\n n = use minor number n (integer >= 0)" - "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES) - " cameras this way." - "\nFor example:" - "\nvideo_nr=-1,2,-1 would assign minor number 2 to" - "\nthe second camera and use auto for the first" - "\none and for every other camera." - "\n"); - -static bool force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] = - SN9C102_FORCE_MUNMAP}; -module_param_array(force_munmap, bool, NULL, 0444); -MODULE_PARM_DESC(force_munmap, - " <0|1[,...]>" - "\nForce the application to unmap previously" - "\nmapped buffer memory before calling any VIDIOC_S_CROP or" - "\nVIDIOC_S_FMT ioctl's. Not all the applications support" - "\nthis feature. This parameter is specific for each" - "\ndetected camera." - "\n0 = do not force memory unmapping" - "\n1 = force memory unmapping (save memory)" - "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." - "\n"); - -static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] = - SN9C102_FRAME_TIMEOUT}; -module_param_array(frame_timeout, uint, NULL, 0644); -MODULE_PARM_DESC(frame_timeout, - " <0|n[,...]>" - "\nTimeout for a video frame in seconds before" - "\nreturning an I/O error; 0 for infinity." - "\nThis parameter is specific for each detected camera." - "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"." - "\n"); - -#ifdef SN9C102_DEBUG -static unsigned short debug = SN9C102_DEBUG_LEVEL; -module_param(debug, ushort, 0644); -MODULE_PARM_DESC(debug, - " <n>" - "\nDebugging information level, from 0 to 3:" - "\n0 = none (use carefully)" - "\n1 = critical errors" - "\n2 = significant informations" - "\n3 = more verbose messages" - "\nLevel 3 is useful for testing only." - "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"." - "\n"); -#endif - -/* - Add the probe entries to this table. Be sure to add the entry in the right - place, since, on failure, the next probing routine is called according to - 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_mt9v111, /* 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_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 */ -}; - -/*****************************************************************************/ - -static u32 -sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, - enum sn9c102_io_method io) -{ - 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; - void* buff = NULL; - u32 i; - - if (count > SN9C102_MAX_FRAMES) - count = SN9C102_MAX_FRAMES; - - if (cam->bridge == BRIDGE_SN9C105 || cam->bridge == BRIDGE_SN9C120) - imagesize += 589 + 2; /* length of JPEG header + EOI marker */ - - cam->nbuffers = count; - while (cam->nbuffers > 0) { - if ((buff = vmalloc_32_user(cam->nbuffers * - PAGE_ALIGN(imagesize)))) - break; - cam->nbuffers--; - } - - for (i = 0; i < cam->nbuffers; i++) { - cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize); - cam->frame[i].buf.index = i; - cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize); - cam->frame[i].buf.length = imagesize; - cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - cam->frame[i].buf.sequence = 0; - cam->frame[i].buf.field = V4L2_FIELD_NONE; - cam->frame[i].buf.memory = V4L2_MEMORY_MMAP; - cam->frame[i].buf.flags = 0; - } - - return cam->nbuffers; -} - - -static void sn9c102_release_buffers(struct sn9c102_device* cam) -{ - if (cam->nbuffers) { - vfree(cam->frame[0].bufmem); - cam->nbuffers = 0; - } - cam->frame_current = NULL; -} - - -static void sn9c102_empty_framequeues(struct sn9c102_device* cam) -{ - u32 i; - - INIT_LIST_HEAD(&cam->inqueue); - INIT_LIST_HEAD(&cam->outqueue); - - for (i = 0; i < SN9C102_MAX_FRAMES; i++) { - cam->frame[i].state = F_UNUSED; - cam->frame[i].buf.bytesused = 0; - } -} - - -static void sn9c102_requeue_outqueue(struct sn9c102_device* cam) -{ - struct sn9c102_frame_t *i; - - list_for_each_entry(i, &cam->outqueue, frame) { - i->state = F_QUEUED; - list_add(&i->frame, &cam->inqueue); - } - - INIT_LIST_HEAD(&cam->outqueue); -} - - -static void sn9c102_queue_unusedframes(struct sn9c102_device* cam) -{ - unsigned long lock_flags; - u32 i; - - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].state == F_UNUSED) { - cam->frame[i].state = F_QUEUED; - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_add_tail(&cam->frame[i].frame, &cam->inqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - } -} - -/*****************************************************************************/ - -/* - 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; - - for (i = 0; i < count; i++) { - u8 index = valreg[i][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; - } - - cam->reg[index] = *buff; - } - - return 0; -} - - -int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index) -{ - struct usb_device* udev = cam->usbdev; - u8* buff = cam->control_buffer; - int res; - - if (index >= ARRAY_SIZE(cam->reg)) - return -1; - - *buff = value; - - 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)", value, index, res); - return -1; - } - - cam->reg[index] = value; - - return 0; -} - - -/* 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; - int res; - - res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, - index, 0, buff, 1, SN9C102_CTRL_TIMEOUT); - if (res < 0) - DBG(3, "Failed to read a register (index 0x%02X, error %d)", - index, res); - - return (res >= 0) ? (int)(*buff) : -1; -} - - -int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index) -{ - if (index >= ARRAY_SIZE(cam->reg)) - return -1; - - return cam->reg[index]; -} - - -static int -sn9c102_i2c_wait(struct sn9c102_device* cam, - const struct sn9c102_sensor* sensor) -{ - int i, r; - - for (i = 1; i <= 5; i++) { - r = sn9c102_read_reg(cam, 0x08); - if (r < 0) - return -EIO; - if (r & 0x04) - return 0; - if (sensor->frequency & SN9C102_I2C_400KHZ) - udelay(5*16); - else - udelay(16*16); - } - return -EBUSY; -} - - -static int -sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, - const struct sn9c102_sensor* sensor) -{ - int r , err = 0; - - r = sn9c102_read_reg(cam, 0x08); - if (r < 0) - err += r; - - if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { - if (!(r & 0x08)) - err += -1; - } else { - if (r & 0x08) - err += -1; - } - - return err ? -EIO : 0; -} - - -static int -sn9c102_i2c_detect_write_error(struct sn9c102_device* cam, - const struct sn9c102_sensor* sensor) -{ - int r; - r = sn9c102_read_reg(cam, 0x08); - return (r < 0 || (r >= 0 && (r & 0x08))) ? -EIO : 0; -} - - -int -sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, - 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 i = 0, err = 0, res; - - /* Write cycle */ - data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | - ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10; - data[1] = data0; /* I2C slave id */ - data[2] = data1; /* address */ - data[7] = 0x10; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += sn9c102_i2c_wait(cam, sensor); - - /* Read cycle - n bytes */ - data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | - ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | - (n << 4) | 0x02; - data[1] = data0; - data[7] = 0x10; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += sn9c102_i2c_wait(cam, sensor); - - /* The first read byte will be placed in data[4] */ - res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1, - 0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += sn9c102_i2c_detect_read_error(cam, sensor); - - PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1, - data[4]); - - if (err) { - DBG(3, "I2C read failed for %s image sensor", sensor->name); - return -1; - } - - if (buffer) - for (i = 0; i < n && i < 5; i++) - buffer[n-i-1] = data[4-i]; - - return (int)data[4]; -} - - -int -sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, - 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; - u8* data = cam->control_buffer; - int err = 0, res; - - /* Write cycle. It usually is address + value */ - data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | - ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) - | ((n - 1) << 4); - data[1] = data0; - data[2] = data1; - data[3] = data2; - data[4] = data3; - data[5] = data4; - data[6] = data5; - data[7] = 0x17; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, - 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); - if (res < 0) - err += res; - - err += sn9c102_i2c_wait(cam, sensor); - err += sn9c102_i2c_detect_write_error(cam, sensor); - - if (err) - DBG(3, "I2C write failed for %s image sensor", sensor->name); - - PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, " - "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X", - n, data0, data1, data2, data3, data4, data5); - - return err ? -1 : 0; -} - - -int -sn9c102_i2c_try_read(struct sn9c102_device* cam, - const struct sn9c102_sensor* sensor, u8 address) -{ - return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id, - address, 1, NULL); -} - - -static int sn9c102_i2c_try_write(struct sn9c102_device* cam, - const struct sn9c102_sensor* sensor, - u8 address, u8 value) -{ - return sn9c102_i2c_try_raw_write(cam, sensor, 3, - sensor->i2c_slave_id, address, - value, 0, 0, 0); -} - - -int sn9c102_i2c_read(struct sn9c102_device* cam, u8 address) -{ - return sn9c102_i2c_try_read(cam, &cam->sensor, address); -} - - -int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value) -{ - return sn9c102_i2c_try_write(cam, &cam->sensor, address, value); -} - -/*****************************************************************************/ - -static size_t sn9c102_sof_length(struct sn9c102_device* cam) -{ - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - return 12; - case BRIDGE_SN9C103: - return 18; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - return 62; - } - - return 0; -} - - -static void* -sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) -{ - 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; 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; -} - - -static void* -sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len) -{ - static const u8 eof_header[4][4] = { - {0x00, 0x00, 0x00, 0x00}, - {0x40, 0x00, 0x00, 0x00}, - {0x80, 0x00, 0x00, 0x00}, - {0xc0, 0x00, 0x00, 0x00}, - }; - 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; - - /* - 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)) - return mem + i; - - return NULL; -} - - -static void -sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f) -{ - 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, - 0x0f, 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, 0x16, - 0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, 0x23, 0x1c, 0x16, - 0x16, 0x20, 0x2c, 0x20, 0x23, 0x26, 0x27, 0x29, 0x2a, 0x29, - 0x19, 0x1f, 0x2d, 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29, - 0x28, 0x01, 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a, - 0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0xff, 0xc4, 0x01, 0xa2, - 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, - 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01, - 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, - 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, - 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04, - 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, - 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, - 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, - 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, - 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, - 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, - 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, - 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, - 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, - 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, - 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, - 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, - 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, - 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, - 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02, - 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, - 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, - 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, - 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, - 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, - 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, - 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, - 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, - 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, - 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, - 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, - 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, - 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, - 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, - 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc0, 0x00, 0x11, - 0x08, 0x01, 0xe0, 0x02, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, - 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03, - 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 - }; - u8 *pos = f->bufmem; - - memcpy(pos, jpeg_header, sizeof(jpeg_header)); - *(pos + 6) = 0x00; - *(pos + 7 + 64) = 0x01; - if (cam->compression.quality == 0) { - memcpy(pos + 7, SN9C102_Y_QTABLE0, 64); - memcpy(pos + 8 + 64, SN9C102_UV_QTABLE0, 64); - } else if (cam->compression.quality == 1) { - memcpy(pos + 7, SN9C102_Y_QTABLE1, 64); - memcpy(pos + 8 + 64, SN9C102_UV_QTABLE1, 64); - } - *(pos + 564) = cam->sensor.pix_format.width & 0xFF; - *(pos + 563) = (cam->sensor.pix_format.width >> 8) & 0xFF; - *(pos + 562) = cam->sensor.pix_format.height & 0xFF; - *(pos + 561) = (cam->sensor.pix_format.height >> 8) & 0xFF; - *(pos + 567) = 0x21; - - f->buf.bytesused += sizeof(jpeg_header); -} - - -static void sn9c102_urb_complete(struct urb *urb) -{ - struct sn9c102_device* cam = urb->context; - struct sn9c102_frame_t** f; - size_t imagesize, soflen; - u8 i; - int err = 0; - - if (urb->status == -ENOENT) - return; - - f = &cam->frame_current; - - if (cam->stream == STREAM_INTERRUPT) { - 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); - } - - if (cam->state & DEV_DISCONNECTED) - return; - - if (cam->state & DEV_MISCONFIGURED) { - wake_up_interruptible(&cam->wait_frame); - return; - } - - if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue)) - goto resubmit_urb; - - if (!(*f)) - (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t, - frame); - - imagesize = (cam->sensor.pix_format.width * - cam->sensor.pix_format.height * - cam->sensor.pix_format.priv) / 8; - if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG) - imagesize += 589; /* length of jpeg header */ - soflen = sn9c102_sof_length(cam); - - for (i = 0; i < urb->number_of_packets; i++) { - unsigned int img, len, status; - void *pos, *sof, *eof; - - len = urb->iso_frame_desc[i].actual_length; - status = urb->iso_frame_desc[i].status; - pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; - - if (status) { - DBG(3, "Error in isochronous frame"); - (*f)->state = F_ERROR; - cam->sof.bytesread = 0; - continue; - } - - PDBGG("Isochrnous frame: length %u, #%u i", len, i); - -redo: - sof = sn9c102_find_sof_header(cam, pos, len); - if (likely(!sof)) { - eof = sn9c102_find_eof_header(cam, pos, len); - if ((*f)->state == F_GRABBING) { -end_of_frame: - img = len; - - if (eof) - img = (eof > pos) ? eof - pos - 1 : 0; - - if ((*f)->buf.bytesused + img > imagesize) { - u32 b; - b = (*f)->buf.bytesused + img - - imagesize; - img = imagesize - (*f)->buf.bytesused; - PDBGG("Expected EOF not found: video " - "frame cut"); - if (eof) - DBG(3, "Exceeded limit: +%u " - "bytes", (unsigned)(b)); - } - - memcpy((*f)->bufmem + (*f)->buf.bytesused, pos, - img); - - if ((*f)->buf.bytesused == 0) - do_gettimeofday(&(*f)->buf.timestamp); - - (*f)->buf.bytesused += img; - - if ((*f)->buf.bytesused == imagesize || - ((cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_SN9C10X || - cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_JPEG) && eof)) { - u32 b; - - b = (*f)->buf.bytesused; - (*f)->state = F_DONE; - (*f)->buf.sequence= ++cam->frame_count; - - spin_lock(&cam->queue_lock); - list_move_tail(&(*f)->frame, - &cam->outqueue); - if (!list_empty(&cam->inqueue)) - (*f) = list_entry( - cam->inqueue.next, - struct sn9c102_frame_t, - frame ); - else - (*f) = NULL; - spin_unlock(&cam->queue_lock); - - memcpy(cam->sysfs.frame_header, - cam->sof.header, soflen); - - DBG(3, "Video frame captured: %lu " - "bytes", (unsigned long)(b)); - - if (!(*f)) - goto resubmit_urb; - - } else if (eof) { - (*f)->state = F_ERROR; - DBG(3, "Not expected EOF after %lu " - "bytes of image data", - (unsigned long) - ((*f)->buf.bytesused)); - } - - if (sof) /* (1) */ - goto start_of_frame; - - } else if (eof) { - DBG(3, "EOF without SOF"); - continue; - - } else { - PDBGG("Ignoring pointless isochronous frame"); - continue; - } - - } else if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) { -start_of_frame: - (*f)->state = F_GRABBING; - (*f)->buf.bytesused = 0; - len -= (sof - pos); - pos = sof; - if (cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_JPEG) - sn9c102_write_jpegheader(cam, (*f)); - DBG(3, "SOF detected: new video frame"); - if (len) - goto redo; - - } else if ((*f)->state == F_GRABBING) { - eof = sn9c102_find_eof_header(cam, pos, len); - if (eof && eof < sof) - goto end_of_frame; /* (1) */ - else { - if (cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_SN9C10X || - cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_JPEG) { - 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 " - "%lu bytes of image data", - (unsigned long) - ((*f)->buf.bytesused)); - goto start_of_frame; - } - } - } - } - -resubmit_urb: - urb->dev = cam->usbdev; - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err < 0 && err != -EPERM) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "usb_submit_urb() failed"); - } - - wake_up_interruptible(&cam->wait_frame); -} - - -static int sn9c102_start_transfer(struct sn9c102_device* cam) -{ - struct usb_device *udev = cam->usbdev; - struct urb* urb; - struct usb_host_interface* altsetting = usb_altnum_to_altsetting( - usb_ifnum_to_if(udev, 0), - SN9C102_ALTERNATE_SETTING); - const unsigned int psz = le16_to_cpu(altsetting-> - endpoint[0].desc.wMaxPacketSize); - s8 i, j; - int err = 0; - - for (i = 0; i < SN9C102_URBS; i++) { - cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz, - GFP_KERNEL); - if (!cam->transfer_buffer[i]) { - err = -ENOMEM; - DBG(1, "Not enough memory"); - goto free_buffers; - } - } - - for (i = 0; i < SN9C102_URBS; i++) { - urb = usb_alloc_urb(SN9C102_ISO_PACKETS, GFP_KERNEL); - cam->urb[i] = urb; - if (!urb) { - err = -ENOMEM; - DBG(1, "usb_alloc_urb() failed"); - goto free_urbs; - } - urb->dev = udev; - urb->context = cam; - urb->pipe = usb_rcvisocpipe(udev, 1); - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = SN9C102_ISO_PACKETS; - urb->complete = sn9c102_urb_complete; - urb->transfer_buffer = cam->transfer_buffer[i]; - urb->transfer_buffer_length = psz * SN9C102_ISO_PACKETS; - urb->interval = 1; - for (j = 0; j < SN9C102_ISO_PACKETS; j++) { - urb->iso_frame_desc[j].offset = psz * j; - urb->iso_frame_desc[j].length = psz; - } - } - - /* Enable video */ - if (!(cam->reg[0x01] & 0x04)) { - err = sn9c102_write_reg(cam, cam->reg[0x01] | 0x04, 0x01); - if (err) { - err = -EIO; - DBG(1, "I/O hardware error"); - goto free_urbs; - } - } - - err = usb_set_interface(udev, 0, SN9C102_ALTERNATE_SETTING); - if (err) { - DBG(1, "usb_set_interface() failed"); - goto free_urbs; - } - - cam->frame_current = NULL; - cam->sof.bytesread = 0; - - for (i = 0; i < SN9C102_URBS; i++) { - err = usb_submit_urb(cam->urb[i], GFP_KERNEL); - if (err) { - for (j = i-1; j >= 0; j--) - usb_kill_urb(cam->urb[j]); - DBG(1, "usb_submit_urb() failed, error %d", err); - goto free_urbs; - } - } - - return 0; - -free_urbs: - for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++) - usb_free_urb(cam->urb[i]); - -free_buffers: - for (i = 0; (i < SN9C102_URBS) && cam->transfer_buffer[i]; i++) - kfree(cam->transfer_buffer[i]); - - return err; -} - - -static int sn9c102_stop_transfer(struct sn9c102_device* cam) -{ - struct usb_device *udev = cam->usbdev; - s8 i; - int err = 0; - - if (cam->state & DEV_DISCONNECTED) - return 0; - - for (i = SN9C102_URBS-1; i >= 0; i--) { - usb_kill_urb(cam->urb[i]); - usb_free_urb(cam->urb[i]); - kfree(cam->transfer_buffer[i]); - } - - err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */ - if (err) - DBG(3, "usb_set_interface() failed"); - - return err; -} - - -static int sn9c102_stream_interrupt(struct sn9c102_device* cam) -{ - cam->stream = STREAM_INTERRUPT; - wait_event_timeout(cam->wait_stream, - (cam->stream == STREAM_OFF) || - (cam->state & DEV_DISCONNECTED), - SN9C102_URB_TIMEOUT); - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - else if (cam->stream != STREAM_OFF) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "URB timeout reached. The camera is misconfigured. " - "To use it, close and open %s again.", - video_device_node_name(cam->v4ldev)); - return -EIO; - } - - return 0; -} - -/*****************************************************************************/ - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count) -{ - char str[7]; - char* endp; - unsigned long val; - - if (len < 6) { - strncpy(str, buff, len); - str[len] = '\0'; - } else { - strncpy(str, buff, 6); - str[6] = '\0'; - } - - val = simple_strtoul(str, &endp, 0); - - *count = 0; - if (val <= 0xffff) - *count = (ssize_t)(endp - str); - if ((*count) && (len == *count+1) && (buff[*count] == '\n')) - *count += 1; - - return (u16)val; -} - -/* - NOTE 1: being inside one of the following methods implies that the v4l - device exists for sure (see kobjects and reference counters) - NOTE 2: buffers are PAGE_SIZE long -*/ - -static ssize_t sn9c102_show_reg(struct device* cd, - struct device_attribute *attr, char* buf) -{ - struct sn9c102_device* cam; - ssize_t count; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - count = sprintf(buf, "%u\n", cam->sysfs.reg); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t -sn9c102_store_reg(struct device* cd, struct device_attribute *attr, - const char* buf, size_t len) -{ - struct sn9c102_device* cam; - u16 index; - ssize_t count; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - index = sn9c102_strtou16(buf, len, &count); - if (index >= ARRAY_SIZE(cam->reg) || !count) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EINVAL; - } - - cam->sysfs.reg = index; - - DBG(2, "Moved SN9C1XX register index to 0x%02X", cam->sysfs.reg); - DBG(3, "Written bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t sn9c102_show_val(struct device* cd, - struct device_attribute *attr, char* buf) -{ - struct sn9c102_device* cam; - ssize_t count; - int val; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - if ((val = sn9c102_read_reg(cam, cam->sysfs.reg)) < 0) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EIO; - } - - count = sprintf(buf, "%d\n", val); - - DBG(3, "Read bytes: %zd, value: %d", count, val); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t -sn9c102_store_val(struct device* cd, struct device_attribute *attr, - const char* buf, size_t len) -{ - struct sn9c102_device* cam; - u16 value; - ssize_t count; - int err; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - value = sn9c102_strtou16(buf, len, &count); - if (!count) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EINVAL; - } - - err = sn9c102_write_reg(cam, value, cam->sysfs.reg); - if (err) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EIO; - } - - DBG(2, "Written SN9C1XX reg. 0x%02X, val. 0x%02X", - cam->sysfs.reg, value); - DBG(3, "Written bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t sn9c102_show_i2c_reg(struct device* cd, - struct device_attribute *attr, char* buf) -{ - struct sn9c102_device* cam; - ssize_t count; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg); - - DBG(3, "Read bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t -sn9c102_store_i2c_reg(struct device* cd, struct device_attribute *attr, - const char* buf, size_t len) -{ - struct sn9c102_device* cam; - u16 index; - ssize_t count; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - index = sn9c102_strtou16(buf, len, &count); - if (!count) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EINVAL; - } - - cam->sysfs.i2c_reg = index; - - DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg); - DBG(3, "Written bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t sn9c102_show_i2c_val(struct device* cd, - struct device_attribute *attr, char* buf) -{ - struct sn9c102_device* cam; - ssize_t count; - int val; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENOSYS; - } - - if ((val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EIO; - } - - count = sprintf(buf, "%d\n", val); - - DBG(3, "Read bytes: %zd, value: %d", count, val); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t -sn9c102_store_i2c_val(struct device* cd, struct device_attribute *attr, - const char* buf, size_t len) -{ - struct sn9c102_device* cam; - u16 value; - ssize_t count; - int err; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENOSYS; - } - - value = sn9c102_strtou16(buf, len, &count); - if (!count) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EINVAL; - } - - err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value); - if (err) { - mutex_unlock(&sn9c102_sysfs_lock); - return -EIO; - } - - DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X", - cam->sysfs.i2c_reg, value); - DBG(3, "Written bytes: %zd", count); - - mutex_unlock(&sn9c102_sysfs_lock); - - return count; -} - - -static ssize_t -sn9c102_store_green(struct device* cd, struct device_attribute *attr, - const char* buf, size_t len) -{ - struct sn9c102_device* cam; - enum sn9c102_bridge bridge; - ssize_t res = 0; - u16 value; - ssize_t count; - - if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - bridge = cam->bridge; - - mutex_unlock(&sn9c102_sysfs_lock); - - value = sn9c102_strtou16(buf, len, &count); - if (!count) - return -EINVAL; - - switch (bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - if (value > 0x0f) - return -EINVAL; - if ((res = sn9c102_store_reg(cd, attr, "0x11", 4)) >= 0) - res = sn9c102_store_val(cd, attr, buf, len); - break; - case BRIDGE_SN9C103: - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - if (value > 0x7f) - return -EINVAL; - if ((res = sn9c102_store_reg(cd, attr, "0x07", 4)) >= 0) - res = sn9c102_store_val(cd, attr, buf, len); - break; - } - - return res; -} - - -static ssize_t -sn9c102_store_blue(struct device* cd, struct device_attribute *attr, - const char* buf, size_t len) -{ - ssize_t res = 0; - u16 value; - ssize_t count; - - value = sn9c102_strtou16(buf, len, &count); - if (!count || value > 0x7f) - return -EINVAL; - - if ((res = sn9c102_store_reg(cd, attr, "0x06", 4)) >= 0) - res = sn9c102_store_val(cd, attr, buf, len); - - return res; -} - - -static ssize_t -sn9c102_store_red(struct device* cd, struct device_attribute *attr, - const char* buf, size_t len) -{ - ssize_t res = 0; - u16 value; - ssize_t count; - - value = sn9c102_strtou16(buf, len, &count); - if (!count || value > 0x7f) - return -EINVAL; - - if ((res = sn9c102_store_reg(cd, attr, "0x05", 4)) >= 0) - res = sn9c102_store_val(cd, attr, buf, len); - - return res; -} - - -static ssize_t sn9c102_show_frame_header(struct device* cd, - struct device_attribute *attr, - char* buf) -{ - struct sn9c102_device* cam; - ssize_t count; - - cam = video_get_drvdata(container_of(cd, struct video_device, dev)); - if (!cam) - return -ENODEV; - - count = sizeof(cam->sysfs.frame_header); - memcpy(buf, cam->sysfs.frame_header, count); - - DBG(3, "Frame header, read bytes: %zd", count); - - return count; -} - - -static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, sn9c102_show_reg, sn9c102_store_reg); -static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, sn9c102_show_val, sn9c102_store_val); -static DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, - sn9c102_show_i2c_reg, sn9c102_store_i2c_reg); -static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, - sn9c102_show_i2c_val, sn9c102_store_i2c_val); -static DEVICE_ATTR(green, S_IWUSR, NULL, sn9c102_store_green); -static DEVICE_ATTR(blue, S_IWUSR, NULL, sn9c102_store_blue); -static DEVICE_ATTR(red, S_IWUSR, NULL, sn9c102_store_red); -static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL); - - -static int sn9c102_create_sysfs(struct sn9c102_device* cam) -{ - struct device *dev = &(cam->v4ldev->dev); - int err = 0; - - if ((err = device_create_file(dev, &dev_attr_reg))) - goto err_out; - if ((err = device_create_file(dev, &dev_attr_val))) - goto err_reg; - if ((err = device_create_file(dev, &dev_attr_frame_header))) - goto err_val; - - if (cam->sensor.sysfs_ops) { - if ((err = device_create_file(dev, &dev_attr_i2c_reg))) - goto err_frame_header; - if ((err = device_create_file(dev, &dev_attr_i2c_val))) - goto err_i2c_reg; - } - - if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { - if ((err = device_create_file(dev, &dev_attr_green))) - goto err_i2c_val; - } else { - if ((err = device_create_file(dev, &dev_attr_blue))) - goto err_i2c_val; - if ((err = device_create_file(dev, &dev_attr_red))) - goto err_blue; - } - - return 0; - -err_blue: - device_remove_file(dev, &dev_attr_blue); -err_i2c_val: - if (cam->sensor.sysfs_ops) - device_remove_file(dev, &dev_attr_i2c_val); -err_i2c_reg: - if (cam->sensor.sysfs_ops) - device_remove_file(dev, &dev_attr_i2c_reg); -err_frame_header: - device_remove_file(dev, &dev_attr_frame_header); -err_val: - device_remove_file(dev, &dev_attr_val); -err_reg: - device_remove_file(dev, &dev_attr_reg); -err_out: - return err; -} -#endif /* CONFIG_VIDEO_ADV_DEBUG */ - -/*****************************************************************************/ - -static int -sn9c102_set_pix_format(struct sn9c102_device* cam, struct v4l2_pix_format* pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X || - pix->pixelformat == V4L2_PIX_FMT_JPEG) { - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - case BRIDGE_SN9C103: - err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, - 0x18); - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, - 0x18); - break; - } - } else { - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - case BRIDGE_SN9C103: - err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, - 0x18); - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, - 0x18); - break; - } - } - - return err ? -EIO : 0; -} - - -static int -sn9c102_set_compression(struct sn9c102_device* cam, - struct v4l2_jpegcompression* compression) -{ - int i, err = 0; - - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - case BRIDGE_SN9C103: - if (compression->quality == 0) - err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, - 0x17); - else if (compression->quality == 1) - err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, - 0x17); - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - if (compression->quality == 0) { - for (i = 0; i <= 63; i++) { - err += sn9c102_write_reg(cam, - SN9C102_Y_QTABLE1[i], - 0x100 + i); - err += sn9c102_write_reg(cam, - SN9C102_UV_QTABLE1[i], - 0x140 + i); - } - err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf, - 0x18); - } else if (compression->quality == 1) { - for (i = 0; i <= 63; i++) { - err += sn9c102_write_reg(cam, - SN9C102_Y_QTABLE1[i], - 0x100 + i); - err += sn9c102_write_reg(cam, - SN9C102_UV_QTABLE1[i], - 0x140 + i); - } - err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x40, - 0x18); - } - break; - } - - return err ? -EIO : 0; -} - - -static int sn9c102_set_scale(struct sn9c102_device* cam, u8 scale) -{ - u8 r = 0; - int err = 0; - - if (scale == 1) - r = cam->reg[0x18] & 0xcf; - else if (scale == 2) { - r = cam->reg[0x18] & 0xcf; - r |= 0x10; - } else if (scale == 4) - r = cam->reg[0x18] | 0x20; - - err += sn9c102_write_reg(cam, r, 0x18); - if (err) - return -EIO; - - PDBGG("Scaling factor: %u", scale); - - return 0; -} - - -static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect) -{ - struct sn9c102_sensor* s = &cam->sensor; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left), - v_start = (u8)(rect->top - s->cropcap.bounds.top), - h_size = (u8)(rect->width / 16), - v_size = (u8)(rect->height / 16); - int err = 0; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - err += sn9c102_write_reg(cam, h_size, 0x15); - err += sn9c102_write_reg(cam, v_size, 0x16); - if (err) - return -EIO; - - PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size " - "%u %u %u %u", h_start, v_start, h_size, v_size); - - return 0; -} - - -static int sn9c102_init(struct sn9c102_device* cam) -{ - struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - struct v4l2_queryctrl *qctrl; - struct v4l2_rect* rect; - u8 i = 0; - int err = 0; - - if (!(cam->state & DEV_INITIALIZED)) { - mutex_init(&cam->open_mutex); - init_waitqueue_head(&cam->wait_open); - qctrl = s->qctrl; - rect = &(s->cropcap.defrect); - } else { /* use current values */ - qctrl = s->_qctrl; - rect = &(s->_rect); - } - - err += sn9c102_set_scale(cam, rect->width / s->pix_format.width); - err += sn9c102_set_crop(cam, rect); - if (err) - return err; - - if (s->init) { - err = s->init(cam); - if (err) { - DBG(3, "Sensor initialization failed"); - return err; - } - } - - if (!(cam->state & DEV_INITIALIZED)) - 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); - } - else - err += sn9c102_set_compression(cam, &cam->compression); - err += sn9c102_set_pix_format(cam, &s->pix_format); - if (s->set_pix_format) - err += s->set_pix_format(cam, &s->pix_format); - if (err) - return err; - - if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X || - s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG) - DBG(3, "Compressed video format is active, quality %d", - cam->compression.quality); - else - DBG(3, "Uncompressed video format is active"); - - if (s->set_crop) - if ((err = s->set_crop(cam, rect))) { - DBG(3, "set_crop() failed"); - return err; - } - - if (s->set_ctrl) { - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (s->qctrl[i].id != 0 && - !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) { - ctrl.id = s->qctrl[i].id; - ctrl.value = qctrl[i].default_value; - err = s->set_ctrl(cam, &ctrl); - if (err) { - DBG(3, "Set %s control failed", - s->qctrl[i].name); - return err; - } - DBG(3, "Image sensor supports '%s' control", - s->qctrl[i].name); - } - } - - if (!(cam->state & DEV_INITIALIZED)) { - mutex_init(&cam->fileop_mutex); - spin_lock_init(&cam->queue_lock); - init_waitqueue_head(&cam->wait_frame); - init_waitqueue_head(&cam->wait_stream); - cam->nreadbuffers = 2; - memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl)); - memcpy(&(s->_rect), &(s->cropcap.defrect), - sizeof(struct v4l2_rect)); - cam->state |= DEV_INITIALIZED; - } - - DBG(2, "Initialization succeeded"); - return 0; -} - -/*****************************************************************************/ - -static void sn9c102_release_resources(struct kref *kref) -{ - struct sn9c102_device *cam; - - mutex_lock(&sn9c102_sysfs_lock); - - cam = container_of(kref, struct sn9c102_device, kref); - - DBG(2, "V4L2 device %s deregistered", - video_device_node_name(cam->v4ldev)); - video_set_drvdata(cam->v4ldev, NULL); - video_unregister_device(cam->v4ldev); - usb_put_dev(cam->usbdev); - kfree(cam->control_buffer); - kfree(cam); - - mutex_unlock(&sn9c102_sysfs_lock); - -} - - -static int sn9c102_open(struct file *filp) -{ - struct sn9c102_device* cam; - int err = 0; - - /* - A read_trylock() in open() is the only safe way to prevent race - conditions with disconnect(), one close() and multiple (not - necessarily simultaneous) attempts to open(). For example, it - prevents from waiting for a second access, while the device - structure is being deallocated, after a possible disconnect() and - during a following close() holding the write lock: given that, after - this deallocation, no access will be possible anymore, using the - non-trylock version would have let open() gain the access to the - device structure improperly. - For this reason the lock must also not be per-device. - */ - if (!down_read_trylock(&sn9c102_dev_lock)) - return -ERESTARTSYS; - - cam = video_drvdata(filp); - - if (wait_for_completion_interruptible(&cam->probe)) { - up_read(&sn9c102_dev_lock); - return -ERESTARTSYS; - } - - kref_get(&cam->kref); - - /* - Make sure to isolate all the simultaneous opens. - */ - if (mutex_lock_interruptible(&cam->open_mutex)) { - kref_put(&cam->kref, sn9c102_release_resources); - up_read(&sn9c102_dev_lock); - return -ERESTARTSYS; - } - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - err = -ENODEV; - goto out; - } - - if (cam->users) { - DBG(2, "Device %s is already in use", - video_device_node_name(cam->v4ldev)); - DBG(3, "Simultaneous opens are not supported"); - /* - open() must follow the open flags and should block - eventually while the device is in use. - */ - if ((filp->f_flags & O_NONBLOCK) || - (filp->f_flags & O_NDELAY)) { - err = -EWOULDBLOCK; - goto out; - } - DBG(2, "A blocking open() has been requested. Wait for the " - "device to be released..."); - up_read(&sn9c102_dev_lock); - /* - We will not release the "open_mutex" lock, so that only one - process can be in the wait queue below. This way the process - will be sleeping while holding the lock, without losing its - priority after any wake_up(). - */ - err = wait_event_interruptible_exclusive(cam->wait_open, - (cam->state & DEV_DISCONNECTED) - || !cam->users); - down_read(&sn9c102_dev_lock); - if (err) - goto out; - if (cam->state & DEV_DISCONNECTED) { - err = -ENODEV; - goto out; - } - } - - if (cam->state & DEV_MISCONFIGURED) { - err = sn9c102_init(cam); - if (err) { - DBG(1, "Initialization failed again. " - "I will retry on next open()."); - goto out; - } - cam->state &= ~DEV_MISCONFIGURED; - } - - if ((err = sn9c102_start_transfer(cam))) - goto out; - - filp->private_data = cam; - cam->users++; - cam->io = IO_NONE; - cam->stream = STREAM_OFF; - cam->nbuffers = 0; - cam->frame_count = 0; - sn9c102_empty_framequeues(cam); - - DBG(3, "Video device %s is open", video_device_node_name(cam->v4ldev)); - -out: - mutex_unlock(&cam->open_mutex); - if (err) - kref_put(&cam->kref, sn9c102_release_resources); - - up_read(&sn9c102_dev_lock); - return err; -} - - -static int sn9c102_release(struct file *filp) -{ - struct sn9c102_device* cam; - - down_write(&sn9c102_dev_lock); - - cam = video_drvdata(filp); - - sn9c102_stop_transfer(cam); - sn9c102_release_buffers(cam); - cam->users--; - wake_up_interruptible_nr(&cam->wait_open, 1); - - DBG(3, "Video device %s closed", video_device_node_name(cam->v4ldev)); - - kref_put(&cam->kref, sn9c102_release_resources); - - up_write(&sn9c102_dev_lock); - - return 0; -} - - -static ssize_t -sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) -{ - struct sn9c102_device *cam = video_drvdata(filp); - struct sn9c102_frame_t* f, * i; - unsigned long lock_flags; - long timeout; - int err = 0; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - if (cam->io == IO_MMAP) { - DBG(3, "Close and open the device again to choose " - "the read method"); - mutex_unlock(&cam->fileop_mutex); - return -EBUSY; - } - - if (cam->io == IO_NONE) { - if (!sn9c102_request_buffers(cam,cam->nreadbuffers, IO_READ)) { - DBG(1, "read() failed, not enough memory"); - mutex_unlock(&cam->fileop_mutex); - return -ENOMEM; - } - cam->io = IO_READ; - cam->stream = STREAM_ON; - } - - if (list_empty(&cam->inqueue)) { - if (!list_empty(&cam->outqueue)) - sn9c102_empty_framequeues(cam); - sn9c102_queue_unusedframes(cam); - } - - if (!count) { - mutex_unlock(&cam->fileop_mutex); - return 0; - } - - if (list_empty(&cam->outqueue)) { - if (filp->f_flags & O_NONBLOCK) { - mutex_unlock(&cam->fileop_mutex); - return -EAGAIN; - } - if (!cam->module_param.frame_timeout) { - err = wait_event_interruptible - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED) ); - if (err) { - mutex_unlock(&cam->fileop_mutex); - return err; - } - } else { - timeout = wait_event_interruptible_timeout - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), - msecs_to_jiffies( - cam->module_param.frame_timeout * 1000 - ) - ); - if (timeout < 0) { - mutex_unlock(&cam->fileop_mutex); - return timeout; - } else if (timeout == 0 && - !(cam->state & DEV_DISCONNECTED)) { - DBG(1, "Video frame timeout elapsed"); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - } - if (cam->state & DEV_DISCONNECTED) { - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - if (cam->state & DEV_MISCONFIGURED) { - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - } - - f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame); - - if (count > f->buf.bytesused) - count = f->buf.bytesused; - - if (copy_to_user(buf, f->bufmem, count)) { - err = -EFAULT; - goto exit; - } - *f_pos += count; - -exit: - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_for_each_entry(i, &cam->outqueue, frame) - i->state = F_UNUSED; - INIT_LIST_HEAD(&cam->outqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - - sn9c102_queue_unusedframes(cam); - - PDBGG("Frame #%lu, bytes read: %zu", - (unsigned long)f->buf.index, count); - - mutex_unlock(&cam->fileop_mutex); - - return count; -} - - -static unsigned int sn9c102_poll(struct file *filp, poll_table *wait) -{ - struct sn9c102_device *cam = video_drvdata(filp); - struct sn9c102_frame_t* f; - unsigned long lock_flags; - unsigned int mask = 0; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return POLLERR; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - goto error; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - goto error; - } - - if (cam->io == IO_NONE) { - if (!sn9c102_request_buffers(cam, cam->nreadbuffers, - IO_READ)) { - DBG(1, "poll() failed, not enough memory"); - goto error; - } - cam->io = IO_READ; - cam->stream = STREAM_ON; - } - - if (cam->io == IO_READ) { - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_for_each_entry(f, &cam->outqueue, frame) - f->state = F_UNUSED; - INIT_LIST_HEAD(&cam->outqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - sn9c102_queue_unusedframes(cam); - } - - poll_wait(filp, &cam->wait_frame, wait); - - if (!list_empty(&cam->outqueue)) - mask |= POLLIN | POLLRDNORM; - - mutex_unlock(&cam->fileop_mutex); - - return mask; - -error: - mutex_unlock(&cam->fileop_mutex); - return POLLERR; -} - - -static void sn9c102_vm_open(struct vm_area_struct* vma) -{ - struct sn9c102_frame_t* f = vma->vm_private_data; - f->vma_use_count++; -} - - -static void sn9c102_vm_close(struct vm_area_struct* vma) -{ - /* NOTE: buffers are not freed here */ - struct sn9c102_frame_t* f = vma->vm_private_data; - f->vma_use_count--; -} - - -static const struct vm_operations_struct sn9c102_vm_ops = { - .open = sn9c102_vm_open, - .close = sn9c102_vm_close, -}; - - -static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) -{ - struct sn9c102_device *cam = video_drvdata(filp); - unsigned long size = vma->vm_end - vma->vm_start, - start = vma->vm_start; - void *pos; - u32 i; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - 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; - } - - for (i = 0; i < cam->nbuffers; i++) { - if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff) - break; - } - if (i == cam->nbuffers) { - mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - - vma->vm_flags |= VM_IO; - vma->vm_flags |= VM_RESERVED; - - pos = cam->frame[i].bufmem; - while (size > 0) { /* size is page-aligned */ - if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { - mutex_unlock(&cam->fileop_mutex); - return -EAGAIN; - } - start += PAGE_SIZE; - pos += PAGE_SIZE; - size -= PAGE_SIZE; - } - - vma->vm_ops = &sn9c102_vm_ops; - vma->vm_private_data = &cam->frame[i]; - sn9c102_vm_open(vma); - - mutex_unlock(&cam->fileop_mutex); - - return 0; -} - -/*****************************************************************************/ - -static int -sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_capability cap = { - .driver = "sn9c102", - .version = LINUX_VERSION_CODE, - .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING, - }; - - strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); - if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) - strlcpy(cap.bus_info, dev_name(&cam->usbdev->dev), - sizeof(cap.bus_info)); - - if (copy_to_user(arg, &cap, sizeof(cap))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_input i; - - if (copy_from_user(&i, arg, sizeof(i))) - return -EFAULT; - - if (i.index) - return -EINVAL; - - memset(&i, 0, sizeof(i)); - strcpy(i.name, "Camera"); - i.type = V4L2_INPUT_TYPE_CAMERA; - i.capabilities = V4L2_IN_CAP_STD; - - if (copy_to_user(arg, &i, sizeof(i))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_g_input(struct sn9c102_device* cam, void __user * arg) -{ - int index = 0; - - if (copy_to_user(arg, &index, sizeof(index))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_s_input(struct sn9c102_device* cam, void __user * arg) -{ - int index; - - if (copy_from_user(&index, arg, sizeof(index))) - return -EFAULT; - - if (index != 0) - return -EINVAL; - - return 0; -} - - -static int -sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg) -{ - struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_queryctrl qc; - u8 i; - - if (copy_from_user(&qc, arg, sizeof(qc))) - return -EFAULT; - - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (qc.id && qc.id == s->qctrl[i].id) { - memcpy(&qc, &(s->qctrl[i]), sizeof(qc)); - if (copy_to_user(arg, &qc, sizeof(qc))) - return -EFAULT; - return 0; - } - - return -EINVAL; -} - - -static int -sn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg) -{ - struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - int err = 0; - u8 i; - - if (!s->get_ctrl && !s->set_ctrl) - return -EINVAL; - - if (copy_from_user(&ctrl, arg, sizeof(ctrl))) - return -EFAULT; - - if (!s->get_ctrl) { - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (ctrl.id && ctrl.id == s->qctrl[i].id) { - ctrl.value = s->_qctrl[i].default_value; - goto exit; - } - return -EINVAL; - } else - err = s->get_ctrl(cam, &ctrl); - -exit: - if (copy_to_user(arg, &ctrl, sizeof(ctrl))) - return -EFAULT; - - PDBGG("VIDIOC_G_CTRL: id %lu, value %lu", - (unsigned long)ctrl.id, (unsigned long)ctrl.value); - - return err; -} - - -static int -sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg) -{ - struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - u8 i; - int err = 0; - - if (!s->set_ctrl) - return -EINVAL; - - if (copy_from_user(&ctrl, arg, sizeof(ctrl))) - return -EFAULT; - - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) { - if (ctrl.id == s->qctrl[i].id) { - if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) - return -EINVAL; - if (ctrl.value < s->qctrl[i].minimum || - ctrl.value > s->qctrl[i].maximum) - return -ERANGE; - ctrl.value -= ctrl.value % s->qctrl[i].step; - break; - } - } - if (i == ARRAY_SIZE(s->qctrl)) - return -EINVAL; - if ((err = s->set_ctrl(cam, &ctrl))) - return err; - - s->_qctrl[i].default_value = ctrl.value; - - PDBGG("VIDIOC_S_CTRL: id %lu, value %lu", - (unsigned long)ctrl.id, (unsigned long)ctrl.value); - - return 0; -} - - -static int -sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_cropcap* cc = &(cam->sensor.cropcap); - - cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - cc->pixelaspect.numerator = 1; - cc->pixelaspect.denominator = 1; - - if (copy_to_user(arg, cc, sizeof(*cc))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg) -{ - struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_crop crop = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - }; - - memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect)); - - if (copy_to_user(arg, &crop, sizeof(crop))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) -{ - struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_crop crop; - struct v4l2_rect* rect; - struct v4l2_rect* bounds = &(s->cropcap.bounds); - struct v4l2_pix_format* pix_format = &(s->pix_format); - u8 scale; - const enum sn9c102_stream_state stream = cam->stream; - const u32 nbuffers = cam->nbuffers; - u32 i; - int err = 0; - - if (copy_from_user(&crop, arg, sizeof(crop))) - return -EFAULT; - - rect = &(crop.c); - - if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (cam->module_param.force_munmap) - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_S_CROP failed. " - "Unmap the buffers first."); - return -EBUSY; - } - - /* Preserve R,G or B origin */ - rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L; - rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L; - - if (rect->width < 16) - rect->width = 16; - if (rect->height < 16) - rect->height = 16; - if (rect->width > bounds->width) - rect->width = bounds->width; - if (rect->height > bounds->height) - rect->height = bounds->height; - if (rect->left < bounds->left) - rect->left = bounds->left; - if (rect->top < bounds->top) - rect->top = bounds->top; - if (rect->left + rect->width > bounds->left + bounds->width) - rect->left = bounds->left+bounds->width - rect->width; - if (rect->top + rect->height > bounds->top + bounds->height) - rect->top = bounds->top+bounds->height - rect->height; - - rect->width &= ~15L; - rect->height &= ~15L; - - if (SN9C102_PRESERVE_IMGSCALE) { - /* Calculate the actual scaling factor */ - u32 a, b; - a = rect->width * rect->height; - b = pix_format->width * pix_format->height; - scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1; - } else - scale = 1; - - if (cam->stream == STREAM_ON) - if ((err = sn9c102_stream_interrupt(cam))) - return err; - - if (copy_to_user(arg, &crop, sizeof(crop))) { - cam->stream = stream; - return -EFAULT; - } - - if (cam->module_param.force_munmap || cam->io == IO_READ) - sn9c102_release_buffers(cam); - - err = sn9c102_set_crop(cam, rect); - if (s->set_crop) - err += s->set_crop(cam, rect); - err += sn9c102_set_scale(cam, scale); - - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " - "use the camera, close and open %s again.", - video_device_node_name(cam->v4ldev)); - return -EIO; - } - - s->pix_format.width = rect->width/scale; - s->pix_format.height = rect->height/scale; - memcpy(&(s->_rect), rect, sizeof(*rect)); - - if ((cam->module_param.force_munmap || cam->io == IO_READ) && - nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " - "use the camera, close and open %s again.", - video_device_node_name(cam->v4ldev)); - return -ENOMEM; - } - - if (cam->io == IO_READ) - sn9c102_empty_framequeues(cam); - else if (cam->module_param.force_munmap) - sn9c102_requeue_outqueue(cam); - - cam->stream = stream; - - return 0; -} - - -static int -sn9c102_vidioc_enum_framesizes(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_frmsizeenum frmsize; - - if (copy_from_user(&frmsize, arg, sizeof(frmsize))) - return -EFAULT; - - if (frmsize.index != 0) - return -EINVAL; - - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - case BRIDGE_SN9C103: - if (frmsize.pixel_format != V4L2_PIX_FMT_SN9C10X && - frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8) - return -EINVAL; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG && - frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8) - return -EINVAL; - } - - frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE; - frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16; - frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16; - frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width; - frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height; - memset(&frmsize.reserved, 0, sizeof(frmsize.reserved)); - - if (copy_to_user(arg, &frmsize, sizeof(frmsize))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_fmtdesc fmtd; - - if (copy_from_user(&fmtd, arg, sizeof(fmtd))) - return -EFAULT; - - if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (fmtd.index == 0) { - strcpy(fmtd.description, "bayer rgb"); - fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; - } else if (fmtd.index == 1) { - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - case BRIDGE_SN9C103: - strcpy(fmtd.description, "compressed"); - fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - strcpy(fmtd.description, "JPEG"); - fmtd.pixelformat = V4L2_PIX_FMT_JPEG; - break; - } - fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; - } else - return -EINVAL; - - fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - memset(&fmtd.reserved, 0, sizeof(fmtd.reserved)); - - if (copy_to_user(arg, &fmtd, sizeof(fmtd))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_format format; - struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format); - - if (copy_from_user(&format, arg, sizeof(format))) - return -EFAULT; - - if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - 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; - memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); - - if (copy_to_user(arg, &format, sizeof(format))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, - void __user * arg) -{ - struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_format format; - struct v4l2_pix_format* pix; - struct v4l2_pix_format* pfmt = &(s->pix_format); - struct v4l2_rect* bounds = &(s->cropcap.bounds); - struct v4l2_rect rect; - u8 scale; - const enum sn9c102_stream_state stream = cam->stream; - const u32 nbuffers = cam->nbuffers; - u32 i; - int err = 0; - - if (copy_from_user(&format, arg, sizeof(format))) - return -EFAULT; - - pix = &(format.fmt.pix); - - if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - memcpy(&rect, &(s->_rect), sizeof(rect)); - - { /* calculate the actual scaling factor */ - u32 a, b; - a = rect.width * rect.height; - b = pix->width * pix->height; - scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1; - } - - rect.width = scale * pix->width; - rect.height = scale * pix->height; - - if (rect.width < 16) - rect.width = 16; - if (rect.height < 16) - rect.height = 16; - if (rect.width > bounds->left + bounds->width - rect.left) - rect.width = bounds->left + bounds->width - rect.left; - if (rect.height > bounds->top + bounds->height - rect.top) - rect.height = bounds->top + bounds->height - rect.top; - - rect.width &= ~15L; - rect.height &= ~15L; - - { /* adjust the scaling factor */ - u32 a, b; - a = rect.width * rect.height; - b = pix->width * pix->height; - scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1; - } - - pix->width = rect.width / scale; - pix->height = rect.height / scale; - - switch (cam->bridge) { - 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; - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - if (pix->pixelformat != V4L2_PIX_FMT_JPEG && - pix->pixelformat != V4L2_PIX_FMT_SBGGR8) - pix->pixelformat = pfmt->pixelformat; - break; - } - pix->priv = pfmt->priv; /* bpp */ - 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; - pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); - pix->field = V4L2_FIELD_NONE; - - if (cmd == VIDIOC_TRY_FMT) { - if (copy_to_user(arg, &format, sizeof(format))) - return -EFAULT; - return 0; - } - - if (cam->module_param.force_munmap) - for (i = 0; i < cam->nbuffers; i++) - if (cam->frame[i].vma_use_count) { - DBG(3, "VIDIOC_S_FMT failed. Unmap the " - "buffers first."); - return -EBUSY; - } - - if (cam->stream == STREAM_ON) - if ((err = sn9c102_stream_interrupt(cam))) - return err; - - if (copy_to_user(arg, &format, sizeof(format))) { - cam->stream = stream; - return -EFAULT; - } - - if (cam->module_param.force_munmap || cam->io == IO_READ) - sn9c102_release_buffers(cam); - - err += sn9c102_set_pix_format(cam, pix); - err += sn9c102_set_crop(cam, &rect); - if (s->set_pix_format) - err += s->set_pix_format(cam, pix); - if (s->set_crop) - err += s->set_crop(cam, &rect); - err += sn9c102_set_scale(cam, scale); - - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " - "use the camera, close and open %s again.", - video_device_node_name(cam->v4ldev)); - return -EIO; - } - - memcpy(pfmt, pix, sizeof(*pix)); - memcpy(&(s->_rect), &rect, sizeof(rect)); - - if ((cam->module_param.force_munmap || cam->io == IO_READ) && - nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " - "use the camera, close and open %s again.", - video_device_node_name(cam->v4ldev)); - return -ENOMEM; - } - - if (cam->io == IO_READ) - sn9c102_empty_framequeues(cam); - else if (cam->module_param.force_munmap) - sn9c102_requeue_outqueue(cam); - - cam->stream = stream; - - return 0; -} - - -static int -sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg) -{ - if (copy_to_user(arg, &cam->compression, sizeof(cam->compression))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_s_jpegcomp(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_jpegcompression jc; - const enum sn9c102_stream_state stream = cam->stream; - int err = 0; - - if (copy_from_user(&jc, arg, sizeof(jc))) - return -EFAULT; - - if (jc.quality != 0 && jc.quality != 1) - return -EINVAL; - - if (cam->stream == STREAM_ON) - if ((err = sn9c102_stream_interrupt(cam))) - return err; - - err += sn9c102_set_compression(cam, &jc); - if (err) { /* atomic, no rollback in ioctl() */ - cam->state |= DEV_MISCONFIGURED; - DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware problems. " - "To use the camera, close and open %s again.", - video_device_node_name(cam->v4ldev)); - return -EIO; - } - - cam->compression.quality = jc.quality; - - cam->stream = stream; - - return 0; -} - - -static int -sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_requestbuffers rb; - u32 i; - int err; - - if (copy_from_user(&rb, arg, sizeof(rb))) - return -EFAULT; - - if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - rb.memory != V4L2_MEMORY_MMAP) - return -EINVAL; - - if (cam->io == IO_READ) { - DBG(3, "Close and open the device again to choose the mmap " - "I/O method"); - 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 -EBUSY; - } - - if (cam->stream == STREAM_ON) - if ((err = sn9c102_stream_interrupt(cam))) - return err; - - sn9c102_empty_framequeues(cam); - - sn9c102_release_buffers(cam); - if (rb.count) - rb.count = sn9c102_request_buffers(cam, rb.count, IO_MMAP); - - if (copy_to_user(arg, &rb, sizeof(rb))) { - sn9c102_release_buffers(cam); - cam->io = IO_NONE; - return -EFAULT; - } - - cam->io = rb.count ? IO_MMAP : IO_NONE; - - return 0; -} - - -static int -sn9c102_vidioc_querybuf(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_buffer b; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; - - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - b.index >= cam->nbuffers || cam->io != IO_MMAP) - return -EINVAL; - - memcpy(&b, &cam->frame[b.index].buf, sizeof(b)); - - if (cam->frame[b.index].vma_use_count) - b.flags |= V4L2_BUF_FLAG_MAPPED; - - if (cam->frame[b.index].state == F_DONE) - b.flags |= V4L2_BUF_FLAG_DONE; - else if (cam->frame[b.index].state != F_UNUSED) - b.flags |= V4L2_BUF_FLAG_QUEUED; - - if (copy_to_user(arg, &b, sizeof(b))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_qbuf(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_buffer b; - unsigned long lock_flags; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; - - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - b.index >= cam->nbuffers || cam->io != IO_MMAP) - return -EINVAL; - - if (cam->frame[b.index].state != F_UNUSED) - return -EINVAL; - - cam->frame[b.index].state = F_QUEUED; - - spin_lock_irqsave(&cam->queue_lock, lock_flags); - list_add_tail(&cam->frame[b.index].frame, &cam->inqueue); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - - PDBGG("Frame #%lu queued", (unsigned long)b.index); - - return 0; -} - - -static int -sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp, - void __user * arg) -{ - struct v4l2_buffer b; - struct sn9c102_frame_t *f; - unsigned long lock_flags; - long timeout; - int err = 0; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; - - if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) - return -EINVAL; - - if (list_empty(&cam->outqueue)) { - if (cam->stream == STREAM_OFF) - return -EINVAL; - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - if (!cam->module_param.frame_timeout) { - err = wait_event_interruptible - ( cam->wait_frame, - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED) ); - 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; - else if (timeout == 0 && - !(cam->state & DEV_DISCONNECTED)) { - DBG(1, "Video frame timeout elapsed"); - return -EIO; - } - } - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; - if (cam->state & DEV_MISCONFIGURED) - return -EIO; - } - - spin_lock_irqsave(&cam->queue_lock, lock_flags); - f = list_entry(cam->outqueue.next, struct sn9c102_frame_t, frame); - list_del(cam->outqueue.next); - spin_unlock_irqrestore(&cam->queue_lock, lock_flags); - - f->state = F_UNUSED; - - memcpy(&b, &f->buf, sizeof(b)); - if (f->vma_use_count) - b.flags |= V4L2_BUF_FLAG_MAPPED; - - if (copy_to_user(arg, &b, sizeof(b))) - return -EFAULT; - - PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index); - - return 0; -} - - -static int -sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg) -{ - int type; - - if (copy_from_user(&type, arg, sizeof(type))) - return -EFAULT; - - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) - return -EINVAL; - - cam->stream = STREAM_ON; - - DBG(3, "Stream on"); - - return 0; -} - - -static int -sn9c102_vidioc_streamoff(struct sn9c102_device* cam, void __user * arg) -{ - int type, err; - - if (copy_from_user(&type, arg, sizeof(type))) - return -EFAULT; - - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) - return -EINVAL; - - if (cam->stream == STREAM_ON) - if ((err = sn9c102_stream_interrupt(cam))) - return err; - - sn9c102_empty_framequeues(cam); - - DBG(3, "Stream off"); - - return 0; -} - - -static int -sn9c102_vidioc_g_parm(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_streamparm sp; - - if (copy_from_user(&sp, arg, sizeof(sp))) - return -EFAULT; - - if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - sp.parm.capture.extendedmode = 0; - sp.parm.capture.readbuffers = cam->nreadbuffers; - - if (copy_to_user(arg, &sp, sizeof(sp))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_s_parm(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_streamparm sp; - - if (copy_from_user(&sp, arg, sizeof(sp))) - return -EFAULT; - - if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - sp.parm.capture.extendedmode = 0; - - if (sp.parm.capture.readbuffers == 0) - sp.parm.capture.readbuffers = cam->nreadbuffers; - - if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES) - sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES; - - if (copy_to_user(arg, &sp, sizeof(sp))) - return -EFAULT; - - cam->nreadbuffers = sp.parm.capture.readbuffers; - - return 0; -} - - -static int -sn9c102_vidioc_enumaudio(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_audio audio; - - if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) - return -EINVAL; - - if (copy_from_user(&audio, arg, sizeof(audio))) - return -EFAULT; - - if (audio.index != 0) - return -EINVAL; - - strcpy(audio.name, "Microphone"); - audio.capability = 0; - audio.mode = 0; - - if (copy_to_user(arg, &audio, sizeof(audio))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_g_audio(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_audio audio; - - if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) - return -EINVAL; - - if (copy_from_user(&audio, arg, sizeof(audio))) - return -EFAULT; - - memset(&audio, 0, sizeof(audio)); - strcpy(audio.name, "Microphone"); - - if (copy_to_user(arg, &audio, sizeof(audio))) - return -EFAULT; - - return 0; -} - - -static int -sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg) -{ - struct v4l2_audio audio; - - if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) - return -EINVAL; - - if (copy_from_user(&audio, arg, sizeof(audio))) - return -EFAULT; - - if (audio.index != 0) - return -EINVAL; - - return 0; -} - - -static long sn9c102_ioctl_v4l2(struct file *filp, - unsigned int cmd, void __user *arg) -{ - struct sn9c102_device *cam = video_drvdata(filp); - - switch (cmd) { - - case VIDIOC_QUERYCAP: - return sn9c102_vidioc_querycap(cam, arg); - - case VIDIOC_ENUMINPUT: - return sn9c102_vidioc_enuminput(cam, arg); - - case VIDIOC_G_INPUT: - return sn9c102_vidioc_g_input(cam, arg); - - case VIDIOC_S_INPUT: - return sn9c102_vidioc_s_input(cam, arg); - - case VIDIOC_QUERYCTRL: - return sn9c102_vidioc_query_ctrl(cam, arg); - - case VIDIOC_G_CTRL: - return sn9c102_vidioc_g_ctrl(cam, arg); - - case VIDIOC_S_CTRL: - return sn9c102_vidioc_s_ctrl(cam, arg); - - case VIDIOC_CROPCAP: - return sn9c102_vidioc_cropcap(cam, arg); - - case VIDIOC_G_CROP: - return sn9c102_vidioc_g_crop(cam, arg); - - case VIDIOC_S_CROP: - return sn9c102_vidioc_s_crop(cam, arg); - - case VIDIOC_ENUM_FRAMESIZES: - return sn9c102_vidioc_enum_framesizes(cam, arg); - - case VIDIOC_ENUM_FMT: - return sn9c102_vidioc_enum_fmt(cam, arg); - - case VIDIOC_G_FMT: - return sn9c102_vidioc_g_fmt(cam, arg); - - case VIDIOC_TRY_FMT: - case VIDIOC_S_FMT: - return sn9c102_vidioc_try_s_fmt(cam, cmd, arg); - - case VIDIOC_G_JPEGCOMP: - return sn9c102_vidioc_g_jpegcomp(cam, arg); - - case VIDIOC_S_JPEGCOMP: - return sn9c102_vidioc_s_jpegcomp(cam, arg); - - case VIDIOC_REQBUFS: - return sn9c102_vidioc_reqbufs(cam, arg); - - case VIDIOC_QUERYBUF: - return sn9c102_vidioc_querybuf(cam, arg); - - case VIDIOC_QBUF: - return sn9c102_vidioc_qbuf(cam, arg); - - case VIDIOC_DQBUF: - return sn9c102_vidioc_dqbuf(cam, filp, arg); - - case VIDIOC_STREAMON: - return sn9c102_vidioc_streamon(cam, arg); - - case VIDIOC_STREAMOFF: - return sn9c102_vidioc_streamoff(cam, arg); - - case VIDIOC_G_PARM: - return sn9c102_vidioc_g_parm(cam, arg); - - case VIDIOC_S_PARM: - return sn9c102_vidioc_s_parm(cam, arg); - - case VIDIOC_ENUMAUDIO: - return sn9c102_vidioc_enumaudio(cam, arg); - - case VIDIOC_G_AUDIO: - return sn9c102_vidioc_g_audio(cam, arg); - - case VIDIOC_S_AUDIO: - return sn9c102_vidioc_s_audio(cam, arg); - - default: - return -ENOTTY; - - } -} - - -static long sn9c102_ioctl(struct file *filp, - unsigned int cmd, unsigned long arg) -{ - struct sn9c102_device *cam = video_drvdata(filp); - int err = 0; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - V4LDBG(3, "sn9c102", cmd); - - err = sn9c102_ioctl_v4l2(filp, cmd, (void __user *)arg); - - mutex_unlock(&cam->fileop_mutex); - - return err; -} - -/*****************************************************************************/ - -static const struct v4l2_file_operations sn9c102_fops = { - .owner = THIS_MODULE, - .open = sn9c102_open, - .release = sn9c102_release, - .unlocked_ioctl = sn9c102_ioctl, - .read = sn9c102_read, - .poll = sn9c102_poll, - .mmap = sn9c102_mmap, -}; - -/*****************************************************************************/ - -/* It exists a single interface only. We do not need to validate anything. */ -static int -sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct sn9c102_device* cam; - static unsigned int dev_nr; - unsigned int i; - int err = 0, r; - - if (!(cam = kzalloc(sizeof(struct sn9c102_device), GFP_KERNEL))) - return -ENOMEM; - - cam->usbdev = udev; - - if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) { - DBG(1, "kzalloc() failed"); - err = -ENOMEM; - goto fail; - } - - if (!(cam->v4ldev = video_device_alloc())) { - DBG(1, "video_device_alloc() failed"); - err = -ENOMEM; - goto fail; - } - - 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); - err = -ENODEV; - goto fail; - } - - cam->bridge = id->driver_info; - switch (cam->bridge) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - DBG(2, "SN9C10[12] PC Camera Controller detected " - "(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); - break; - case BRIDGE_SN9C105: - DBG(2, "SN9C105 PC Camera Controller detected " - "(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); - break; - } - - for (i = 0; i < ARRAY_SIZE(sn9c102_sensor_table); i++) { - err = sn9c102_sensor_table[i](cam); - if (!err) - break; - } - - if (!err) { - DBG(2, "%s image sensor detected", cam->sensor.name); - DBG(3, "Support for %s maintained by %s", - cam->sensor.name, cam->sensor.maintainer); - } else { - DBG(1, "No supported image sensor detected for this bridge"); - err = -ENODEV; - goto fail; - } - - if (!(cam->bridge & cam->sensor.supported_bridge)) { - DBG(1, "Bridge not supported"); - err = -ENODEV; - goto fail; - } - - if (sn9c102_init(cam)) { - DBG(1, "Initialization failed. I will retry on open()."); - cam->state |= DEV_MISCONFIGURED; - } - - strcpy(cam->v4ldev->name, "SN9C1xx PC Camera"); - cam->v4ldev->fops = &sn9c102_fops; - cam->v4ldev->release = video_device_release; - cam->v4ldev->parent = &udev->dev; - - init_completion(&cam->probe); - - err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, - video_nr[dev_nr]); - if (err) { - DBG(1, "V4L2 device registration failed"); - if (err == -ENFILE && video_nr[dev_nr] == -1) - DBG(1, "Free /dev/videoX node not found"); - video_nr[dev_nr] = -1; - dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; - complete_all(&cam->probe); - goto fail; - } - - DBG(2, "V4L2 device registered as %s", - video_device_node_name(cam->v4ldev)); - - video_set_drvdata(cam->v4ldev, cam); - cam->module_param.force_munmap = force_munmap[dev_nr]; - cam->module_param.frame_timeout = frame_timeout[dev_nr]; - - dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; - -#ifdef CONFIG_VIDEO_ADV_DEBUG - err = sn9c102_create_sysfs(cam); - if (!err) - DBG(2, "Optional device control through 'sysfs' " - "interface ready"); - else - DBG(2, "Failed to create optional 'sysfs' interface for " - "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); - kref_init(&cam->kref); - usb_get_dev(cam->usbdev); - - complete_all(&cam->probe); - - return 0; - -fail: - if (cam) { - kfree(cam->control_buffer); - if (cam->v4ldev) - video_device_release(cam->v4ldev); - kfree(cam); - } - return err; -} - - -static void sn9c102_usb_disconnect(struct usb_interface* intf) -{ - struct sn9c102_device* cam; - - down_write(&sn9c102_dev_lock); - - cam = usb_get_intfdata(intf); - - DBG(2, "Disconnecting %s...", cam->v4ldev->name); - - if (cam->users) { - DBG(2, "Device %s is open! Deregistration and memory " - "deallocation are deferred.", - video_device_node_name(cam->v4ldev)); - cam->state |= DEV_MISCONFIGURED; - sn9c102_stop_transfer(cam); - cam->state |= DEV_DISCONNECTED; - wake_up_interruptible(&cam->wait_frame); - wake_up(&cam->wait_stream); - } else - cam->state |= DEV_DISCONNECTED; - - wake_up_interruptible_all(&cam->wait_open); - - kref_put(&cam->kref, sn9c102_release_resources); - - up_write(&sn9c102_dev_lock); -} - - -static struct usb_driver sn9c102_usb_driver = { - .name = "sn9c102", - .id_table = sn9c102_id_table, - .probe = sn9c102_usb_probe, - .disconnect = sn9c102_usb_disconnect, -}; - -module_usb_driver(sn9c102_usb_driver); diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h deleted file mode 100644 index b3d2cc729657..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ /dev/null @@ -1,147 +0,0 @@ -/*************************************************************************** - * Table of device identifiers of 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. * - ***************************************************************************/ - -#ifndef _SN9C102_DEVTABLE_H_ -#define _SN9C102_DEVTABLE_H_ - -#include <linux/usb.h> - -struct sn9c102_device; - -/* - Each SN9C1xx camera has proper PID/VID identifiers. - SN9C103, SN9C105, SN9C120 support multiple interfaces, but we only have to - handle the video class interface. -*/ -#define SN9C102_USB_DEVICE(vend, prod, bridge) \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ - USB_DEVICE_ID_MATCH_INT_CLASS, \ - .idVendor = (vend), \ - .idProduct = (prod), \ - .bInterfaceClass = 0xff, \ - .driver_info = (bridge) - -static const struct usb_device_id sn9c102_id_table[] = { - /* SN9C101 and SN9C102 */ -#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE - { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, -/* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */ - { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), }, -#endif - { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), }, -#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE - { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), }, -#endif - { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, /* not in sonixb */ -#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE - { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, -/* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */ - { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), }, -#endif - { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, /* not in sonixb */ - /* SN9C103 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), }, non existent ? */ - { SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), }, /* not in sonixb */ -#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE -/* { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), }, HY7131D/E */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, non existent ? */ - { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), }, -/* { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, CISVF10 */ - { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), }, -/* { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), }, PAS106 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), }, TAS5130 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, TAS5110, non existent */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, non existent ? */ - { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), }, -/* { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60ba, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60bb, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, non existent ? */ -#endif - /* SN9C105 */ -#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE - { 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), }, PO1030 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), }, OM6801 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), }, HV7131GP */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), }, non existent ? */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), }, MO4000 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60ef, BRIDGE_SN9C105), }, ICM105C */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), }, OV7648 */ - { 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), }, po2030 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), }, om6801 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, S5K53BEB */ - { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), }, -/* { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, MO8000 */ - { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), }, - { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, - { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, - { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), }, -#endif - { } -}; - -/* - Probing functions: on success, you must attach the sensor to the camera - by calling sn9c102_attach_sensor(). - To enable the I2C communication, you might need to perform a really basic - initialization of the SN9C1XX chip. - 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_mt9v111(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); - -#endif /* _SN9C102_DEVTABLE_H_ */ diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c deleted file mode 100644 index 2dce5c908c8e..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c +++ /dev/null @@ -1,264 +0,0 @@ -/*************************************************************************** - * Plug-in for HV7131D image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2004-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" -#include "sn9c102_devtable.h" - - -static int hv7131d_init(struct sn9c102_device* cam) -{ - int err; - - 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); - err += sn9c102_i2c_write(cam, 0x28, 0x00); - - return err; -} - - -static int hv7131d_get_ctrl(struct sn9c102_device* cam, - struct v4l2_control* ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - { - int r1 = sn9c102_i2c_read(cam, 0x26), - r2 = sn9c102_i2c_read(cam, 0x27); - if (r1 < 0 || r2 < 0) - return -EIO; - ctrl->value = (r1 << 8) | (r2 & 0xff); - } - return 0; - case V4L2_CID_RED_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0) - return -EIO; - ctrl->value = 0x3f - (ctrl->value & 0x3f); - return 0; - case V4L2_CID_BLUE_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0) - return -EIO; - ctrl->value = 0x3f - (ctrl->value & 0x3f); - return 0; - case SN9C102_V4L2_CID_GREEN_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0) - return -EIO; - ctrl->value = 0x3f - (ctrl->value & 0x3f); - return 0; - case SN9C102_V4L2_CID_RESET_LEVEL: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0) - return -EIO; - ctrl->value &= 0x3f; - return 0; - case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x34)) < 0) - return -EIO; - ctrl->value &= 0x07; - return 0; - default: - return -EINVAL; - } -} - - -static int hv7131d_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x26, ctrl->value >> 8); - err += sn9c102_i2c_write(cam, 0x27, ctrl->value & 0xff); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_write(cam, 0x31, 0x3f - ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_write(cam, 0x33, 0x3f - ctrl->value); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_i2c_write(cam, 0x32, 0x3f - ctrl->value); - break; - case SN9C102_V4L2_CID_RESET_LEVEL: - err += sn9c102_i2c_write(cam, 0x30, ctrl->value); - break; - case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE: - err += sn9c102_i2c_write(cam, 0x34, ctrl->value); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int hv7131d_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) + 2, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static int hv7131d_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, 0x42, 0x19); - else - err += sn9c102_write_reg(cam, 0xf2, 0x19); - - return err; -} - - -static const struct sn9c102_sensor hv7131d = { - .name = "HV7131D", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, - .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x11, - .init = &hv7131d_init, - .qctrl = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x0250, - .maximum = 0xffff, - .step = 0x0001, - .default_value = 0x0250, - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x20, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x1e, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_RESET_LEVEL, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "reset level", - .minimum = 0x19, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x30, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "pixel bias voltage", - .minimum = 0x00, - .maximum = 0x07, - .step = 0x01, - .default_value = 0x02, - .flags = 0, - }, - }, - .get_ctrl = &hv7131d_get_ctrl, - .set_ctrl = &hv7131d_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &hv7131d_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &hv7131d_set_pix_format -}; - - -int sn9c102_probe_hv7131d(struct sn9c102_device* cam) -{ - int r0 = 0, r1 = 0, err; - - 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 (err || r0 < 0 || r1 < 0) - return -EIO; - - if ((r0 != 0x00 && r0 != 0x01) || r1 != 0x04) - return -ENODEV; - - sn9c102_attach_sensor(cam, &hv7131d); - - return 0; -} diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131r.c b/drivers/media/video/sn9c102/sn9c102_hv7131r.c deleted file mode 100644 index 4295887ff609..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_hv7131r.c +++ /dev/null @@ -1,363 +0,0 @@ -/*************************************************************************** - * 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" -#include "sn9c102_devtable.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/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c deleted file mode 100644 index 1f5b09bec89c..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_mi0343.c +++ /dev/null @@ -1,352 +0,0 @@ -/*************************************************************************** - * Plug-in for MI-0343 image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2004-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" -#include "sn9c102_devtable.h" - - -static int mi0343_init(struct sn9c102_device* cam) -{ - struct sn9c102_sensor* s = sn9c102_get_sensor(cam); - int err = 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; -} - - -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, 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; - break; - 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; - case V4L2_CID_RED_BALANCE: - 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, 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, s, s->i2c_slave_id, 0x2e, 2, - data) < 0) - return -EIO; - break; - default: - return -EINVAL; - } - - switch (ctrl->id) { - case V4L2_CID_GAIN: - case V4L2_CID_RED_BALANCE: - case V4L2_CID_BLUE_BALANCE: - case SN9C102_V4L2_CID_GREEN_BALANCE: - 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) - ctrl->value -= 0x60; - else if (ctrl->value >= 0xe0 && ctrl->value <= 0xff) - ctrl->value -= 0xe0; - } - - return 0; -} - - -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; - - switch (ctrl->id) { - case V4L2_CID_GAIN: - case V4L2_CID_RED_BALANCE: - case V4L2_CID_BLUE_BALANCE: - case SN9C102_V4L2_CID_GREEN_BALANCE: - if (ctrl->value <= (0x3f-0x10)) - reg = 0x10 + ctrl->value; - else if (ctrl->value <= ((0x3f-0x10) + (0x7f-0x60))) - reg = 0x60 + (ctrl->value - (0x3f-0x10)); - else - reg = 0xe0 + (ctrl->value - (0x3f-0x10) - (0x7f-0x60)); - break; - } - - 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, reg >> 8, reg & 0xff, - 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; - case V4L2_CID_RED_BALANCE: - 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, 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, s, 4, s->i2c_slave_id, - 0x2b, reg >> 8, reg & 0xff, - 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x2e, reg >> 8, reg & 0xff, - 0, 0); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int mi0343_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) + 0, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -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, 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, s, 4, s->i2c_slave_id, - 0x0a, 0x00, 0x05, 0, 0); - err += sn9c102_write_reg(cam, 0xa0, 0x19); - } - - return err; -} - - -static const struct sn9c102_sensor mi0343 = { - .name = "MI-0343", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x5d, - .init = &mi0343_init, - .qctrl = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x06, - .flags = 0, - }, - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),/*0x6d*/ - .step = 0x01, - .default_value = 0x00, - .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_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0), - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0), - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = ((0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0)), - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - }, - .get_ctrl = &mi0343_get_ctrl, - .set_ctrl = &mi0343_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &mi0343_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &mi0343_set_pix_format -}; - - -int sn9c102_probe_mi0343(struct sn9c102_device* cam) -{ - u8 data[2]; - - 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, data) < 0) - return -EIO; - - if (data[1] != 0x42 || data[0] != 0xe3) - return -ENODEV; - - sn9c102_attach_sensor(cam, &mi0343); - - return 0; -} diff --git a/drivers/media/video/sn9c102/sn9c102_mi0360.c b/drivers/media/video/sn9c102/sn9c102_mi0360.c deleted file mode 100644 index d973fc1973d9..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_mi0360.c +++ /dev/null @@ -1,453 +0,0 @@ -/*************************************************************************** - * 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" -#include "sn9c102_devtable.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/drivers/media/video/sn9c102/sn9c102_mt9v111.c b/drivers/media/video/sn9c102/sn9c102_mt9v111.c deleted file mode 100644 index 95986eb492e4..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_mt9v111.c +++ /dev/null @@ -1,260 +0,0 @@ -/*************************************************************************** - * Plug-in for MT9V111 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" -#include "sn9c102_devtable.h" - - -static int mt9v111_init(struct sn9c102_device *cam) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - - err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02}, - {0x00, 0x03}, {0x1a, 0x04}, - {0x1f, 0x05}, {0x20, 0x06}, - {0x1f, 0x07}, {0x81, 0x08}, - {0x5c, 0x09}, {0x00, 0x0a}, - {0x00, 0x0b}, {0x00, 0x0c}, - {0x00, 0x0d}, {0x00, 0x0e}, - {0x00, 0x0f}, {0x03, 0x10}, - {0x00, 0x11}, {0x00, 0x12}, - {0x02, 0x13}, {0x14, 0x14}, - {0x28, 0x15}, {0x1e, 0x16}, - {0xe2, 0x17}, {0x06, 0x18}, - {0x00, 0x19}, {0x00, 0x1a}, - {0x00, 0x1b}, {0x08, 0x20}, - {0x39, 0x21}, {0x51, 0x22}, - {0x63, 0x23}, {0x73, 0x24}, - {0x82, 0x25}, {0x8f, 0x26}, - {0x9b, 0x27}, {0xa7, 0x28}, - {0xb1, 0x29}, {0xbc, 0x2a}, - {0xc6, 0x2b}, {0xcf, 0x2c}, - {0xd8, 0x2d}, {0xe1, 0x2e}, - {0xea, 0x2f}, {0xf2, 0x30}, - {0x13, 0x84}, {0x00, 0x85}, - {0x25, 0x86}, {0x00, 0x87}, - {0x07, 0x88}, {0x00, 0x89}, - {0xee, 0x8a}, {0x0f, 0x8b}, - {0xe5, 0x8c}, {0x0f, 0x8d}, - {0x2e, 0x8e}, {0x00, 0x8f}, - {0x30, 0x90}, {0x00, 0x91}, - {0xd4, 0x92}, {0x0f, 0x93}, - {0xfc, 0x94}, {0x0f, 0x95}, - {0x14, 0x96}, {0x00, 0x97}, - {0x00, 0x98}, {0x60, 0x99}, - {0x07, 0x9a}, {0x40, 0x9b}, - {0x20, 0x9c}, {0x00, 0x9d}, - {0x00, 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}, - {0x2d, 0xd0}, {0xdd, 0xd1}, - {0x6a, 0xd2}, {0x50, 0xd3}, - {0x60, 0xd4}, {0x00, 0xd5}, - {0x00, 0xd6}); - - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01, - 0x00, 0x01, 0, 0); - 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, 0x08, - 0x04, 0x80, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01, - 0x00, 0x04, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x08, - 0x00, 0x08, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x02, - 0x00, 0x16, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03, - 0x01, 0xe7, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04, - 0x02, 0x87, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06, - 0x00, 0x40, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05, - 0x00, 0x09, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x07, - 0x30, 0x02, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0c, - 0x00, 0x00, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x12, - 0x00, 0xb0, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x13, - 0x00, 0x7c, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x1e, - 0x00, 0x00, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20, - 0x00, 0x00, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20, - 0x00, 0x00, 0, 0); - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01, - 0x00, 0x04, 0, 0); - - return err; -} - -static int mt9v111_get_ctrl(struct sn9c102_device *cam, - struct v4l2_control *ctrl) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - u8 data[2]; - int err = 0; - - switch (ctrl->id) { - 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 err ? -EIO : 0; -} - -static int mt9v111_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_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 mt9v111_set_crop(struct sn9c102_device *cam, - const struct v4l2_rect *rect) -{ - struct sn9c102_sensor *s = sn9c102_get_sensor(cam); - int err = 0; - u8 v_start = (u8) (rect->top - s->cropcap.bounds.top) + 2; - - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - -static int mt9v111_set_pix_format(struct sn9c102_device *cam, - const struct v4l2_pix_format *pix) -{ - int err = 0; - - if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) { - err += sn9c102_write_reg(cam, 0xb4, 0x17); - } else { - err += sn9c102_write_reg(cam, 0xe2, 0x17); - } - - return err; -} - - -static const struct sn9c102_sensor mt9v111 = { - .name = "MT9V111", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x5c, - .init = &mt9v111_init, - .qctrl = { - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical mirror", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0, - .flags = 0, - }, - }, - .get_ctrl = &mt9v111_get_ctrl, - .set_ctrl = &mt9v111_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &mt9v111_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &mt9v111_set_pix_format -}; - - -int sn9c102_probe_mt9v111(struct sn9c102_device *cam) -{ - u8 data[2]; - int err = 0; - - err += sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1}, - {0x29, 0x01}, {0x42, 0x17}, - {0x62, 0x17}, {0x08, 0x01}); - err += sn9c102_i2c_try_raw_write(cam, &mt9v111, 4, - mt9v111.i2c_slave_id, 0x01, 0x00, - 0x04, 0, 0); - if (err || sn9c102_i2c_try_raw_read(cam, &mt9v111, - mt9v111.i2c_slave_id, 0x36, 2, - data) < 0) - return -EIO; - - if (data[0] != 0x82 || data[1] != 0x3a) - return -ENODEV; - - sn9c102_attach_sensor(cam, &mt9v111); - - return 0; -} diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c deleted file mode 100644 index 803712c29f02..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_ov7630.c +++ /dev/null @@ -1,626 +0,0 @@ -/*************************************************************************** - * Plug-in for OV7630 image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2006-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" -#include "sn9c102_devtable.h" - - -static int ov7630_init(struct sn9c102_device* cam) -{ - int err = 0; - - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - 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, 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); - 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); - break; - case BRIDGE_SN9C103: - 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); - err += sn9c102_i2c_write(cam, 0x15, 0x34); - 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, 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); - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03}, - {0x1a, 0x04}, {0x03, 0x10}, - {0x0a, 0x14}, {0xe2, 0x17}, - {0x0b, 0x18}, {0x00, 0x19}, - {0x1d, 0x1a}, {0x10, 0x1b}, - {0x02, 0x1c}, {0x03, 0x1d}, - {0x0f, 0x1e}, {0x0c, 0x1f}, - {0x00, 0x20}, {0x24, 0x21}, - {0x3b, 0x22}, {0x47, 0x23}, - {0x60, 0x24}, {0x71, 0x25}, - {0x80, 0x26}, {0x8f, 0x27}, - {0x9d, 0x28}, {0xaa, 0x29}, - {0xb8, 0x2a}, {0xc4, 0x2b}, - {0xd1, 0x2c}, {0xdd, 0x2d}, - {0xe8, 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}, - {0x17, 0x84}, {0x00, 0x85}, - {0x2e, 0x86}, {0x00, 0x87}, - {0x09, 0x88}, {0x00, 0x89}, - {0xe8, 0x8a}, {0x0f, 0x8b}, - {0xda, 0x8c}, {0x0f, 0x8d}, - {0x40, 0x8e}, {0x00, 0x8f}, - {0x37, 0x90}, {0x00, 0x91}, - {0xcf, 0x92}, {0x0f, 0x93}, - {0xfa, 0x94}, {0x0f, 0x95}, - {0x00, 0x96}, {0x00, 0x97}, - {0x00, 0x98}, {0x66, 0x99}, - {0x00, 0x9a}, {0x40, 0x9b}, - {0x20, 0x9c}, {0x00, 0x9d}, - {0x00, 0x9e}, {0x00, 0x9f}, - {0x2d, 0xc0}, {0x2d, 0xc1}, - {0x3a, 0xc2}, {0x00, 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}, - {0x60, 0xd4}, {0x00, 0xd5}, - {0x00, 0xd6}); - - err += sn9c102_i2c_write(cam, 0x12, 0x80); - err += sn9c102_i2c_write(cam, 0x12, 0x48); - err += sn9c102_i2c_write(cam, 0x01, 0x80); - err += sn9c102_i2c_write(cam, 0x02, 0x80); - err += sn9c102_i2c_write(cam, 0x03, 0x80); - err += sn9c102_i2c_write(cam, 0x04, 0x10); - err += sn9c102_i2c_write(cam, 0x05, 0x20); - err += sn9c102_i2c_write(cam, 0x06, 0x80); - err += sn9c102_i2c_write(cam, 0x11, 0x00); - err += sn9c102_i2c_write(cam, 0x0c, 0x20); - err += sn9c102_i2c_write(cam, 0x0d, 0x20); - err += sn9c102_i2c_write(cam, 0x15, 0x80); - err += sn9c102_i2c_write(cam, 0x16, 0x03); - err += sn9c102_i2c_write(cam, 0x17, 0x1b); - err += sn9c102_i2c_write(cam, 0x18, 0xbd); - err += sn9c102_i2c_write(cam, 0x19, 0x05); - err += sn9c102_i2c_write(cam, 0x1a, 0xf6); - err += sn9c102_i2c_write(cam, 0x1b, 0x04); - err += sn9c102_i2c_write(cam, 0x21, 0x1b); - err += sn9c102_i2c_write(cam, 0x22, 0x00); - err += sn9c102_i2c_write(cam, 0x23, 0xde); - err += sn9c102_i2c_write(cam, 0x24, 0x10); - err += sn9c102_i2c_write(cam, 0x25, 0x8a); - err += sn9c102_i2c_write(cam, 0x26, 0xa0); - err += sn9c102_i2c_write(cam, 0x27, 0xca); - err += sn9c102_i2c_write(cam, 0x28, 0xa2); - err += sn9c102_i2c_write(cam, 0x29, 0x74); - err += sn9c102_i2c_write(cam, 0x2a, 0x88); - err += sn9c102_i2c_write(cam, 0x2b, 0x34); - err += sn9c102_i2c_write(cam, 0x2c, 0x88); - err += sn9c102_i2c_write(cam, 0x2e, 0x00); - err += sn9c102_i2c_write(cam, 0x2f, 0x00); - err += sn9c102_i2c_write(cam, 0x30, 0x00); - err += sn9c102_i2c_write(cam, 0x32, 0xc2); - err += sn9c102_i2c_write(cam, 0x33, 0x08); - err += sn9c102_i2c_write(cam, 0x4c, 0x40); - err += sn9c102_i2c_write(cam, 0x4d, 0xf3); - err += sn9c102_i2c_write(cam, 0x60, 0x05); - err += sn9c102_i2c_write(cam, 0x61, 0x40); - err += sn9c102_i2c_write(cam, 0x62, 0x12); - err += sn9c102_i2c_write(cam, 0x63, 0x57); - err += sn9c102_i2c_write(cam, 0x64, 0x73); - err += sn9c102_i2c_write(cam, 0x65, 0x00); - err += sn9c102_i2c_write(cam, 0x66, 0x55); - err += sn9c102_i2c_write(cam, 0x67, 0x01); - err += sn9c102_i2c_write(cam, 0x68, 0xac); - err += sn9c102_i2c_write(cam, 0x69, 0x38); - err += sn9c102_i2c_write(cam, 0x6f, 0x1f); - err += sn9c102_i2c_write(cam, 0x70, 0x01); - err += sn9c102_i2c_write(cam, 0x71, 0x00); - err += sn9c102_i2c_write(cam, 0x72, 0x10); - err += sn9c102_i2c_write(cam, 0x73, 0x50); - err += sn9c102_i2c_write(cam, 0x74, 0x20); - err += sn9c102_i2c_write(cam, 0x76, 0x01); - err += sn9c102_i2c_write(cam, 0x77, 0xf3); - err += sn9c102_i2c_write(cam, 0x78, 0x90); - err += sn9c102_i2c_write(cam, 0x79, 0x98); - err += sn9c102_i2c_write(cam, 0x7a, 0x98); - err += sn9c102_i2c_write(cam, 0x7b, 0x00); - err += sn9c102_i2c_write(cam, 0x7c, 0x38); - err += sn9c102_i2c_write(cam, 0x7d, 0xff); - break; - default: - break; - } - - return err; -} - - -static int ov7630_get_ctrl(struct sn9c102_device* cam, - struct v4l2_control* ctrl) -{ - enum sn9c102_bridge bridge = sn9c102_get_bridge(cam); - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0) - return -EIO; - break; - case V4L2_CID_RED_BALANCE: - if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120) - ctrl->value = sn9c102_pread_reg(cam, 0x05); - else - ctrl->value = sn9c102_pread_reg(cam, 0x07); - break; - case V4L2_CID_BLUE_BALANCE: - ctrl->value = sn9c102_pread_reg(cam, 0x06); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120) - ctrl->value = sn9c102_pread_reg(cam, 0x07); - else - ctrl->value = sn9c102_pread_reg(cam, 0x05); - break; - break; - case V4L2_CID_GAIN: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0) - return -EIO; - ctrl->value &= 0x3f; - break; - case V4L2_CID_DO_WHITE_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0) - return -EIO; - ctrl->value &= 0x3f; - break; - case V4L2_CID_WHITENESS: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x0d)) < 0) - return -EIO; - ctrl->value &= 0x3f; - break; - case V4L2_CID_AUTOGAIN: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0) - return -EIO; - ctrl->value &= 0x01; - break; - case V4L2_CID_VFLIP: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x75)) < 0) - return -EIO; - ctrl->value = (ctrl->value & 0x80) ? 1 : 0; - break; - case SN9C102_V4L2_CID_GAMMA: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x14)) < 0) - return -EIO; - ctrl->value = (ctrl->value & 0x02) ? 1 : 0; - break; - case SN9C102_V4L2_CID_BAND_FILTER: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x2d)) < 0) - return -EIO; - ctrl->value = (ctrl->value & 0x02) ? 1 : 0; - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int ov7630_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) -{ - enum sn9c102_bridge bridge = sn9c102_get_bridge(cam); - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x10, ctrl->value); - break; - case V4L2_CID_RED_BALANCE: - if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120) - err += sn9c102_write_reg(cam, ctrl->value, 0x05); - else - err += sn9c102_write_reg(cam, ctrl->value, 0x07); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_write_reg(cam, ctrl->value, 0x06); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120) - err += sn9c102_write_reg(cam, ctrl->value, 0x07); - else - err += sn9c102_write_reg(cam, ctrl->value, 0x05); - break; - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x00, ctrl->value); - break; - case V4L2_CID_DO_WHITE_BALANCE: - err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); - break; - case V4L2_CID_WHITENESS: - err += sn9c102_i2c_write(cam, 0x0d, ctrl->value); - break; - case V4L2_CID_AUTOGAIN: - err += sn9c102_i2c_write(cam, 0x13, ctrl->value | - (ctrl->value << 1)); - break; - case V4L2_CID_VFLIP: - err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7)); - break; - case SN9C102_V4L2_CID_GAMMA: - err += sn9c102_i2c_write(cam, 0x14, ctrl->value << 2); - break; - case SN9C102_V4L2_CID_BAND_FILTER: - err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int ov7630_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_SN9C101: - case BRIDGE_SN9C102: - case BRIDGE_SN9C103: - h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1; - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4; - break; - default: - break; - } - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static int ov7630_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) -{ - int err = 0; - - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - case BRIDGE_SN9C103: - if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) - err += sn9c102_write_reg(cam, 0x50, 0x19); - else - err += sn9c102_write_reg(cam, 0x20, 0x19); - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) { - err += sn9c102_write_reg(cam, 0xe5, 0x17); - err += sn9c102_i2c_write(cam, 0x11, 0x04); - } else { - err += sn9c102_write_reg(cam, 0xe2, 0x17); - err += sn9c102_i2c_write(cam, 0x11, 0x02); - } - break; - default: - break; - } - - return err; -} - - -static const struct sn9c102_sensor ov7630 = { - .name = "OV7630", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | 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 = 0x21, - .init = &ov7630_init, - .qctrl = { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x14, - .flags = 0, - }, - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = 0x60, - .flags = 0, - }, - { - .id = V4L2_CID_WHITENESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "white balance background: red", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x20, - .flags = 0, - }, - { - .id = V4L2_CID_DO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "white balance background: blue", - .minimum = 0x00, - .maximum = 0x3f, - .step = 0x01, - .default_value = 0x20, - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x7f, - .step = 0x01, - .default_value = 0x20, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x7f, - .step = 0x01, - .default_value = 0x20, - .flags = 0, - }, - { - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto adjust", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_VFLIP, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "vertical flip", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x01, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x7f, - .step = 0x01, - .default_value = 0x20, - .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, - }, - { - .id = SN9C102_V4L2_CID_GAMMA, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "rgb gamma", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - }, - .get_ctrl = &ov7630_get_ctrl, - .set_ctrl = &ov7630_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &ov7630_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SN9C10X, - .priv = 8, - }, - .set_pix_format = &ov7630_set_pix_format -}; - - -int sn9c102_probe_ov7630(struct sn9c102_device* cam) -{ - int pid, ver, err = 0; - - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, - {0x28, 0x17}); - break; - case BRIDGE_SN9C103: /* do _not_ change anything! */ - 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_const_regs(cam, {0x01, 0x01}, - {0x00, 0x01}); - break; - case BRIDGE_SN9C105: - case BRIDGE_SN9C120: - err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1}, - {0x29, 0x01}, {0x74, 0x02}, - {0x0e, 0x01}, {0x44, 0x01}); - break; - default: - break; - } - - pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a); - ver = sn9c102_i2c_try_read(cam, &ov7630, 0x0b); - if (err || pid < 0 || ver < 0) - return -EIO; - if (pid != 0x76 || ver != 0x31) - return -ENODEV; - sn9c102_attach_sensor(cam, &ov7630); - - return 0; -} diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c deleted file mode 100644 index 7977795d342b..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_ov7660.c +++ /dev/null @@ -1,538 +0,0 @@ -/*************************************************************************** - * Plug-in for OV7660 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" -#include "sn9c102_devtable.h" - - -static int ov7660_init(struct sn9c102_device* cam) -{ - int err = 0; - - 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, 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); - err += sn9c102_i2c_write(cam, 0x06, 0x0B); - err += sn9c102_i2c_write(cam, 0x07, 0x00); - err += sn9c102_i2c_write(cam, 0x08, 0x1C); - err += sn9c102_i2c_write(cam, 0x09, 0x01); - err += sn9c102_i2c_write(cam, 0x0A, 0x76); - err += sn9c102_i2c_write(cam, 0x0B, 0x60); - err += sn9c102_i2c_write(cam, 0x0C, 0x00); - err += sn9c102_i2c_write(cam, 0x0D, 0x08); - err += sn9c102_i2c_write(cam, 0x0E, 0x04); - err += sn9c102_i2c_write(cam, 0x0F, 0x6F); - 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, 0xC7); - err += sn9c102_i2c_write(cam, 0x14, 0x2C); - err += sn9c102_i2c_write(cam, 0x15, 0x00); - err += sn9c102_i2c_write(cam, 0x16, 0x02); - err += sn9c102_i2c_write(cam, 0x17, 0x10); - err += sn9c102_i2c_write(cam, 0x18, 0x60); - err += sn9c102_i2c_write(cam, 0x19, 0x02); - err += sn9c102_i2c_write(cam, 0x1A, 0x7B); - err += sn9c102_i2c_write(cam, 0x1B, 0x02); - err += sn9c102_i2c_write(cam, 0x1C, 0x7F); - err += sn9c102_i2c_write(cam, 0x1D, 0xA2); - err += sn9c102_i2c_write(cam, 0x1E, 0x01); - err += sn9c102_i2c_write(cam, 0x1F, 0x0E); - err += sn9c102_i2c_write(cam, 0x20, 0x05); - err += sn9c102_i2c_write(cam, 0x21, 0x05); - err += sn9c102_i2c_write(cam, 0x22, 0x05); - err += sn9c102_i2c_write(cam, 0x23, 0x05); - err += sn9c102_i2c_write(cam, 0x24, 0x68); - err += sn9c102_i2c_write(cam, 0x25, 0x58); - err += sn9c102_i2c_write(cam, 0x26, 0xD4); - err += sn9c102_i2c_write(cam, 0x27, 0x80); - err += sn9c102_i2c_write(cam, 0x28, 0x80); - err += sn9c102_i2c_write(cam, 0x29, 0x30); - err += sn9c102_i2c_write(cam, 0x2A, 0x00); - err += sn9c102_i2c_write(cam, 0x2B, 0x00); - err += sn9c102_i2c_write(cam, 0x2C, 0x80); - err += sn9c102_i2c_write(cam, 0x2D, 0x00); - err += sn9c102_i2c_write(cam, 0x2E, 0x00); - err += sn9c102_i2c_write(cam, 0x2F, 0x0E); - err += sn9c102_i2c_write(cam, 0x30, 0x08); - err += sn9c102_i2c_write(cam, 0x31, 0x30); - err += sn9c102_i2c_write(cam, 0x32, 0xB4); - err += sn9c102_i2c_write(cam, 0x33, 0x00); - err += sn9c102_i2c_write(cam, 0x34, 0x07); - err += sn9c102_i2c_write(cam, 0x35, 0x84); - err += sn9c102_i2c_write(cam, 0x36, 0x00); - err += sn9c102_i2c_write(cam, 0x37, 0x0C); - 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, 0x0A); - err += sn9c102_i2c_write(cam, 0x3C, 0x6C); - err += sn9c102_i2c_write(cam, 0x3D, 0x99); - err += sn9c102_i2c_write(cam, 0x3E, 0x0E); - err += sn9c102_i2c_write(cam, 0x3F, 0x41); - err += sn9c102_i2c_write(cam, 0x40, 0xC1); - err += sn9c102_i2c_write(cam, 0x41, 0x22); - err += sn9c102_i2c_write(cam, 0x42, 0x08); - err += sn9c102_i2c_write(cam, 0x43, 0xF0); - err += sn9c102_i2c_write(cam, 0x44, 0x10); - err += sn9c102_i2c_write(cam, 0x45, 0x78); - err += sn9c102_i2c_write(cam, 0x46, 0xA8); - err += sn9c102_i2c_write(cam, 0x47, 0x60); - err += sn9c102_i2c_write(cam, 0x48, 0x80); - err += sn9c102_i2c_write(cam, 0x49, 0x00); - err += sn9c102_i2c_write(cam, 0x4A, 0x00); - err += sn9c102_i2c_write(cam, 0x4B, 0x00); - err += sn9c102_i2c_write(cam, 0x4C, 0x00); - err += sn9c102_i2c_write(cam, 0x4D, 0x00); - err += sn9c102_i2c_write(cam, 0x4E, 0x00); - err += sn9c102_i2c_write(cam, 0x4F, 0x46); - err += sn9c102_i2c_write(cam, 0x50, 0x36); - err += sn9c102_i2c_write(cam, 0x51, 0x0F); - err += sn9c102_i2c_write(cam, 0x52, 0x17); - err += sn9c102_i2c_write(cam, 0x53, 0x7F); - err += sn9c102_i2c_write(cam, 0x54, 0x96); - err += sn9c102_i2c_write(cam, 0x55, 0x40); - err += sn9c102_i2c_write(cam, 0x56, 0x40); - err += sn9c102_i2c_write(cam, 0x57, 0x40); - err += sn9c102_i2c_write(cam, 0x58, 0x0F); - err += sn9c102_i2c_write(cam, 0x59, 0xBA); - err += sn9c102_i2c_write(cam, 0x5A, 0x9A); - err += sn9c102_i2c_write(cam, 0x5B, 0x22); - err += sn9c102_i2c_write(cam, 0x5C, 0xB9); - err += sn9c102_i2c_write(cam, 0x5D, 0x9B); - err += sn9c102_i2c_write(cam, 0x5E, 0x10); - err += sn9c102_i2c_write(cam, 0x5F, 0xF0); - err += sn9c102_i2c_write(cam, 0x60, 0x05); - err += sn9c102_i2c_write(cam, 0x61, 0x60); - err += sn9c102_i2c_write(cam, 0x62, 0x00); - err += sn9c102_i2c_write(cam, 0x63, 0x00); - err += sn9c102_i2c_write(cam, 0x64, 0x50); - err += sn9c102_i2c_write(cam, 0x65, 0x30); - err += sn9c102_i2c_write(cam, 0x66, 0x00); - err += sn9c102_i2c_write(cam, 0x67, 0x80); - err += sn9c102_i2c_write(cam, 0x68, 0x7A); - err += sn9c102_i2c_write(cam, 0x69, 0x90); - err += sn9c102_i2c_write(cam, 0x6A, 0x80); - err += sn9c102_i2c_write(cam, 0x6B, 0x0A); - err += sn9c102_i2c_write(cam, 0x6C, 0x30); - err += sn9c102_i2c_write(cam, 0x6D, 0x48); - err += sn9c102_i2c_write(cam, 0x6E, 0x80); - err += sn9c102_i2c_write(cam, 0x6F, 0x74); - err += sn9c102_i2c_write(cam, 0x70, 0x64); - err += sn9c102_i2c_write(cam, 0x71, 0x60); - err += sn9c102_i2c_write(cam, 0x72, 0x5C); - err += sn9c102_i2c_write(cam, 0x73, 0x58); - err += sn9c102_i2c_write(cam, 0x74, 0x54); - err += sn9c102_i2c_write(cam, 0x75, 0x4C); - err += sn9c102_i2c_write(cam, 0x76, 0x40); - err += sn9c102_i2c_write(cam, 0x77, 0x38); - err += sn9c102_i2c_write(cam, 0x78, 0x34); - err += sn9c102_i2c_write(cam, 0x79, 0x30); - err += sn9c102_i2c_write(cam, 0x7A, 0x2F); - err += sn9c102_i2c_write(cam, 0x7B, 0x2B); - err += sn9c102_i2c_write(cam, 0x7C, 0x03); - err += sn9c102_i2c_write(cam, 0x7D, 0x07); - err += sn9c102_i2c_write(cam, 0x7E, 0x17); - err += sn9c102_i2c_write(cam, 0x7F, 0x34); - err += sn9c102_i2c_write(cam, 0x80, 0x41); - err += sn9c102_i2c_write(cam, 0x81, 0x4D); - err += sn9c102_i2c_write(cam, 0x82, 0x58); - err += sn9c102_i2c_write(cam, 0x83, 0x63); - err += sn9c102_i2c_write(cam, 0x84, 0x6E); - err += sn9c102_i2c_write(cam, 0x85, 0x77); - err += sn9c102_i2c_write(cam, 0x86, 0x87); - err += sn9c102_i2c_write(cam, 0x87, 0x95); - err += sn9c102_i2c_write(cam, 0x88, 0xAF); - err += sn9c102_i2c_write(cam, 0x89, 0xC7); - err += sn9c102_i2c_write(cam, 0x8A, 0xDF); - err += sn9c102_i2c_write(cam, 0x8B, 0x99); - err += sn9c102_i2c_write(cam, 0x8C, 0x99); - err += sn9c102_i2c_write(cam, 0x8D, 0xCF); - err += sn9c102_i2c_write(cam, 0x8E, 0x20); - err += sn9c102_i2c_write(cam, 0x8F, 0x26); - err += sn9c102_i2c_write(cam, 0x90, 0x10); - err += sn9c102_i2c_write(cam, 0x91, 0x0C); - err += sn9c102_i2c_write(cam, 0x92, 0x25); - err += sn9c102_i2c_write(cam, 0x93, 0x00); - err += sn9c102_i2c_write(cam, 0x94, 0x50); - err += sn9c102_i2c_write(cam, 0x95, 0x50); - err += sn9c102_i2c_write(cam, 0x96, 0x00); - err += sn9c102_i2c_write(cam, 0x97, 0x01); - err += sn9c102_i2c_write(cam, 0x98, 0x10); - err += sn9c102_i2c_write(cam, 0x99, 0x40); - err += sn9c102_i2c_write(cam, 0x9A, 0x40); - err += sn9c102_i2c_write(cam, 0x9B, 0x20); - err += sn9c102_i2c_write(cam, 0x9C, 0x00); - err += sn9c102_i2c_write(cam, 0x9D, 0x99); - err += sn9c102_i2c_write(cam, 0x9E, 0x7F); - err += sn9c102_i2c_write(cam, 0x9F, 0x00); - err += sn9c102_i2c_write(cam, 0xA0, 0x00); - err += sn9c102_i2c_write(cam, 0xA1, 0x00); - - return err; -} - - -static int ov7660_get_ctrl(struct sn9c102_device* cam, - struct v4l2_control* ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0) - return -EIO; - break; - case V4L2_CID_DO_WHITE_BALANCE: - if ((ctrl->value = sn9c102_read_reg(cam, 0x02)) < 0) - return -EIO; - ctrl->value = (ctrl->value & 0x04) ? 1 : 0; - break; - case V4L2_CID_RED_BALANCE: - if ((ctrl->value = sn9c102_read_reg(cam, 0x05)) < 0) - return -EIO; - ctrl->value &= 0x7f; - break; - case V4L2_CID_BLUE_BALANCE: - if ((ctrl->value = sn9c102_read_reg(cam, 0x06)) < 0) - return -EIO; - ctrl->value &= 0x7f; - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - 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 &= 0x1f; - break; - case V4L2_CID_AUTOGAIN: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0) - return -EIO; - ctrl->value &= 0x01; - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int ov7660_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x10, ctrl->value); - break; - case V4L2_CID_DO_WHITE_BALANCE: - err += sn9c102_write_reg(cam, 0x43 | (ctrl->value << 2), 0x02); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_write_reg(cam, ctrl->value, 0x05); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_write_reg(cam, ctrl->value, 0x06); - break; - 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, 0x60 + ctrl->value); - break; - case V4L2_CID_AUTOGAIN: - err += sn9c102_i2c_write(cam, 0x13, 0xc0 | - (ctrl->value * 0x07)); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int ov7660_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 ov7660_set_pix_format(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix) -{ - int r0, err = 0; - - r0 = sn9c102_pread_reg(cam, 0x01); - - if (pix->pixelformat == V4L2_PIX_FMT_JPEG) { - err += sn9c102_write_reg(cam, r0 | 0x40, 0x01); - err += sn9c102_write_reg(cam, 0xa2, 0x17); - err += sn9c102_i2c_write(cam, 0x11, 0x00); - } else { - err += sn9c102_write_reg(cam, r0 | 0x40, 0x01); - err += sn9c102_write_reg(cam, 0xa2, 0x17); - err += sn9c102_i2c_write(cam, 0x11, 0x0d); - } - - return err; -} - - -static const struct sn9c102_sensor ov7660 = { - .name = "OV7660", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120, - .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x21, - .init = &ov7660_init, - .qctrl = { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x09, - .flags = 0, - }, - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = 0x27, - .flags = 0, - }, - { - .id = V4L2_CID_DO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "night mode", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x7f, - .step = 0x01, - .default_value = 0x14, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x7f, - .step = 0x01, - .default_value = 0x14, - .flags = 0, - }, - { - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "auto adjust", - .minimum = 0x00, - .maximum = 0x01, - .step = 0x01, - .default_value = 0x01, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x7f, - .step = 0x01, - .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, - }, - }, - .get_ctrl = &ov7660_get_ctrl, - .set_ctrl = &ov7660_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &ov7660_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_JPEG, - .priv = 8, - }, - .set_pix_format = &ov7660_set_pix_format -}; - - -int sn9c102_probe_ov7660(struct sn9c102_device* cam) -{ - int pid, ver, err; - - 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); - if (err || pid < 0 || ver < 0) - return -EIO; - if (pid != 0x76 || ver != 0x60) - return -ENODEV; - - sn9c102_attach_sensor(cam, &ov7660); - - return 0; -} diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c deleted file mode 100644 index 81cd969c1b7b..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_pas106b.c +++ /dev/null @@ -1,302 +0,0 @@ -/*************************************************************************** - * Plug-in for PAS106B image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2004-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 <linux/delay.h> -#include "sn9c102_sensor.h" -#include "sn9c102_devtable.h" - - -static int pas106b_init(struct sn9c102_device* cam) -{ - int err = 0; - - 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); - err += sn9c102_i2c_write(cam, 0x06, 0x88); - err += sn9c102_i2c_write(cam, 0x07, 0x80); - err += sn9c102_i2c_write(cam, 0x10, 0x06); - err += sn9c102_i2c_write(cam, 0x11, 0x06); - err += sn9c102_i2c_write(cam, 0x12, 0x00); - err += sn9c102_i2c_write(cam, 0x14, 0x02); - err += sn9c102_i2c_write(cam, 0x13, 0x01); - - msleep(400); - - return err; -} - - -static int pas106b_get_ctrl(struct sn9c102_device* cam, - struct v4l2_control* ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - { - int r1 = sn9c102_i2c_read(cam, 0x03), - r2 = sn9c102_i2c_read(cam, 0x04); - if (r1 < 0 || r2 < 0) - return -EIO; - ctrl->value = (r1 << 4) | (r2 & 0x0f); - } - return 0; - case V4L2_CID_RED_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0) - return -EIO; - ctrl->value &= 0x1f; - return 0; - case V4L2_CID_BLUE_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0) - return -EIO; - ctrl->value &= 0x1f; - return 0; - case V4L2_CID_GAIN: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x0e)) < 0) - return -EIO; - ctrl->value &= 0x1f; - return 0; - case V4L2_CID_CONTRAST: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x0f)) < 0) - return -EIO; - ctrl->value &= 0x07; - return 0; - case SN9C102_V4L2_CID_GREEN_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x0a)) < 0) - return -EIO; - ctrl->value = (ctrl->value & 0x1f) << 1; - return 0; - case SN9C102_V4L2_CID_DAC_MAGNITUDE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0) - return -EIO; - ctrl->value &= 0xf8; - return 0; - default: - return -EINVAL; - } -} - - -static int pas106b_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x03, ctrl->value >> 4); - err += sn9c102_i2c_write(cam, 0x04, ctrl->value & 0x0f); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_write(cam, 0x09, ctrl->value); - break; - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x0e, ctrl->value); - break; - case V4L2_CID_CONTRAST: - err += sn9c102_i2c_write(cam, 0x0f, ctrl->value); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_i2c_write(cam, 0x0a, ctrl->value >> 1); - err += sn9c102_i2c_write(cam, 0x0b, ctrl->value >> 1); - break; - case SN9C102_V4L2_CID_DAC_MAGNITUDE: - err += sn9c102_i2c_write(cam, 0x08, ctrl->value << 3); - break; - default: - return -EINVAL; - } - err += sn9c102_i2c_write(cam, 0x13, 0x01); - - return err ? -EIO : 0; -} - - -static int pas106b_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) + 4, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static int pas106b_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, 0x2c, 0x17); - else - err += sn9c102_write_reg(cam, 0x20, 0x17); - - return err; -} - - -static const struct sn9c102_sensor pas106b = { - .name = "PAS106B", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .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, - .i2c_slave_id = 0x40, - .init = &pas106b_init, - .qctrl = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x125, - .maximum = 0xfff, - .step = 0x001, - .default_value = 0x140, - .flags = 0, - }, - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x0d, - .flags = 0, - }, - { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "contrast", - .minimum = 0x00, - .maximum = 0x07, - .step = 0x01, - .default_value = 0x00, /* 0x00~0x03 have same effect */ - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x04, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x06, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x3e, - .step = 0x02, - .default_value = 0x02, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "DAC magnitude", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x01, - .flags = 0, - }, - }, - .get_ctrl = &pas106b_get_ctrl, - .set_ctrl = &pas106b_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 352, - .height = 288, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 352, - .height = 288, - }, - }, - .set_crop = &pas106b_set_crop, - .pix_format = { - .width = 352, - .height = 288, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, /* we use this field as 'bits per pixel' */ - }, - .set_pix_format = &pas106b_set_pix_format -}; - - -int sn9c102_probe_pas106b(struct sn9c102_device* cam) -{ - int r0 = 0, r1 = 0; - unsigned int pid = 0; - - /* - Minimal initialization to enable the I2C communication - NOTE: do NOT change the values! - */ - 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; - - pid = (r0 << 11) | ((r1 & 0xf0) >> 4); - if (pid != 0x007) - return -ENODEV; - - sn9c102_attach_sensor(cam, &pas106b); - - return 0; -} diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c deleted file mode 100644 index 2e86fdc86989..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c +++ /dev/null @@ -1,335 +0,0 @@ -/*************************************************************************** - * Plug-in for PAS202BCB image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio * - * <medaglia@undl.org.br> * - * * - * Support for SN9C103, DAC Magnitude, exposure and green gain controls * - * added 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 <linux/delay.h> -#include "sn9c102_sensor.h" -#include "sn9c102_devtable.h" - - -static int pas202bcb_init(struct sn9c102_device* cam) -{ - int err = 0; - - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - 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_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; - } - - err += sn9c102_i2c_write(cam, 0x02, 0x14); - err += sn9c102_i2c_write(cam, 0x03, 0x40); - err += sn9c102_i2c_write(cam, 0x0d, 0x2c); - err += sn9c102_i2c_write(cam, 0x0e, 0x01); - err += sn9c102_i2c_write(cam, 0x0f, 0xa9); - err += sn9c102_i2c_write(cam, 0x10, 0x08); - err += sn9c102_i2c_write(cam, 0x13, 0x63); - err += sn9c102_i2c_write(cam, 0x15, 0x70); - err += sn9c102_i2c_write(cam, 0x11, 0x01); - - msleep(400); - - return err; -} - - -static int pas202bcb_get_ctrl(struct sn9c102_device* cam, - struct v4l2_control* ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - { - int r1 = sn9c102_i2c_read(cam, 0x04), - r2 = sn9c102_i2c_read(cam, 0x05); - if (r1 < 0 || r2 < 0) - return -EIO; - ctrl->value = (r1 << 6) | (r2 & 0x3f); - } - return 0; - case V4L2_CID_RED_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0) - return -EIO; - ctrl->value &= 0x0f; - return 0; - case V4L2_CID_BLUE_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x07)) < 0) - return -EIO; - ctrl->value &= 0x0f; - return 0; - case V4L2_CID_GAIN: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0) - return -EIO; - ctrl->value &= 0x1f; - return 0; - case SN9C102_V4L2_CID_GREEN_BALANCE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0) - return -EIO; - ctrl->value &= 0x0f; - return 0; - case SN9C102_V4L2_CID_DAC_MAGNITUDE: - if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0) - return -EIO; - return 0; - default: - return -EINVAL; - } -} - - -static int pas202bcb_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, 0x28, 0x17); - else - err += sn9c102_write_reg(cam, 0x20, 0x17); - - return err; -} - - -static int pas202bcb_set_ctrl(struct sn9c102_device* cam, - const struct v4l2_control* ctrl) -{ - int err = 0; - - switch (ctrl->id) { - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6); - err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f); - break; - case V4L2_CID_RED_BALANCE: - err += sn9c102_i2c_write(cam, 0x09, ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: - err += sn9c102_i2c_write(cam, 0x07, ctrl->value); - break; - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x10, ctrl->value); - break; - case SN9C102_V4L2_CID_GREEN_BALANCE: - err += sn9c102_i2c_write(cam, 0x08, ctrl->value); - break; - case SN9C102_V4L2_CID_DAC_MAGNITUDE: - err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); - break; - default: - return -EINVAL; - } - err += sn9c102_i2c_write(cam, 0x11, 0x01); - - return err ? -EIO : 0; -} - - -static int pas202bcb_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) + 3; - - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4; - break; - case BRIDGE_SN9C103: - h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3; - break; - default: - break; - } - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - return err; -} - - -static const struct sn9c102_sensor pas202bcb = { - .name = "PAS202BCB", - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, - .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, - .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, - .interface = SN9C102_I2C_2WIRES, - .i2c_slave_id = 0x40, - .init = &pas202bcb_init, - .qctrl = { - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x01e5, - .maximum = 0x3fff, - .step = 0x0001, - .default_value = 0x01e5, - .flags = 0, - }, - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x0b, - .flags = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "red balance", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "blue balance", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x05, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_GREEN_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "green balance", - .minimum = 0x00, - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - { - .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "DAC magnitude", - .minimum = 0x00, - .maximum = 0xff, - .step = 0x01, - .default_value = 0x04, - .flags = 0, - }, - }, - .get_ctrl = &pas202bcb_get_ctrl, - .set_ctrl = &pas202bcb_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &pas202bcb_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &pas202bcb_set_pix_format -}; - - -int sn9c102_probe_pas202bcb(struct sn9c102_device* cam) -{ - int r0 = 0, r1 = 0, err = 0; - unsigned int pid = 0; - - /* - * Minimal initialization to enable the I2C communication - * NOTE: do NOT change the values! - */ - switch (sn9c102_get_bridge(cam)) { - case BRIDGE_SN9C101: - case BRIDGE_SN9C102: - 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_const_regs(cam, {0x09, 0x01}, {0x44, 0x01}, - {0x44, 0x02}, {0x29, 0x17}); - break; - default: - break; - } - - r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00); - r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01); - - if (err || r0 < 0 || r1 < 0) - return -EIO; - - pid = (r0 << 4) | ((r1 & 0xf0) >> 4); - if (pid != 0x017) - return -ENODEV; - - sn9c102_attach_sensor(cam, &pas202bcb); - - return 0; -} diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h deleted file mode 100644 index 3679970dba2c..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_sensor.h +++ /dev/null @@ -1,307 +0,0 @@ -/*************************************************************************** - * API for image sensors connected to the SN9C1xx PC Camera Controllers * - * * - * Copyright (C) 2004-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. * - ***************************************************************************/ - -#ifndef _SN9C102_SENSOR_H_ -#define _SN9C102_SENSOR_H_ - -#include <linux/usb.h> -#include <linux/videodev2.h> -#include <linux/device.h> -#include <linux/stddef.h> -#include <linux/errno.h> -#include <asm/types.h> - -struct sn9c102_device; -struct sn9c102_sensor; - -/*****************************************************************************/ - -/* - OVERVIEW. - This is a small interface that allows you to add support for any CCD/CMOS - image sensors connected to the SN9C1XX bridges. The entire API is documented - below. In the most general case, to support a sensor there are three steps - you have to follow: - 1) define the main "sn9c102_sensor" structure by setting the basic fields; - 2) write a probing function to be called by the core module when the USB - camera is recognized, then add both the USB ids and the name of that - function to the two corresponding tables in sn9c102_devtable.h; - 3) implement the methods that you want/need (and fill the rest of the main - structure accordingly). - "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do - NOT need to touch the source code of the core module for the things to work - properly, unless you find bugs or flaws in it. Finally, do not forget to - read the V4L2 API for completeness. -*/ - -/*****************************************************************************/ - -enum sn9c102_bridge { - BRIDGE_SN9C101 = 0x01, - BRIDGE_SN9C102 = 0x02, - BRIDGE_SN9C103 = 0x04, - BRIDGE_SN9C105 = 0x08, - BRIDGE_SN9C120 = 0x10, -}; - -/* Return the bridge name */ -enum sn9c102_bridge sn9c102_get_bridge(struct sn9c102_device* cam); - -/* Return a pointer the sensor struct attached to the camera */ -struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam); - -/* Identify a device */ -extern struct sn9c102_device* -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, - const struct sn9c102_sensor* sensor); - -/* - Read/write routines: they always return -1 on error, 0 or the read value - otherwise. NOTE that a real read operation is not supported by the SN9C1XX - chip for some of its registers. To work around this problem, a pseudo-read - call is provided instead: it returns the last successfully written value - on the register (0 if it has never been written), the usual -1 on error. -*/ - -/* The "try" I2C I/O versions are used when probing the sensor */ -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 - I2C protocol. There are a number of good reasons why you must use the - single-byte versions of these functions: do not abuse. The first function - writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C1XX - chip. The second one programs the registers 0x09 and 0x10 with data0 and - data1, and places the n bytes read from the sensor register table in the - buffer pointed by 'buffer'. Both the functions return -1 on error; the write - version returns 0 on success, while the read version returns the first read - byte. -*/ -extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, - 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, - 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_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 addresses must be < 256. -*/ -#define sn9c102_write_const_regs(sn9c102_device, data...) \ - ({ static const u8 _valreg[][2] = {data}; \ - sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); }) - -/*****************************************************************************/ - -enum sn9c102_i2c_sysfs_ops { - SN9C102_I2C_READ = 0x01, - SN9C102_I2C_WRITE = 0x02, -}; - -enum sn9c102_i2c_frequency { /* sensors may support both the frequencies */ - SN9C102_I2C_100KHZ = 0x01, - SN9C102_I2C_400KHZ = 0x02, -}; - -enum sn9c102_i2c_interface { - SN9C102_I2C_2WIRES, - SN9C102_I2C_3WIRES, -}; - -#define SN9C102_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10) - -struct sn9c102_sensor { - char name[32], /* sensor name */ - maintainer[64]; /* name of the maintainer <email> */ - - enum sn9c102_bridge supported_bridge; /* supported SN9C1xx bridges */ - - /* Supported operations through the 'sysfs' interface */ - enum sn9c102_i2c_sysfs_ops sysfs_ops; - - /* - These sensor capabilities must be provided if the SN9C1XX controller - needs to communicate through the sensor serial interface by using - at least one of the i2c functions available. - */ - enum sn9c102_i2c_frequency frequency; - enum sn9c102_i2c_interface interface; - - /* - This identifier must be provided if the image sensor implements - the standard I2C protocol. - */ - u8 i2c_slave_id; /* reg. 0x09 */ - - /* - NOTE: Where not noted,most of the functions below are not mandatory. - Set to null if you do not implement them. If implemented, - they must return 0 on success, the proper error otherwise. - */ - - int (*init)(struct sn9c102_device* cam); - /* - This function will be called after the sensor has been attached. - It should be used to initialize the sensor only, but may also - configure part of the SN9C1XX chip if necessary. You don't need to - setup picture settings like brightness, contrast, etc.. here, if - the corresponding controls are implemented (see below), since - they are adjusted in the core driver by calling the set_ctrl() - method after init(), where the arguments are the default values - specified in the v4l2_queryctrl list of supported controls; - Same suggestions apply for other settings, _if_ the corresponding - methods are present; if not, the initialization must configure the - sensor according to the default configuration structures below. - */ - - struct v4l2_queryctrl qctrl[SN9C102_MAX_CTRLS]; - /* - Optional list of default controls, defined as indicated in the - V4L2 API. Menu type controls are not handled by this interface. - */ - - int (*get_ctrl)(struct sn9c102_device* cam, struct v4l2_control* ctrl); - int (*set_ctrl)(struct sn9c102_device* cam, - const struct v4l2_control* ctrl); - /* - You must implement at least the set_ctrl method if you have defined - the list above. The returned value must follow the V4L2 - specifications for the VIDIOC_G|C_CTRL ioctls. V4L2_CID_H|VCENTER - are not supported by this driver, so do not implement them. Also, - you don't have to check whether the passed values are out of bounds, - given that this is done by the core module. - */ - - struct v4l2_cropcap cropcap; - /* - Think the image sensor as a grid of R,G,B monochromatic pixels - disposed according to a particular Bayer pattern, which describes - the complete array of pixels, from (0,0) to (xmax, ymax). We will - use this coordinate system from now on. It is assumed the sensor - chip can be programmed to capture/transmit a subsection of that - array of pixels: we will call this subsection "active window". - It is not always true that the largest achievable active window can - cover the whole array of pixels. The V4L2 API defines another - area called "source rectangle", which, in turn, is a subrectangle of - the active window. The SN9C1XX chip is always programmed to read the - source rectangle. - The bounds of both the active window and the source rectangle are - specified in the cropcap substructures 'bounds' and 'defrect'. - By default, the source rectangle should cover the largest possible - area. Again, it is not always true that the largest source rectangle - can cover the entire active window, although it is a rare case for - the hardware we have. The bounds of the source rectangle _must_ be - multiple of 16 and must use the same coordinate system as indicated - before; their centers shall align initially. - If necessary, the sensor chip must be initialized during init() to - set the bounds of the active sensor window; however, by default, it - usually covers the largest achievable area (maxwidth x maxheight) - of pixels, so no particular initialization is needed, if you have - defined the correct default bounds in the structures. - See the V4L2 API for further details. - NOTE: once you have defined the bounds of the active window - (struct cropcap.bounds) you must not change them.anymore. - Only 'bounds' and 'defrect' fields are mandatory, other fields - will be ignored. - */ - - int (*set_crop)(struct sn9c102_device* cam, - const struct v4l2_rect* rect); - /* - To be called on VIDIOC_C_SETCROP. The core module always calls a - default routine which configures the appropriate SN9C1XX regs (also - scaling), but you may need to override/adjust specific stuff. - 'rect' contains width and height values that are multiple of 16: in - case you override the default function, you always have to program - the chip to match those values; on error return the corresponding - error code without rolling back. - NOTE: in case, you must program the SN9C1XX chip to get rid of - blank pixels or blank lines at the _start_ of each line or - frame after each HSYNC or VSYNC, so that the image starts with - real RGB data (see regs 0x12, 0x13) (having set H_SIZE and, - V_SIZE you don't have to care about blank pixels or blank - lines at the end of each line or frame). - */ - - struct v4l2_pix_format pix_format; - /* - What you have to define here are: 1) initial 'width' and 'height' of - the target rectangle 2) the initial 'pixelformat', which can be - either V4L2_PIX_FMT_SN9C10X, V4L2_PIX_FMT_JPEG (for ompressed video) - or V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate - the number of bits per pixel for uncompressed video, 8 or 9 (despite - the current value of 'pixelformat'). - NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4 - of cropcap.defrect.width and cropcap.defrect.height. I - suggest 1/1. - NOTE 2: The initial compression quality is defined by the first bit - of reg 0x17 during the initialization of the image sensor. - NOTE 3: as said above, you have to program the SN9C1XX chip to get - rid of any blank pixels, so that the output of the sensor - matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR). - */ - - int (*set_pix_format)(struct sn9c102_device* cam, - const struct v4l2_pix_format* pix); - /* - To be called on VIDIOC_S_FMT, when switching from the SBGGR8 to - SN9C10X pixel format or viceversa. On error return the corresponding - error code without rolling back. - */ - - /* - Do NOT write to the data below, it's READ ONLY. It is used by the - core module to store successfully updated values of the above - settings, for rollbacks..etc..in case of errors during atomic I/O - */ - struct v4l2_queryctrl _qctrl[SN9C102_MAX_CTRLS]; - struct v4l2_rect _rect; -}; - -/*****************************************************************************/ - -/* Private ioctl's for control settings supported by some image sensors */ -#define SN9C102_V4L2_CID_DAC_MAGNITUDE (V4L2_CID_PRIVATE_BASE + 0) -#define SN9C102_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 1) -#define SN9C102_V4L2_CID_RESET_LEVEL (V4L2_CID_PRIVATE_BASE + 2) -#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE (V4L2_CID_PRIVATE_BASE + 3) -#define SN9C102_V4L2_CID_GAMMA (V4L2_CID_PRIVATE_BASE + 4) -#define SN9C102_V4L2_CID_BAND_FILTER (V4L2_CID_PRIVATE_BASE + 5) -#define SN9C102_V4L2_CID_BRIGHT_LEVEL (V4L2_CID_PRIVATE_BASE + 6) - -#endif /* _SN9C102_SENSOR_H_ */ diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c deleted file mode 100644 index 04cdfdde8564..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c +++ /dev/null @@ -1,154 +0,0 @@ -/*************************************************************************** - * Plug-in for TAS5110C1B image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2004-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" -#include "sn9c102_devtable.h" - - -static int tas5110c1b_init(struct sn9c102_device* cam) -{ - int err = 0; - - 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); - - return err; -} - - -static int tas5110c1b_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, 0x20, 0xf6 - ctrl->value); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int tas5110c1b_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); - - /* Don't change ! */ - err += sn9c102_write_reg(cam, 0x14, 0x1a); - err += sn9c102_write_reg(cam, 0x0a, 0x1b); - err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19); - - return err; -} - - -static int tas5110c1b_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, 0x2b, 0x19); - else - err += sn9c102_write_reg(cam, 0xfb, 0x19); - - return err; -} - - -static const struct sn9c102_sensor tas5110c1b = { - .name = "TAS5110C1B", - .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_3WIRES, - .init = &tas5110c1b_init, - .qctrl = { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0xf6, - .step = 0x01, - .default_value = 0x40, - .flags = 0, - }, - }, - .set_ctrl = &tas5110c1b_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 352, - .height = 288, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 352, - .height = 288, - }, - }, - .set_crop = &tas5110c1b_set_crop, - .pix_format = { - .width = 352, - .height = 288, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &tas5110c1b_set_pix_format -}; - - -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, 0x60ab), }, - { } - }; - - /* Sensor detection is based on USB pid/vid */ - if (!sn9c102_match_id(cam, tas5110c1b_id_table)) - return -ENODEV; - - sn9c102_attach_sensor(cam, &tas5110c1b); - - return 0; -} diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110d.c b/drivers/media/video/sn9c102/sn9c102_tas5110d.c deleted file mode 100644 index 9372e6f9fcff..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_tas5110d.c +++ /dev/null @@ -1,119 +0,0 @@ -/*************************************************************************** - * 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" -#include "sn9c102_devtable.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/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c deleted file mode 100644 index a30bbc4389f5..000000000000 --- a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c +++ /dev/null @@ -1,165 +0,0 @@ -/*************************************************************************** - * Plug-in for TAS5130D1B image sensor connected to the SN9C1xx PC Camera * - * Controllers * - * * - * Copyright (C) 2004-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" -#include "sn9c102_devtable.h" - - -static int tas5130d1b_init(struct sn9c102_device* cam) -{ - int err; - - err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x20, 0x17}, - {0x04, 0x01}, {0x01, 0x10}, - {0x00, 0x11}, {0x00, 0x14}, - {0x60, 0x17}, {0x07, 0x18}); - - return err; -} - - -static int tas5130d1b_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, 0x20, 0xf6 - ctrl->value); - break; - case V4L2_CID_EXPOSURE: - err += sn9c102_i2c_write(cam, 0x40, 0x47 - ctrl->value); - break; - default: - return -EINVAL; - } - - return err ? -EIO : 0; -} - - -static int tas5130d1b_set_crop(struct sn9c102_device* cam, - const struct v4l2_rect* rect) -{ - struct sn9c102_sensor* s = sn9c102_get_sensor(cam); - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12; - int err = 0; - - err += sn9c102_write_reg(cam, h_start, 0x12); - err += sn9c102_write_reg(cam, v_start, 0x13); - - /* Do NOT change! */ - err += sn9c102_write_reg(cam, 0x1f, 0x1a); - err += sn9c102_write_reg(cam, 0x1a, 0x1b); - err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19); - - return err; -} - - -static int tas5130d1b_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, 0x63, 0x19); - else - err += sn9c102_write_reg(cam, 0xf3, 0x19); - - return err; -} - - -static const struct sn9c102_sensor tas5130d1b = { - .name = "TAS5130D1B", - .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_3WIRES, - .init = &tas5130d1b_init, - .qctrl = { - { - .id = V4L2_CID_GAIN, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "global gain", - .minimum = 0x00, - .maximum = 0xf6, - .step = 0x02, - .default_value = 0x00, - .flags = 0, - }, - { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "exposure", - .minimum = 0x00, - .maximum = 0x47, - .step = 0x01, - .default_value = 0x00, - .flags = 0, - }, - }, - .set_ctrl = &tas5130d1b_set_ctrl, - .cropcap = { - .bounds = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - .defrect = { - .left = 0, - .top = 0, - .width = 640, - .height = 480, - }, - }, - .set_crop = &tas5130d1b_set_crop, - .pix_format = { - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .priv = 8, - }, - .set_pix_format = &tas5130d1b_set_pix_format -}; - - -int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam) -{ - const struct usb_device_id tas5130d1b_id_table[] = { - { USB_DEVICE(0x0c45, 0x6024), }, - { USB_DEVICE(0x0c45, 0x6025), }, - { USB_DEVICE(0x0c45, 0x60aa), }, - { } - }; - - /* Sensor detection is based on USB pid/vid */ - if (!sn9c102_match_id(cam, tas5130d1b_id_table)) - return -ENODEV; - - sn9c102_attach_sensor(cam, &tas5130d1b); - - return 0; -} diff --git a/drivers/media/video/stk1160/Kconfig b/drivers/media/video/stk1160/Kconfig deleted file mode 100644 index 1c3a1ec00237..000000000000 --- a/drivers/media/video/stk1160/Kconfig +++ /dev/null @@ -1,20 +0,0 @@ -config VIDEO_STK1160 - tristate "STK1160 USB video capture support" - depends on VIDEO_DEV && I2C - select VIDEOBUF2_VMALLOC - select VIDEO_SAA711X - - ---help--- - This is a video4linux driver for STK1160 based video capture devices. - - To compile this driver as a module, choose M here: the - module will be called stk1160 - -config VIDEO_STK1160_AC97 - bool "STK1160 AC97 codec support" - depends on VIDEO_STK1160 && SND - select SND_AC97_CODEC - - ---help--- - Enables AC97 codec support for stk1160 driver. -. diff --git a/drivers/media/video/stk1160/Makefile b/drivers/media/video/stk1160/Makefile deleted file mode 100644 index 8a3c78482e73..000000000000 --- a/drivers/media/video/stk1160/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -obj-stk1160-ac97-$(CONFIG_VIDEO_STK1160_AC97) := stk1160-ac97.o - -stk1160-y := stk1160-core.o \ - stk1160-v4l.o \ - stk1160-video.o \ - stk1160-i2c.o \ - $(obj-stk1160-ac97-y) - -obj-$(CONFIG_VIDEO_STK1160) += stk1160.o - -ccflags-y += -Idrivers/media/video diff --git a/drivers/media/video/stk1160/stk1160-ac97.c b/drivers/media/video/stk1160/stk1160-ac97.c deleted file mode 100644 index 8d325f50c87b..000000000000 --- a/drivers/media/video/stk1160/stk1160-ac97.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * STK1160 driver - * - * Copyright (C) 2012 Ezequiel Garcia - * <elezegarcia--a.t--gmail.com> - * - * Based on Easycap driver by R.M. Thomas - * Copyright (C) 2010 R.M. Thomas - * <rmthomas--a.t--sciolus.org> - * - * 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. - * - */ - -#include <linux/module.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/ac97_codec.h> - -#include "stk1160.h" -#include "stk1160-reg.h" - -static struct snd_ac97 *stk1160_ac97; - -static void stk1160_write_ac97(struct snd_ac97 *ac97, u16 reg, u16 value) -{ - struct stk1160 *dev = ac97->private_data; - - /* Set codec register address */ - stk1160_write_reg(dev, STK1160_AC97_ADDR, reg); - - /* Set codec command */ - stk1160_write_reg(dev, STK1160_AC97_CMD, value & 0xff); - stk1160_write_reg(dev, STK1160_AC97_CMD + 1, (value & 0xff00) >> 8); - - /* - * Set command write bit to initiate write operation. - * The bit will be cleared when transfer is done. - */ - stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8c); -} - -static u16 stk1160_read_ac97(struct snd_ac97 *ac97, u16 reg) -{ - struct stk1160 *dev = ac97->private_data; - u8 vall = 0; - u8 valh = 0; - - /* Set codec register address */ - stk1160_write_reg(dev, STK1160_AC97_ADDR, reg); - - /* - * Set command read bit to initiate read operation. - * The bit will be cleared when transfer is done. - */ - stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8b); - - /* Retrieve register value */ - stk1160_read_reg(dev, STK1160_AC97_CMD, &vall); - stk1160_read_reg(dev, STK1160_AC97_CMD + 1, &valh); - - return (valh << 8) | vall; -} - -static void stk1160_reset_ac97(struct snd_ac97 *ac97) -{ - struct stk1160 *dev = ac97->private_data; - /* Two-step reset AC97 interface and hardware codec */ - stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x94); - stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x88); - - /* Set 16-bit audio data and choose L&R channel*/ - stk1160_write_reg(dev, STK1160_AC97CTL_1 + 2, 0x01); -} - -static struct snd_ac97_bus_ops stk1160_ac97_ops = { - .read = stk1160_read_ac97, - .write = stk1160_write_ac97, - .reset = stk1160_reset_ac97, -}; - -int stk1160_ac97_register(struct stk1160 *dev) -{ - struct snd_card *card = NULL; - struct snd_ac97_bus *ac97_bus; - struct snd_ac97_template ac97_template; - int rc; - - /* - * Just want a card to access ac96 controls, - * the actual capture interface will be handled by snd-usb-audio - */ - rc = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, 0, &card); - if (rc < 0) - return rc; - - snd_card_set_dev(card, dev->dev); - - /* TODO: I'm not sure where should I get these names :-( */ - snprintf(card->shortname, sizeof(card->shortname), - "stk1160-mixer"); - snprintf(card->longname, sizeof(card->longname), - "stk1160 ac97 codec mixer control"); - strncpy(card->driver, dev->dev->driver->name, sizeof(card->driver)); - - rc = snd_ac97_bus(card, 0, &stk1160_ac97_ops, NULL, &ac97_bus); - if (rc) - goto err; - - /* We must set private_data before calling snd_ac97_mixer */ - memset(&ac97_template, 0, sizeof(ac97_template)); - ac97_template.private_data = dev; - ac97_template.scaps = AC97_SCAP_SKIP_MODEM; - rc = snd_ac97_mixer(ac97_bus, &ac97_template, &stk1160_ac97); - if (rc) - goto err; - - dev->snd_card = card; - rc = snd_card_register(card); - if (rc) - goto err; - - return 0; - -err: - dev->snd_card = NULL; - if (card) - snd_card_free(card); - return rc; -} - -int stk1160_ac97_unregister(struct stk1160 *dev) -{ - struct snd_card *card = dev->snd_card; - - /* - * We need to check usb_device, - * because ac97 release attempts to communicate with codec - */ - if (card && dev->udev) - snd_card_free(card); - - return 0; -} diff --git a/drivers/media/video/stk1160/stk1160-core.c b/drivers/media/video/stk1160/stk1160-core.c deleted file mode 100644 index 74236fd3b7ec..000000000000 --- a/drivers/media/video/stk1160/stk1160-core.c +++ /dev/null @@ -1,432 +0,0 @@ -/* - * STK1160 driver - * - * Copyright (C) 2012 Ezequiel Garcia - * <elezegarcia--a.t--gmail.com> - * - * Based on Easycap driver by R.M. Thomas - * Copyright (C) 2010 R.M. Thomas - * <rmthomas--a.t--sciolus.org> - * - * 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. - * - * TODO: - * - * 1. (Try to) detect if we must register ac97 mixer - * 2. Support stream at lower speed: lower frame rate or lower frame size. - * - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/slab.h> - -#include <linux/usb.h> -#include <linux/mm.h> -#include <linux/vmalloc.h> -#include <media/saa7115.h> - -#include "stk1160.h" -#include "stk1160-reg.h" - -static unsigned int input; -module_param(input, int, 0644); -MODULE_PARM_DESC(input, "Set default input"); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Ezequiel Garcia"); -MODULE_DESCRIPTION("STK1160 driver"); - -/* Devices supported by this driver */ -static struct usb_device_id stk1160_id_table[] = { - { USB_DEVICE(0x05e1, 0x0408) }, - { } -}; -MODULE_DEVICE_TABLE(usb, stk1160_id_table); - -/* saa7113 I2C address */ -static unsigned short saa7113_addrs[] = { - 0x4a >> 1, - I2C_CLIENT_END -}; - -/* - * Read/Write stk registers - */ -int stk1160_read_reg(struct stk1160 *dev, u16 reg, u8 *value) -{ - int ret; - int pipe = usb_rcvctrlpipe(dev->udev, 0); - - *value = 0; - ret = usb_control_msg(dev->udev, pipe, 0x00, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x00, reg, value, sizeof(u8), HZ); - if (ret < 0) { - stk1160_err("read failed on reg 0x%x (%d)\n", - reg, ret); - return ret; - } - - return 0; -} - -int stk1160_write_reg(struct stk1160 *dev, u16 reg, u16 value) -{ - int ret; - int pipe = usb_sndctrlpipe(dev->udev, 0); - - ret = usb_control_msg(dev->udev, pipe, 0x01, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, reg, NULL, 0, HZ); - if (ret < 0) { - stk1160_err("write failed on reg 0x%x (%d)\n", - reg, ret); - return ret; - } - - return 0; -} - -void stk1160_select_input(struct stk1160 *dev) -{ - static const u8 gctrl[] = { - 0x98, 0x90, 0x88, 0x80 - }; - - if (dev->ctl_input < ARRAY_SIZE(gctrl)) - stk1160_write_reg(dev, STK1160_GCTRL, gctrl[dev->ctl_input]); -} - -/* TODO: We should break this into pieces */ -static void stk1160_reg_reset(struct stk1160 *dev) -{ - int i; - - static const struct regval ctl[] = { - {STK1160_GCTRL+2, 0x0078}, - - {STK1160_RMCTL+1, 0x0000}, - {STK1160_RMCTL+3, 0x0002}, - - {STK1160_PLLSO, 0x0010}, - {STK1160_PLLSO+1, 0x0000}, - {STK1160_PLLSO+2, 0x0014}, - {STK1160_PLLSO+3, 0x000E}, - - {STK1160_PLLFD, 0x0046}, - - /* Timing generator setup */ - {STK1160_TIGEN, 0x0012}, - {STK1160_TICTL, 0x002D}, - {STK1160_TICTL+1, 0x0001}, - {STK1160_TICTL+2, 0x0000}, - {STK1160_TICTL+3, 0x0000}, - {STK1160_TIGEN, 0x0080}, - - {0xffff, 0xffff} - }; - - for (i = 0; ctl[i].reg != 0xffff; i++) - stk1160_write_reg(dev, ctl[i].reg, ctl[i].val); -} - -static void stk1160_release(struct v4l2_device *v4l2_dev) -{ - struct stk1160 *dev = container_of(v4l2_dev, struct stk1160, v4l2_dev); - - stk1160_info("releasing all resources\n"); - - stk1160_i2c_unregister(dev); - - v4l2_ctrl_handler_free(&dev->ctrl_handler); - v4l2_device_unregister(&dev->v4l2_dev); - kfree(dev->alt_max_pkt_size); - kfree(dev); -} - -/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */ -#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) - -/* - * Scan usb interface and populate max_pkt_size array - * with information on each alternate setting. - * The array should be allocated by the caller. - */ -static int stk1160_scan_usb(struct usb_interface *intf, struct usb_device *udev, - unsigned int *max_pkt_size) -{ - int i, e, sizedescr, size, ifnum; - const struct usb_endpoint_descriptor *desc; - - bool has_video = false, has_audio = false; - const char *speed; - - ifnum = intf->altsetting[0].desc.bInterfaceNumber; - - /* Get endpoints */ - for (i = 0; i < intf->num_altsetting; i++) { - - for (e = 0; e < intf->altsetting[i].desc.bNumEndpoints; e++) { - - /* This isn't clear enough, at least to me */ - desc = &intf->altsetting[i].endpoint[e].desc; - sizedescr = le16_to_cpu(desc->wMaxPacketSize); - size = sizedescr & 0x7ff; - - if (udev->speed == USB_SPEED_HIGH) - size = size * hb_mult(sizedescr); - - if (usb_endpoint_xfer_isoc(desc) && - usb_endpoint_dir_in(desc)) { - switch (desc->bEndpointAddress) { - case STK1160_EP_AUDIO: - has_audio = true; - break; - case STK1160_EP_VIDEO: - has_video = true; - max_pkt_size[i] = size; - break; - } - } - } - } - - /* Is this even possible? */ - if (!(has_audio || has_video)) { - dev_err(&udev->dev, "no audio or video endpoints found\n"); - return -ENODEV; - } - - switch (udev->speed) { - case USB_SPEED_LOW: - speed = "1.5"; - break; - case USB_SPEED_FULL: - speed = "12"; - break; - case USB_SPEED_HIGH: - speed = "480"; - break; - default: - speed = "unknown"; - } - - dev_info(&udev->dev, "New device %s %s @ %s Mbps (%04x:%04x, interface %d, class %d)\n", - udev->manufacturer ? udev->manufacturer : "", - udev->product ? udev->product : "", - speed, - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), - ifnum, - intf->altsetting->desc.bInterfaceNumber); - - /* This should never happen, since we rejected audio interfaces */ - if (has_audio) - dev_warn(&udev->dev, "audio interface %d found.\n\ - This is not implemented by this driver,\ - you should use snd-usb-audio instead\n", ifnum); - - if (has_video) - dev_info(&udev->dev, "video interface %d found\n", - ifnum); - - /* - * Make sure we have 480 Mbps of bandwidth, otherwise things like - * video stream wouldn't likely work, since 12 Mbps is generally - * not enough even for most streams. - */ - if (udev->speed != USB_SPEED_HIGH) - dev_warn(&udev->dev, "must be connected to a high-speed USB 2.0 port\n\ - You may not be able to stream video smoothly\n"); - - return 0; -} - -static int stk1160_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - int ifnum; - int rc = 0; - - unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ - struct usb_device *udev; - struct stk1160 *dev; - - ifnum = interface->altsetting[0].desc.bInterfaceNumber; - udev = interface_to_usbdev(interface); - - /* - * Since usb audio class is supported by snd-usb-audio, - * we reject audio interface. - */ - if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) - return -ENODEV; - - /* Alloc an array for all possible max_pkt_size */ - alt_max_pkt_size = kmalloc(sizeof(alt_max_pkt_size[0]) * - interface->num_altsetting, GFP_KERNEL); - if (alt_max_pkt_size == NULL) - return -ENOMEM; - - /* - * Scan usb posibilities and populate alt_max_pkt_size array. - * Also, check if device speed is fast enough. - */ - rc = stk1160_scan_usb(interface, udev, alt_max_pkt_size); - if (rc < 0) { - kfree(alt_max_pkt_size); - return rc; - } - - dev = kzalloc(sizeof(struct stk1160), GFP_KERNEL); - if (dev == NULL) { - kfree(alt_max_pkt_size); - return -ENOMEM; - } - - dev->alt_max_pkt_size = alt_max_pkt_size; - dev->udev = udev; - dev->num_alt = interface->num_altsetting; - dev->ctl_input = input; - - /* We save struct device for debug purposes only */ - dev->dev = &interface->dev; - - usb_set_intfdata(interface, dev); - - /* initialize videobuf2 stuff */ - rc = stk1160_vb2_setup(dev); - if (rc < 0) - goto free_err; - - /* - * There is no need to take any locks here in probe - * because we register the device node as the *last* thing. - */ - spin_lock_init(&dev->buf_lock); - mutex_init(&dev->v4l_lock); - mutex_init(&dev->vb_queue_lock); - - rc = v4l2_ctrl_handler_init(&dev->ctrl_handler, 0); - if (rc) { - stk1160_err("v4l2_ctrl_handler_init failed (%d)\n", rc); - goto free_err; - } - - /* - * We obtain a v4l2_dev but defer - * registration of video device node as the last thing. - * There is no need to set the name if we give a device struct - */ - dev->v4l2_dev.release = stk1160_release; - dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler; - rc = v4l2_device_register(dev->dev, &dev->v4l2_dev); - if (rc) { - stk1160_err("v4l2_device_register failed (%d)\n", rc); - goto free_ctrl; - } - - rc = stk1160_i2c_register(dev); - if (rc < 0) - goto unreg_v4l2; - - /* - * To the best of my knowledge stk1160 boards only have - * saa7113, but it doesn't hurt to support them all. - */ - dev->sd_saa7115 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "saa7115_auto", 0, saa7113_addrs); - - stk1160_info("driver ver %s successfully loaded\n", - STK1160_VERSION); - - /* i2c reset saa711x */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0); - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, - 0, 0, 0); - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); - - /* reset stk1160 to default values */ - stk1160_reg_reset(dev); - - /* select default input */ - stk1160_select_input(dev); - - stk1160_ac97_register(dev); - - rc = stk1160_video_register(dev); - if (rc < 0) - goto unreg_i2c; - - return 0; - -unreg_i2c: - stk1160_i2c_unregister(dev); -unreg_v4l2: - v4l2_device_unregister(&dev->v4l2_dev); -free_ctrl: - v4l2_ctrl_handler_free(&dev->ctrl_handler); -free_err: - kfree(alt_max_pkt_size); - kfree(dev); - - return rc; -} - -static void stk1160_disconnect(struct usb_interface *interface) -{ - struct stk1160 *dev; - - dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - /* - * Wait until all current v4l2 operation are finished - * then deallocate resources - */ - mutex_lock(&dev->vb_queue_lock); - mutex_lock(&dev->v4l_lock); - - /* Here is the only place where isoc get released */ - stk1160_uninit_isoc(dev); - - /* ac97 unregister needs to be done before usb_device is cleared */ - stk1160_ac97_unregister(dev); - - stk1160_clear_queue(dev); - - video_unregister_device(&dev->vdev); - v4l2_device_disconnect(&dev->v4l2_dev); - - /* This way current users can detect device is gone */ - dev->udev = NULL; - - mutex_unlock(&dev->v4l_lock); - mutex_unlock(&dev->vb_queue_lock); - - /* - * This calls stk1160_release if it's the last reference. - * therwise, release is posponed until there are no users left. - */ - v4l2_device_put(&dev->v4l2_dev); -} - -static struct usb_driver stk1160_usb_driver = { - .name = "stk1160", - .id_table = stk1160_id_table, - .probe = stk1160_probe, - .disconnect = stk1160_disconnect, -}; - -module_usb_driver(stk1160_usb_driver); diff --git a/drivers/media/video/stk1160/stk1160-i2c.c b/drivers/media/video/stk1160/stk1160-i2c.c deleted file mode 100644 index 176ac937306b..000000000000 --- a/drivers/media/video/stk1160/stk1160-i2c.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - * STK1160 driver - * - * Copyright (C) 2012 Ezequiel Garcia - * <elezegarcia--a.t--gmail.com> - * - * Based on Easycap driver by R.M. Thomas - * Copyright (C) 2010 R.M. Thomas - * <rmthomas--a.t--sciolus.org> - * - * 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. - * - */ - -#include <linux/module.h> -#include <linux/usb.h> -#include <linux/i2c.h> - -#include "stk1160.h" -#include "stk1160-reg.h" - -static unsigned int i2c_debug; -module_param(i2c_debug, int, 0644); -MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); - -#define dprintk_i2c(fmt, args...) \ -do { \ - if (i2c_debug) \ - printk(KERN_DEBUG fmt, ##args); \ -} while (0) - -static int stk1160_i2c_busy_wait(struct stk1160 *dev, u8 wait_bit_mask) -{ - unsigned long end; - u8 flag; - - /* Wait until read/write finish bit is set */ - end = jiffies + msecs_to_jiffies(STK1160_I2C_TIMEOUT); - while (time_is_after_jiffies(end)) { - - stk1160_read_reg(dev, STK1160_SICTL+1, &flag); - /* read/write done? */ - if (flag & wait_bit_mask) - goto done; - - usleep_range(10 * USEC_PER_MSEC, 20 * USEC_PER_MSEC); - } - - return -ETIMEDOUT; - -done: - return 0; -} - -static int stk1160_i2c_write_reg(struct stk1160 *dev, u8 addr, - u8 reg, u8 value) -{ - int rc; - - /* Set serial device address */ - rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr); - if (rc < 0) - return rc; - - /* Set i2c device register sub-address */ - rc = stk1160_write_reg(dev, STK1160_SBUSW_WA, reg); - if (rc < 0) - return rc; - - /* Set i2c device register value */ - rc = stk1160_write_reg(dev, STK1160_SBUSW_WD, value); - if (rc < 0) - return rc; - - /* Start write now */ - rc = stk1160_write_reg(dev, STK1160_SICTL, 0x01); - if (rc < 0) - return rc; - - rc = stk1160_i2c_busy_wait(dev, 0x04); - if (rc < 0) - return rc; - - return 0; -} - -static int stk1160_i2c_read_reg(struct stk1160 *dev, u8 addr, - u8 reg, u8 *value) -{ - int rc; - - /* Set serial device address */ - rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr); - if (rc < 0) - return rc; - - /* Set i2c device register sub-address */ - rc = stk1160_write_reg(dev, STK1160_SBUSR_RA, reg); - if (rc < 0) - return rc; - - /* Start read now */ - rc = stk1160_write_reg(dev, STK1160_SICTL, 0x20); - if (rc < 0) - return rc; - - rc = stk1160_i2c_busy_wait(dev, 0x01); - if (rc < 0) - return rc; - - stk1160_read_reg(dev, STK1160_SBUSR_RD, value); - if (rc < 0) - return rc; - - return 0; -} - -/* - * stk1160_i2c_check_for_device() - * check if there is a i2c_device at the supplied address - */ -static int stk1160_i2c_check_for_device(struct stk1160 *dev, - unsigned char addr) -{ - int rc; - - /* Set serial device address */ - rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr); - if (rc < 0) - return rc; - - /* Set device sub-address, we'll chip version reg */ - rc = stk1160_write_reg(dev, STK1160_SBUSR_RA, 0x00); - if (rc < 0) - return rc; - - /* Start read now */ - rc = stk1160_write_reg(dev, STK1160_SICTL, 0x20); - if (rc < 0) - return rc; - - rc = stk1160_i2c_busy_wait(dev, 0x01); - if (rc < 0) - return -ENODEV; - - return 0; -} - -/* - * stk1160_i2c_xfer() - * the main i2c transfer function - */ -static int stk1160_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msgs[], int num) -{ - struct stk1160 *dev = i2c_adap->algo_data; - int addr, rc, i; - - for (i = 0; i < num; i++) { - addr = msgs[i].addr << 1; - dprintk_i2c("%s: addr=%x", __func__, addr); - - if (!msgs[i].len) { - /* no len: check only for device presence */ - rc = stk1160_i2c_check_for_device(dev, addr); - if (rc < 0) { - dprintk_i2c(" no device\n"); - return rc; - } - - } else if (msgs[i].flags & I2C_M_RD) { - /* read request without preceding register selection */ - dprintk_i2c(" subaddr not selected"); - rc = -EOPNOTSUPP; - goto err; - - } else if (i + 1 < num && msgs[i].len <= 2 && - (msgs[i + 1].flags & I2C_M_RD) && - msgs[i].addr == msgs[i + 1].addr) { - - if (msgs[i].len != 1 || msgs[i + 1].len != 1) { - dprintk_i2c(" len not supported"); - rc = -EOPNOTSUPP; - goto err; - } - - dprintk_i2c(" subaddr=%x", msgs[i].buf[0]); - - rc = stk1160_i2c_read_reg(dev, addr, msgs[i].buf[0], - msgs[i + 1].buf); - - dprintk_i2c(" read=%x", *msgs[i + 1].buf); - - /* consumed two msgs, so we skip one of them */ - i++; - - } else { - if (msgs[i].len != 2) { - dprintk_i2c(" len not supported"); - rc = -EOPNOTSUPP; - goto err; - } - - dprintk_i2c(" subaddr=%x write=%x", - msgs[i].buf[0], msgs[i].buf[1]); - - rc = stk1160_i2c_write_reg(dev, addr, msgs[i].buf[0], - msgs[i].buf[1]); - } - - if (rc < 0) - goto err; - dprintk_i2c(" OK\n"); - } - - return num; -err: - dprintk_i2c(" ERROR: %d\n", rc); - return num; -} - -/* - * functionality(), what da heck is this? - */ -static u32 functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_SMBUS_EMUL; -} - -static struct i2c_algorithm algo = { - .master_xfer = stk1160_i2c_xfer, - .functionality = functionality, -}; - -static struct i2c_adapter adap_template = { - .owner = THIS_MODULE, - .name = "stk1160", - .algo = &algo, -}; - -static struct i2c_client client_template = { - .name = "stk1160 internal", -}; - -/* - * stk1160_i2c_register() - * register i2c bus - */ -int stk1160_i2c_register(struct stk1160 *dev) -{ - int rc; - - dev->i2c_adap = adap_template; - dev->i2c_adap.dev.parent = dev->dev; - strcpy(dev->i2c_adap.name, "stk1160"); - dev->i2c_adap.algo_data = dev; - - i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); - - rc = i2c_add_adapter(&dev->i2c_adap); - if (rc < 0) { - stk1160_err("cannot add i2c adapter (%d)\n", rc); - return rc; - } - - dev->i2c_client = client_template; - dev->i2c_client.adapter = &dev->i2c_adap; - - /* Set i2c clock divider device address */ - stk1160_write_reg(dev, STK1160_SICTL_CD, 0x0f); - - /* ??? */ - stk1160_write_reg(dev, STK1160_ASIC + 3, 0x00); - - return 0; -} - -/* - * stk1160_i2c_unregister() - * unregister i2c_bus - */ -int stk1160_i2c_unregister(struct stk1160 *dev) -{ - i2c_del_adapter(&dev->i2c_adap); - return 0; -} diff --git a/drivers/media/video/stk1160/stk1160-reg.h b/drivers/media/video/stk1160/stk1160-reg.h deleted file mode 100644 index 3e49da6e7edd..000000000000 --- a/drivers/media/video/stk1160/stk1160-reg.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * STK1160 driver - * - * Copyright (C) 2012 Ezequiel Garcia - * <elezegarcia--a.t--gmail.com> - * - * Based on Easycap driver by R.M. Thomas - * Copyright (C) 2010 R.M. Thomas - * <rmthomas--a.t--sciolus.org> - * - * 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. - * - */ - -/* GPIO Control */ -#define STK1160_GCTRL 0x000 - -/* Remote Wakup Control */ -#define STK1160_RMCTL 0x00c - -/* - * Decoder Control Register: - * This byte controls capture start/stop - * with bit #7 (0x?? OR 0x80 to activate). - */ -#define STK1160_DCTRL 0x100 - -/* Capture Frame Start Position */ -#define STK116_CFSPO 0x110 -#define STK116_CFSPO_STX_L 0x110 -#define STK116_CFSPO_STX_H 0x111 -#define STK116_CFSPO_STY_L 0x112 -#define STK116_CFSPO_STY_H 0x113 - -/* Capture Frame End Position */ -#define STK116_CFEPO 0x114 -#define STK116_CFEPO_ENX_L 0x114 -#define STK116_CFEPO_ENX_H 0x115 -#define STK116_CFEPO_ENY_L 0x116 -#define STK116_CFEPO_ENY_H 0x117 - -/* Serial Interface Control */ -#define STK1160_SICTL 0x200 -#define STK1160_SICTL_CD 0x202 -#define STK1160_SICTL_SDA 0x203 - -/* Serial Bus Write */ -#define STK1160_SBUSW 0x204 -#define STK1160_SBUSW_WA 0x204 -#define STK1160_SBUSW_WD 0x205 - -/* Serial Bus Read */ -#define STK1160_SBUSR 0x208 -#define STK1160_SBUSR_RA 0x208 -#define STK1160_SBUSR_RD 0x209 - -/* Alternate Serial Inteface Control */ -#define STK1160_ASIC 0x2fc - -/* PLL Select Options */ -#define STK1160_PLLSO 0x018 - -/* PLL Frequency Divider */ -#define STK1160_PLLFD 0x01c - -/* Timing Generator */ -#define STK1160_TIGEN 0x300 - -/* Timing Control Parameter */ -#define STK1160_TICTL 0x350 - -/* AC97 Audio Control */ -#define STK1160_AC97CTL_0 0x500 -#define STK1160_AC97CTL_1 0x504 - -/* Use [0:6] bits of register 0x504 to set codec command address */ -#define STK1160_AC97_ADDR 0x504 -/* Use [16:31] bits of register 0x500 to set codec command data */ -#define STK1160_AC97_CMD 0x502 - -/* Audio I2S Interface */ -#define STK1160_I2SCTL 0x50c - -/* EEPROM Interface */ -#define STK1160_EEPROM_SZ 0x5f0 diff --git a/drivers/media/video/stk1160/stk1160-v4l.c b/drivers/media/video/stk1160/stk1160-v4l.c deleted file mode 100644 index 360bdbee4270..000000000000 --- a/drivers/media/video/stk1160/stk1160-v4l.c +++ /dev/null @@ -1,738 +0,0 @@ -/* - * STK1160 driver - * - * Copyright (C) 2012 Ezequiel Garcia - * <elezegarcia--a.t--gmail.com> - * - * Based on Easycap driver by R.M. Thomas - * Copyright (C) 2010 R.M. Thomas - * <rmthomas--a.t--sciolus.org> - * - * 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. - * - */ - -#include <linux/module.h> -#include <linux/usb.h> -#include <linux/mm.h> -#include <linux/slab.h> - -#include <linux/videodev2.h> -#include <media/v4l2-device.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-fh.h> -#include <media/v4l2-event.h> -#include <media/v4l2-chip-ident.h> -#include <media/videobuf2-vmalloc.h> - -#include <media/saa7115.h> - -#include "stk1160.h" -#include "stk1160-reg.h" - -static unsigned int vidioc_debug; -module_param(vidioc_debug, int, 0644); -MODULE_PARM_DESC(vidioc_debug, "enable debug messages [vidioc]"); - -static bool keep_buffers; -module_param(keep_buffers, bool, 0644); -MODULE_PARM_DESC(keep_buffers, "don't release buffers upon stop streaming"); - -/* supported video standards */ -static struct stk1160_fmt format[] = { - { - .name = "16 bpp YUY2, 4:2:2, packed", - .fourcc = V4L2_PIX_FMT_UYVY, - .depth = 16, - } -}; - -static void stk1160_set_std(struct stk1160 *dev) -{ - int i; - - static struct regval std525[] = { - - /* 720x480 */ - - /* Frame start */ - {STK116_CFSPO_STX_L, 0x0000}, - {STK116_CFSPO_STX_H, 0x0000}, - {STK116_CFSPO_STY_L, 0x0003}, - {STK116_CFSPO_STY_H, 0x0000}, - - /* Frame end */ - {STK116_CFEPO_ENX_L, 0x05a0}, - {STK116_CFEPO_ENX_H, 0x0005}, - {STK116_CFEPO_ENY_L, 0x00f3}, - {STK116_CFEPO_ENY_H, 0x0000}, - - {0xffff, 0xffff} - }; - - static struct regval std625[] = { - - /* 720x576 */ - - /* TODO: Each line of frame has some junk at the end */ - /* Frame start */ - {STK116_CFSPO, 0x0000}, - {STK116_CFSPO+1, 0x0000}, - {STK116_CFSPO+2, 0x0001}, - {STK116_CFSPO+3, 0x0000}, - - /* Frame end */ - {STK116_CFEPO, 0x05a0}, - {STK116_CFEPO+1, 0x0005}, - {STK116_CFEPO+2, 0x0121}, - {STK116_CFEPO+3, 0x0001}, - - {0xffff, 0xffff} - }; - - if (dev->norm & V4L2_STD_525_60) { - stk1160_dbg("registers to NTSC like standard\n"); - for (i = 0; std525[i].reg != 0xffff; i++) - stk1160_write_reg(dev, std525[i].reg, std525[i].val); - } else { - stk1160_dbg("registers to PAL like standard\n"); - for (i = 0; std625[i].reg != 0xffff; i++) - stk1160_write_reg(dev, std625[i].reg, std625[i].val); - } - -} - -/* - * Set a new alternate setting. - * Returns true is dev->max_pkt_size has changed, false otherwise. - */ -static bool stk1160_set_alternate(struct stk1160 *dev) -{ - int i, prev_alt = dev->alt; - unsigned int min_pkt_size; - bool new_pkt_size; - - /* - * If we don't set right alternate, - * then we will get a green screen with junk. - */ - min_pkt_size = STK1160_MIN_PKT_SIZE; - - for (i = 0; i < dev->num_alt; i++) { - /* stop when the selected alt setting offers enough bandwidth */ - if (dev->alt_max_pkt_size[i] >= min_pkt_size) { - dev->alt = i; - break; - /* - * otherwise make sure that we end up with the maximum bandwidth - * because the min_pkt_size equation might be wrong... - */ - } else if (dev->alt_max_pkt_size[i] > - dev->alt_max_pkt_size[dev->alt]) - dev->alt = i; - } - - stk1160_info("setting alternate %d\n", dev->alt); - - if (dev->alt != prev_alt) { - stk1160_dbg("minimum isoc packet size: %u (alt=%d)\n", - min_pkt_size, dev->alt); - stk1160_dbg("setting alt %d with wMaxPacketSize=%u\n", - dev->alt, dev->alt_max_pkt_size[dev->alt]); - usb_set_interface(dev->udev, 0, dev->alt); - } - - new_pkt_size = dev->max_pkt_size != dev->alt_max_pkt_size[dev->alt]; - dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt]; - - return new_pkt_size; -} - -static int stk1160_start_streaming(struct stk1160 *dev) -{ - int i, rc; - bool new_pkt_size; - - /* Check device presence */ - if (!dev->udev) - return -ENODEV; - - if (mutex_lock_interruptible(&dev->v4l_lock)) - return -ERESTARTSYS; - /* - * For some reason it is mandatory to set alternate *first* - * and only *then* initialize isoc urbs. - * Someone please explain me why ;) - */ - new_pkt_size = stk1160_set_alternate(dev); - - /* - * We (re)allocate isoc urbs if: - * there is no allocated isoc urbs, OR - * a new dev->max_pkt_size is detected - */ - if (!dev->isoc_ctl.num_bufs || new_pkt_size) { - rc = stk1160_alloc_isoc(dev); - if (rc < 0) - return rc; - } - - /* submit urbs and enables IRQ */ - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_KERNEL); - if (rc) { - stk1160_err("cannot submit urb[%d] (%d)\n", i, rc); - stk1160_uninit_isoc(dev); - return rc; - } - } - - /* Start saa711x */ - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); - - /* Start stk1160 */ - stk1160_write_reg(dev, STK1160_DCTRL, 0xb3); - stk1160_write_reg(dev, STK1160_DCTRL+3, 0x00); - - stk1160_dbg("streaming started\n"); - - mutex_unlock(&dev->v4l_lock); - - return 0; -} - -/* Must be called with v4l_lock hold */ -static void stk1160_stop_hw(struct stk1160 *dev) -{ - /* If the device is not physically present, there is nothing to do */ - if (!dev->udev) - return; - - /* set alternate 0 */ - dev->alt = 0; - stk1160_info("setting alternate %d\n", dev->alt); - usb_set_interface(dev->udev, 0, 0); - - /* Stop stk1160 */ - stk1160_write_reg(dev, STK1160_DCTRL, 0x00); - stk1160_write_reg(dev, STK1160_DCTRL+3, 0x00); - - /* Stop saa711x */ - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); -} - -static int stk1160_stop_streaming(struct stk1160 *dev) -{ - if (mutex_lock_interruptible(&dev->v4l_lock)) - return -ERESTARTSYS; - - stk1160_cancel_isoc(dev); - - /* - * It is possible to keep buffers around using a module parameter. - * This is intended to avoid memory fragmentation. - */ - if (!keep_buffers) - stk1160_free_isoc(dev); - - stk1160_stop_hw(dev); - - stk1160_clear_queue(dev); - - stk1160_dbg("streaming stopped\n"); - - mutex_unlock(&dev->v4l_lock); - - return 0; -} - -static struct v4l2_file_operations stk1160_fops = { - .owner = THIS_MODULE, - .open = v4l2_fh_open, - .release = vb2_fop_release, - .read = vb2_fop_read, - .poll = vb2_fop_poll, - .mmap = vb2_fop_mmap, - .unlocked_ioctl = video_ioctl2, -}; - -/* - * vidioc ioctls - */ -static int vidioc_querycap(struct file *file, - void *priv, struct v4l2_capability *cap) -{ - struct stk1160 *dev = video_drvdata(file); - - strcpy(cap->driver, "stk1160"); - strcpy(cap->card, "stk1160"); - usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); - cap->device_caps = - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_STREAMING | - V4L2_CAP_READWRITE; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - if (f->index != 0) - return -EINVAL; - - strlcpy(f->description, format[f->index].name, sizeof(f->description)); - f->pixelformat = format[f->index].fourcc; - return 0; -} - -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct stk1160 *dev = video_drvdata(file); - - f->fmt.pix.width = dev->width; - f->fmt.pix.height = dev->height; - f->fmt.pix.field = V4L2_FIELD_INTERLACED; - f->fmt.pix.pixelformat = dev->fmt->fourcc; - f->fmt.pix.bytesperline = dev->width * 2; - f->fmt.pix.sizeimage = dev->height * f->fmt.pix.bytesperline; - f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - - return 0; -} - -static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct stk1160 *dev = video_drvdata(file); - - if (f->fmt.pix.pixelformat != format[0].fourcc) { - stk1160_err("fourcc format 0x%08x invalid\n", - f->fmt.pix.pixelformat); - return -EINVAL; - } - - /* - * User can't choose size at his own will, - * so we just return him the current size chosen - * at standard selection. - * TODO: Implement frame scaling? - */ - - f->fmt.pix.width = dev->width; - f->fmt.pix.height = dev->height; - f->fmt.pix.field = V4L2_FIELD_INTERLACED; - f->fmt.pix.bytesperline = dev->width * 2; - f->fmt.pix.sizeimage = dev->height * f->fmt.pix.bytesperline; - f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct stk1160 *dev = video_drvdata(file); - struct vb2_queue *q = &dev->vb_vidq; - int rc; - - if (vb2_is_busy(q)) - return -EBUSY; - - rc = vidioc_try_fmt_vid_cap(file, priv, f); - if (rc < 0) - return rc; - - /* We don't support any format changes */ - - return 0; -} - -static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm) -{ - struct stk1160 *dev = video_drvdata(file); - v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm); - return 0; -} - -static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) -{ - struct stk1160 *dev = video_drvdata(file); - - *norm = dev->norm; - return 0; -} - -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) -{ - struct stk1160 *dev = video_drvdata(file); - struct vb2_queue *q = &dev->vb_vidq; - - if (vb2_is_busy(q)) - return -EBUSY; - - /* Check device presence */ - if (!dev->udev) - return -ENODEV; - - /* We need to set this now, before we call stk1160_set_std */ - dev->norm = *norm; - - /* This is taken from saa7115 video decoder */ - if (dev->norm & V4L2_STD_525_60) { - dev->width = 720; - dev->height = 480; - } else if (dev->norm & V4L2_STD_625_50) { - dev->width = 720; - dev->height = 576; - } else { - stk1160_err("invalid standard\n"); - return -EINVAL; - } - - stk1160_set_std(dev); - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, - dev->norm); - - return 0; -} - - -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *i) -{ - struct stk1160 *dev = video_drvdata(file); - - if (i->index > STK1160_MAX_INPUT) - return -EINVAL; - - sprintf(i->name, "Composite%d", i->index); - i->type = V4L2_INPUT_TYPE_CAMERA; - i->std = dev->vdev.tvnorms; - return 0; -} - -static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) -{ - struct stk1160 *dev = video_drvdata(file); - *i = dev->ctl_input; - return 0; -} - -static int vidioc_s_input(struct file *file, void *priv, unsigned int i) -{ - struct stk1160 *dev = video_drvdata(file); - - if (vb2_is_busy(&dev->vb_vidq)) - return -EBUSY; - - if (i > STK1160_MAX_INPUT) - return -EINVAL; - - dev->ctl_input = i; - - stk1160_select_input(dev); - - return 0; -} - -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - switch (chip->match.type) { - case V4L2_CHIP_MATCH_HOST: - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - return 0; - default: - return -EINVAL; - } -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int vidioc_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct stk1160 *dev = video_drvdata(file); - int rc; - u8 val; - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_AC97: - /* TODO: Support me please :-( */ - return -EINVAL; - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* TODO: is this correct? */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - - /* Match host */ - rc = stk1160_read_reg(dev, reg->reg, &val); - reg->val = val; - reg->size = 1; - - return rc; -} - -static int vidioc_s_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct stk1160 *dev = video_drvdata(file); - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_AC97: - return -EINVAL; - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* TODO: is this correct? */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - - /* Match host */ - return stk1160_write_reg(dev, reg->reg, cpu_to_le16(reg->val)); -} -#endif - -static const struct v4l2_ioctl_ops stk1160_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_querystd = vidioc_querystd, - .vidioc_g_std = vidioc_g_std, - .vidioc_s_std = vidioc_s_std, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - - /* vb2 takes care of these */ - .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_streamon = vb2_ioctl_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - - .vidioc_log_status = v4l2_ctrl_log_status, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = vidioc_g_chip_ident, - -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, -#endif -}; - -/********************************************************************/ - -/* - * Videobuf2 operations - */ -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *v4l_fmt, - unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], void *alloc_ctxs[]) -{ - struct stk1160 *dev = vb2_get_drv_priv(vq); - unsigned long size; - - size = dev->width * dev->height * 2; - - /* - * Here we can change the number of buffers being requested. - * So, we set a minimum and a maximum like this: - */ - *nbuffers = clamp_t(unsigned int, *nbuffers, - STK1160_MIN_VIDEO_BUFFERS, STK1160_MAX_VIDEO_BUFFERS); - - /* This means a packed colorformat */ - *nplanes = 1; - - sizes[0] = size; - - stk1160_info("%s: buffer count %d, each %ld bytes\n", - __func__, *nbuffers, size); - - return 0; -} - -static void buffer_queue(struct vb2_buffer *vb) -{ - unsigned long flags; - struct stk1160 *dev = vb2_get_drv_priv(vb->vb2_queue); - struct stk1160_buffer *buf = - container_of(vb, struct stk1160_buffer, vb); - - spin_lock_irqsave(&dev->buf_lock, flags); - if (!dev->udev) { - /* - * If the device is disconnected return the buffer to userspace - * directly. The next QBUF call will fail with -ENODEV. - */ - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); - } else { - - buf->mem = vb2_plane_vaddr(vb, 0); - buf->length = vb2_plane_size(vb, 0); - buf->bytesused = 0; - buf->pos = 0; - - /* - * If buffer length is less from expected then we return - * the buffer to userspace directly. - */ - if (buf->length < dev->width * dev->height * 2) - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); - else - list_add_tail(&buf->list, &dev->avail_bufs); - - } - spin_unlock_irqrestore(&dev->buf_lock, flags); -} - -static int start_streaming(struct vb2_queue *vq, unsigned int count) -{ - struct stk1160 *dev = vb2_get_drv_priv(vq); - return stk1160_start_streaming(dev); -} - -/* abort streaming and wait for last buffer */ -static int stop_streaming(struct vb2_queue *vq) -{ - struct stk1160 *dev = vb2_get_drv_priv(vq); - return stk1160_stop_streaming(dev); -} - -static struct vb2_ops stk1160_video_qops = { - .queue_setup = queue_setup, - .buf_queue = buffer_queue, - .start_streaming = start_streaming, - .stop_streaming = stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, -}; - -static struct video_device v4l_template = { - .name = "stk1160", - .tvnorms = V4L2_STD_525_60 | V4L2_STD_625_50, - .fops = &stk1160_fops, - .ioctl_ops = &stk1160_ioctl_ops, - .release = video_device_release_empty, -}; - -/********************************************************************/ - -/* Must be called with both v4l_lock and vb_queue_lock hold */ -void stk1160_clear_queue(struct stk1160 *dev) -{ - struct stk1160_buffer *buf; - unsigned long flags; - - /* Release all active buffers */ - spin_lock_irqsave(&dev->buf_lock, flags); - while (!list_empty(&dev->avail_bufs)) { - buf = list_first_entry(&dev->avail_bufs, - struct stk1160_buffer, list); - list_del(&buf->list); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); - stk1160_info("buffer [%p/%d] aborted\n", - buf, buf->vb.v4l2_buf.index); - } - /* It's important to clear current buffer */ - dev->isoc_ctl.buf = NULL; - spin_unlock_irqrestore(&dev->buf_lock, flags); -} - -int stk1160_vb2_setup(struct stk1160 *dev) -{ - int rc; - struct vb2_queue *q; - - q = &dev->vb_vidq; - memset(q, 0, sizeof(dev->vb_vidq)); - q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR; - q->drv_priv = dev; - q->buf_struct_size = sizeof(struct stk1160_buffer); - q->ops = &stk1160_video_qops; - q->mem_ops = &vb2_vmalloc_memops; - - rc = vb2_queue_init(q); - if (rc < 0) - return rc; - - /* initialize video dma queue */ - INIT_LIST_HEAD(&dev->avail_bufs); - - return 0; -} - -int stk1160_video_register(struct stk1160 *dev) -{ - int rc; - - /* Initialize video_device with a template structure */ - dev->vdev = v4l_template; - dev->vdev.debug = vidioc_debug; - dev->vdev.queue = &dev->vb_vidq; - - /* - * Provide mutexes for v4l2 core and for videobuf2 queue. - * It will be used to protect *only* v4l2 ioctls. - */ - dev->vdev.lock = &dev->v4l_lock; - dev->vdev.queue->lock = &dev->vb_queue_lock; - - /* This will be used to set video_device parent */ - dev->vdev.v4l2_dev = &dev->v4l2_dev; - set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags); - - /* NTSC is default */ - dev->norm = V4L2_STD_NTSC_M; - dev->width = 720; - dev->height = 480; - - /* set default format */ - dev->fmt = &format[0]; - stk1160_set_std(dev); - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, - dev->norm); - - video_set_drvdata(&dev->vdev, dev); - rc = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); - if (rc < 0) { - stk1160_err("video_register_device failed (%d)\n", rc); - return rc; - } - - v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n", - video_device_node_name(&dev->vdev)); - - return 0; -} diff --git a/drivers/media/video/stk1160/stk1160-video.c b/drivers/media/video/stk1160/stk1160-video.c deleted file mode 100644 index 378526981146..000000000000 --- a/drivers/media/video/stk1160/stk1160-video.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - * STK1160 driver - * - * Copyright (C) 2012 Ezequiel Garcia - * <elezegarcia--a.t--gmail.com> - * - * Based on Easycap driver by R.M. Thomas - * Copyright (C) 2010 R.M. Thomas - * <rmthomas--a.t--sciolus.org> - * - * 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. - * - */ - -#include <linux/module.h> -#include <linux/usb.h> -#include <linux/slab.h> -#include <linux/ratelimit.h> - -#include "stk1160.h" - -static unsigned int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "enable debug messages"); - -static inline void print_err_status(struct stk1160 *dev, - int packet, int status) -{ - char *errmsg = "Unknown"; - - switch (status) { - case -ENOENT: - errmsg = "unlinked synchronuously"; - break; - case -ECONNRESET: - errmsg = "unlinked asynchronuously"; - break; - case -ENOSR: - errmsg = "Buffer error (overrun)"; - break; - case -EPIPE: - errmsg = "Stalled (device not responding)"; - break; - case -EOVERFLOW: - errmsg = "Babble (bad cable?)"; - break; - case -EPROTO: - errmsg = "Bit-stuff error (bad cable?)"; - break; - case -EILSEQ: - errmsg = "CRC/Timeout (could be anything)"; - break; - case -ETIME: - errmsg = "Device does not respond"; - break; - } - - if (packet < 0) - printk_ratelimited(KERN_WARNING "URB status %d [%s].\n", - status, errmsg); - else - printk_ratelimited(KERN_INFO "URB packet %d, status %d [%s].\n", - packet, status, errmsg); -} - -static inline -struct stk1160_buffer *stk1160_next_buffer(struct stk1160 *dev) -{ - struct stk1160_buffer *buf = NULL; - unsigned long flags = 0; - - /* Current buffer must be NULL when this functions gets called */ - BUG_ON(dev->isoc_ctl.buf); - - spin_lock_irqsave(&dev->buf_lock, flags); - if (!list_empty(&dev->avail_bufs)) { - buf = list_first_entry(&dev->avail_bufs, - struct stk1160_buffer, list); - list_del(&buf->list); - } - spin_unlock_irqrestore(&dev->buf_lock, flags); - - return buf; -} - -static inline -void stk1160_buffer_done(struct stk1160 *dev) -{ - struct stk1160_buffer *buf = dev->isoc_ctl.buf; - - dev->field_count++; - - buf->vb.v4l2_buf.sequence = dev->field_count >> 1; - buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; - buf->vb.v4l2_buf.bytesused = buf->bytesused; - do_gettimeofday(&buf->vb.v4l2_buf.timestamp); - - vb2_set_plane_payload(&buf->vb, 0, buf->bytesused); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); - - dev->isoc_ctl.buf = NULL; -} - -static inline -void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len) -{ - int linesdone, lineoff, lencopy; - int bytesperline = dev->width * 2; - struct stk1160_buffer *buf = dev->isoc_ctl.buf; - u8 *dst = buf->mem; - int remain; - - /* - * TODO: These stk1160_dbg are very spammy! - * We should 1) check why we are getting them - * and 2) add ratelimit. - * - * UPDATE: One of the reasons (the only one?) for getting these - * is incorrect standard (mismatch between expected and configured). - * So perhaps, we could add a counter for errors. When the counter - * reaches some value, we simply stop streaming. - */ - - len -= 4; - src += 4; - - remain = len; - - linesdone = buf->pos / bytesperline; - lineoff = buf->pos % bytesperline; /* offset in current line */ - - if (!buf->odd) - dst += bytesperline; - - /* Multiply linesdone by two, to take account of the other field */ - dst += linesdone * bytesperline * 2 + lineoff; - - /* Copy the remaining of current line */ - if (remain < (bytesperline - lineoff)) - lencopy = remain; - else - lencopy = bytesperline - lineoff; - - /* - * Check if we have enough space left in the buffer. - * In that case, we force loop exit after copy. - */ - if (lencopy > buf->bytesused - buf->length) { - lencopy = buf->bytesused - buf->length; - remain = lencopy; - } - - /* Check if the copy is done */ - if (lencopy == 0 || remain == 0) - return; - - /* Let the bug hunt begin! sanity checks! */ - if (lencopy < 0) { - stk1160_dbg("copy skipped: negative lencopy\n"); - return; - } - - if ((unsigned long)dst + lencopy > - (unsigned long)buf->mem + buf->length) { - printk_ratelimited(KERN_WARNING "stk1160: buffer overflow detected\n"); - return; - } - - memcpy(dst, src, lencopy); - - buf->bytesused += lencopy; - buf->pos += lencopy; - remain -= lencopy; - - /* Copy current field line by line, interlacing with the other field */ - while (remain > 0) { - - dst += lencopy + bytesperline; - src += lencopy; - - /* Copy one line at a time */ - if (remain < bytesperline) - lencopy = remain; - else - lencopy = bytesperline; - - /* - * Check if we have enough space left in the buffer. - * In that case, we force loop exit after copy. - */ - if (lencopy > buf->bytesused - buf->length) { - lencopy = buf->bytesused - buf->length; - remain = lencopy; - } - - /* Check if the copy is done */ - if (lencopy == 0 || remain == 0) - return; - - if (lencopy < 0) { - printk_ratelimited(KERN_WARNING "stk1160: negative lencopy detected\n"); - return; - } - - if ((unsigned long)dst + lencopy > - (unsigned long)buf->mem + buf->length) { - printk_ratelimited(KERN_WARNING "stk1160: buffer overflow detected\n"); - return; - } - - memcpy(dst, src, lencopy); - remain -= lencopy; - - buf->bytesused += lencopy; - buf->pos += lencopy; - } -} - -/* - * Controls the isoc copy of each urb packet - */ -static void stk1160_process_isoc(struct stk1160 *dev, struct urb *urb) -{ - int i, len, status; - u8 *p; - - if (!dev) { - stk1160_warn("%s called with null device\n", __func__); - return; - } - - if (urb->status < 0) { - /* Print status and drop current packet (or field?) */ - print_err_status(dev, -1, urb->status); - return; - } - - for (i = 0; i < urb->number_of_packets; i++) { - status = urb->iso_frame_desc[i].status; - if (status < 0) { - print_err_status(dev, i, status); - continue; - } - - /* Get packet actual length and pointer to data */ - p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - len = urb->iso_frame_desc[i].actual_length; - - /* Empty packet */ - if (len <= 4) - continue; - - /* - * An 8-byte packet sequence means end of field. - * So if we don't have any packet, we start receiving one now - * and if we do have a packet, then we are done with it. - * - * These end of field packets are always 0xc0 or 0x80, - * but not always 8-byte long so we don't check packet length. - */ - if (p[0] == 0xc0) { - - /* - * If first byte is 0xc0 then we received - * second field, and frame has ended. - */ - if (dev->isoc_ctl.buf != NULL) - stk1160_buffer_done(dev); - - dev->isoc_ctl.buf = stk1160_next_buffer(dev); - if (dev->isoc_ctl.buf == NULL) - return; - } - - /* - * If we don't have a buffer here, then it means we - * haven't found the start mark sequence. - */ - if (dev->isoc_ctl.buf == NULL) - continue; - - if (p[0] == 0xc0 || p[0] == 0x80) { - - /* We set next packet parity and - * continue to get next one - */ - dev->isoc_ctl.buf->odd = *p & 0x40; - dev->isoc_ctl.buf->pos = 0; - continue; - } - - stk1160_copy_video(dev, p, len); - } -} - - -/* - * IRQ callback, called by URB callback - */ -static void stk1160_isoc_irq(struct urb *urb) -{ - int i, rc; - struct stk1160 *dev = urb->context; - - switch (urb->status) { - case 0: - break; - case -ECONNRESET: /* kill */ - case -ENOENT: - case -ESHUTDOWN: - /* TODO: check uvc driver: he frees the queue here */ - return; - default: - stk1160_err("urb error! status %d\n", urb->status); - return; - } - - stk1160_process_isoc(dev, urb); - - /* Reset urb buffers */ - for (i = 0; i < urb->number_of_packets; i++) { - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = 0; - } - - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (rc) - stk1160_err("urb re-submit failed (%d)\n", rc); -} - -/* - * Cancel urbs - * This function can't be called in atomic context - */ -void stk1160_cancel_isoc(struct stk1160 *dev) -{ - int i; - - /* - * This check is not necessary, but we add it - * to avoid a spurious debug message - */ - if (!dev->isoc_ctl.num_bufs) - return; - - stk1160_dbg("killing urbs...\n"); - - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - - /* - * To kill urbs we can't be in atomic context. - * We don't care for NULL pointer since - * usb_kill_urb allows it. - */ - usb_kill_urb(dev->isoc_ctl.urb[i]); - } - - stk1160_dbg("all urbs killed\n"); -} - -/* - * Releases urb and transfer buffers - * Obviusly, associated urb must be killed before releasing it. - */ -void stk1160_free_isoc(struct stk1160 *dev) -{ - struct urb *urb; - int i; - - stk1160_dbg("freeing urb buffers...\n"); - - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - - urb = dev->isoc_ctl.urb[i]; - if (urb) { - - if (dev->isoc_ctl.transfer_buffer[i]) { -#ifndef CONFIG_DMA_NONCOHERENT - usb_free_coherent(dev->udev, - urb->transfer_buffer_length, - dev->isoc_ctl.transfer_buffer[i], - urb->transfer_dma); -#else - kfree(dev->isoc_ctl.transfer_buffer[i]); -#endif - } - usb_free_urb(urb); - dev->isoc_ctl.urb[i] = NULL; - } - dev->isoc_ctl.transfer_buffer[i] = NULL; - } - - kfree(dev->isoc_ctl.urb); - kfree(dev->isoc_ctl.transfer_buffer); - - dev->isoc_ctl.urb = NULL; - dev->isoc_ctl.transfer_buffer = NULL; - dev->isoc_ctl.num_bufs = 0; - - stk1160_dbg("all urb buffers freed\n"); -} - -/* - * Helper for cancelling and freeing urbs - * This function can't be called in atomic context - */ -void stk1160_uninit_isoc(struct stk1160 *dev) -{ - stk1160_cancel_isoc(dev); - stk1160_free_isoc(dev); -} - -/* - * Allocate URBs - */ -int stk1160_alloc_isoc(struct stk1160 *dev) -{ - struct urb *urb; - int i, j, k, sb_size, max_packets, num_bufs; - - /* - * It may be necessary to release isoc here, - * since isoc are only released on disconnection. - * (see new_pkt_size flag) - */ - if (dev->isoc_ctl.num_bufs) - stk1160_uninit_isoc(dev); - - stk1160_dbg("allocating urbs...\n"); - - num_bufs = STK1160_NUM_BUFS; - max_packets = STK1160_NUM_PACKETS; - sb_size = max_packets * dev->max_pkt_size; - - dev->isoc_ctl.buf = NULL; - dev->isoc_ctl.max_pkt_size = dev->max_pkt_size; - dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); - if (!dev->isoc_ctl.urb) { - stk1160_err("out of memory for urb array\n"); - return -ENOMEM; - } - - dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, - GFP_KERNEL); - if (!dev->isoc_ctl.transfer_buffer) { - stk1160_err("out of memory for usb transfers\n"); - kfree(dev->isoc_ctl.urb); - return -ENOMEM; - } - - /* allocate urbs and transfer buffers */ - for (i = 0; i < num_bufs; i++) { - - urb = usb_alloc_urb(max_packets, GFP_KERNEL); - if (!urb) { - stk1160_err("cannot alloc urb[%d]\n", i); - stk1160_uninit_isoc(dev); - return -ENOMEM; - } - dev->isoc_ctl.urb[i] = urb; - -#ifndef CONFIG_DMA_NONCOHERENT - dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev, - sb_size, GFP_KERNEL, &urb->transfer_dma); -#else - dev->isoc_ctl.transfer_buffer[i] = kmalloc(sb_size, GFP_KERNEL); -#endif - if (!dev->isoc_ctl.transfer_buffer[i]) { - stk1160_err("cannot alloc %d bytes for tx buffer\n", - sb_size); - stk1160_uninit_isoc(dev); - return -ENOMEM; - } - memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); - - /* - * FIXME: Where can I get the endpoint? - */ - urb->dev = dev->udev; - urb->pipe = usb_rcvisocpipe(dev->udev, STK1160_EP_VIDEO); - urb->transfer_buffer = dev->isoc_ctl.transfer_buffer[i]; - urb->transfer_buffer_length = sb_size; - urb->complete = stk1160_isoc_irq; - urb->context = dev; - urb->interval = 1; - urb->start_frame = 0; - urb->number_of_packets = max_packets; -#ifndef CONFIG_DMA_NONCOHERENT - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; -#else - urb->transfer_flags = URB_ISO_ASAP; -#endif - - k = 0; - for (j = 0; j < max_packets; j++) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = - dev->isoc_ctl.max_pkt_size; - k += dev->isoc_ctl.max_pkt_size; - } - } - - stk1160_dbg("urbs allocated\n"); - - /* At last we can say we have some buffers */ - dev->isoc_ctl.num_bufs = num_bufs; - - return 0; -} - diff --git a/drivers/media/video/stk1160/stk1160.h b/drivers/media/video/stk1160/stk1160.h deleted file mode 100644 index 3feba0033f98..000000000000 --- a/drivers/media/video/stk1160/stk1160.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * STK1160 driver - * - * Copyright (C) 2012 Ezequiel Garcia - * <elezegarcia--a.t--gmail.com> - * - * Based on Easycap driver by R.M. Thomas - * Copyright (C) 2010 R.M. Thomas - * <rmthomas--a.t--sciolus.org> - * - * 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. - * - */ - -#include <linux/i2c.h> -#include <sound/core.h> -#include <sound/ac97_codec.h> -#include <media/videobuf2-core.h> -#include <media/v4l2-device.h> -#include <media/v4l2-ctrls.h> - -#define STK1160_VERSION "0.9.5" -#define STK1160_VERSION_NUM 0x000905 - -/* TODO: Decide on number of packets for each buffer */ -#define STK1160_NUM_PACKETS 64 - -/* Number of buffers for isoc transfers */ -#define STK1160_NUM_BUFS 16 /* TODO */ - -/* TODO: This endpoint address should be retrieved */ -#define STK1160_EP_VIDEO 0x82 -#define STK1160_EP_AUDIO 0x81 - -/* Max and min video buffers */ -#define STK1160_MIN_VIDEO_BUFFERS 8 -#define STK1160_MAX_VIDEO_BUFFERS 32 - -#define STK1160_MIN_PKT_SIZE 3072 - -#define STK1160_MAX_INPUT 3 - -#define STK1160_I2C_TIMEOUT 100 - -/* TODO: Print helpers - * I could use dev_xxx, pr_xxx, v4l2_xxx or printk. - * However, there isn't a solid consensus on which - * new drivers should use. - * - */ -#define DEBUG -#ifdef DEBUG -#define stk1160_dbg(fmt, args...) \ - printk(KERN_DEBUG "stk1160: " fmt, ## args) -#else -#define stk1160_dbg(fmt, args...) -#endif - -#define stk1160_info(fmt, args...) \ - pr_info("stk1160: " fmt, ## args) - -#define stk1160_warn(fmt, args...) \ - pr_warn("stk1160: " fmt, ## args) - -#define stk1160_err(fmt, args...) \ - pr_err("stk1160: " fmt, ## args) - -/* Buffer for one video frame */ -struct stk1160_buffer { - /* common v4l buffer stuff -- must be first */ - struct vb2_buffer vb; - struct list_head list; - - void *mem; - unsigned int length; /* buffer length */ - unsigned int bytesused; /* bytes written */ - int odd; /* current oddity */ - - /* - * Since we interlace two fields per frame, - * this is different from bytesused. - */ - unsigned int pos; /* current pos inside buffer */ -}; - -struct stk1160_isoc_ctl { - /* max packet size of isoc transaction */ - int max_pkt_size; - - /* number of allocated urbs */ - int num_bufs; - - /* urb for isoc transfers */ - struct urb **urb; - - /* transfer buffers for isoc transfer */ - char **transfer_buffer; - - /* current buffer */ - struct stk1160_buffer *buf; -}; - -struct stk1160_fmt { - char *name; - u32 fourcc; /* v4l2 format id */ - int depth; -}; - -struct stk1160 { - struct v4l2_device v4l2_dev; - struct video_device vdev; - struct v4l2_ctrl_handler ctrl_handler; - - struct device *dev; - struct usb_device *udev; - - /* saa7115 subdev */ - struct v4l2_subdev *sd_saa7115; - - /* isoc control struct */ - struct list_head avail_bufs; - - /* video capture */ - struct vb2_queue vb_vidq; - - /* max packet size of isoc transaction */ - int max_pkt_size; - /* array of wMaxPacketSize */ - unsigned int *alt_max_pkt_size; - /* alternate */ - int alt; - /* Number of alternative settings */ - int num_alt; - - struct stk1160_isoc_ctl isoc_ctl; - char urb_buf[255]; /* urb control msg buffer */ - - /* frame properties */ - int width; /* current frame width */ - int height; /* current frame height */ - unsigned int ctl_input; /* selected input */ - v4l2_std_id norm; /* current norm */ - struct stk1160_fmt *fmt; /* selected format */ - - unsigned int field_count; /* not sure ??? */ - enum v4l2_field field; /* also not sure :/ */ - - /* i2c i/o */ - struct i2c_adapter i2c_adap; - struct i2c_client i2c_client; - - struct mutex v4l_lock; - struct mutex vb_queue_lock; - spinlock_t buf_lock; - - struct file *fh_owner; /* filehandle ownership */ - - /* EXPERIMENTAL */ - struct snd_card *snd_card; -}; - -struct regval { - u16 reg; - u16 val; -}; - -/* Provided by stk1160-v4l.c */ -int stk1160_vb2_setup(struct stk1160 *dev); -int stk1160_video_register(struct stk1160 *dev); -void stk1160_video_unregister(struct stk1160 *dev); -void stk1160_clear_queue(struct stk1160 *dev); - -/* Provided by stk1160-video.c */ -int stk1160_alloc_isoc(struct stk1160 *dev); -void stk1160_free_isoc(struct stk1160 *dev); -void stk1160_cancel_isoc(struct stk1160 *dev); -void stk1160_uninit_isoc(struct stk1160 *dev); - -/* Provided by stk1160-i2c.c */ -int stk1160_i2c_register(struct stk1160 *dev); -int stk1160_i2c_unregister(struct stk1160 *dev); - -/* Provided by stk1160-core.c */ -int stk1160_read_reg(struct stk1160 *dev, u16 reg, u8 *value); -int stk1160_write_reg(struct stk1160 *dev, u16 reg, u16 value); -int stk1160_write_regs_req(struct stk1160 *dev, u8 req, u16 reg, - char *buf, int len); -int stk1160_read_reg_req_len(struct stk1160 *dev, u8 req, u16 reg, - char *buf, int len); -void stk1160_select_input(struct stk1160 *dev); - -/* Provided by stk1160-ac97.c */ -#ifdef CONFIG_VIDEO_STK1160_AC97 -int stk1160_ac97_register(struct stk1160 *dev); -int stk1160_ac97_unregister(struct stk1160 *dev); -#else -static inline int stk1160_ac97_register(struct stk1160 *dev) { return 0; } -static inline int stk1160_ac97_unregister(struct stk1160 *dev) { return 0; } -#endif - diff --git a/drivers/media/video/tlg2300/Kconfig b/drivers/media/video/tlg2300/Kconfig deleted file mode 100644 index 645d915267e6..000000000000 --- a/drivers/media/video/tlg2300/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -config VIDEO_TLG2300 - tristate "Telegent TLG2300 USB video capture support" - depends on VIDEO_DEV && I2C && SND && DVB_CORE - select VIDEO_TUNER - select VIDEO_TVEEPROM - depends on RC_CORE - select VIDEOBUF_VMALLOC - select SND_PCM - select VIDEOBUF_DVB - - ---help--- - This is a video4linux driver for Telegent tlg2300 based TV cards. - The driver supports V4L2, DVB-T and radio. - - To compile this driver as a module, choose M here: the - module will be called poseidon diff --git a/drivers/media/video/tlg2300/Makefile b/drivers/media/video/tlg2300/Makefile deleted file mode 100644 index 4d660879999f..000000000000 --- a/drivers/media/video/tlg2300/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -poseidon-objs := pd-video.o pd-alsa.o pd-dvb.o pd-radio.o pd-main.o - -obj-$(CONFIG_VIDEO_TLG2300) += poseidon.o - -ccflags-y += -Idrivers/media/video -ccflags-y += -Idrivers/media/tuners -ccflags-y += -Idrivers/media/dvb-core -ccflags-y += -Idrivers/media/dvb-frontends - diff --git a/drivers/media/video/tlg2300/pd-alsa.c b/drivers/media/video/tlg2300/pd-alsa.c deleted file mode 100644 index 9f8b7da56b67..000000000000 --- a/drivers/media/video/tlg2300/pd-alsa.c +++ /dev/null @@ -1,332 +0,0 @@ -#include <linux/kernel.h> -#include <linux/usb.h> -#include <linux/init.h> -#include <linux/sound.h> -#include <linux/spinlock.h> -#include <linux/soundcard.h> -#include <linux/vmalloc.h> -#include <linux/proc_fs.h> -#include <linux/module.h> -#include <linux/gfp.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/info.h> -#include <sound/initval.h> -#include <sound/control.h> -#include <media/v4l2-common.h> -#include "pd-common.h" -#include "vendorcmds.h" - -static void complete_handler_audio(struct urb *urb); -#define AUDIO_EP (0x83) -#define AUDIO_BUF_SIZE (512) -#define PERIOD_SIZE (1024 * 8) -#define PERIOD_MIN (4) -#define PERIOD_MAX PERIOD_MIN - -static struct snd_pcm_hardware snd_pd_hw_capture = { - .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID, - - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = PERIOD_SIZE * PERIOD_MIN, - .period_bytes_min = PERIOD_SIZE, - .period_bytes_max = PERIOD_SIZE, - .periods_min = PERIOD_MIN, - .periods_max = PERIOD_MAX, - /* - .buffer_bytes_max = 62720 * 8, - .period_bytes_min = 64, - .period_bytes_max = 12544, - .periods_min = 2, - .periods_max = 98 - */ -}; - -static int snd_pd_capture_open(struct snd_pcm_substream *substream) -{ - struct poseidon *p = snd_pcm_substream_chip(substream); - struct poseidon_audio *pa = &p->audio; - struct snd_pcm_runtime *runtime = substream->runtime; - - if (!p) - return -ENODEV; - pa->users++; - pa->card_close = 0; - pa->capture_pcm_substream = substream; - runtime->private_data = p; - - runtime->hw = snd_pd_hw_capture; - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - usb_autopm_get_interface(p->interface); - kref_get(&p->kref); - return 0; -} - -static int snd_pd_pcm_close(struct snd_pcm_substream *substream) -{ - struct poseidon *p = snd_pcm_substream_chip(substream); - struct poseidon_audio *pa = &p->audio; - - pa->users--; - pa->card_close = 1; - usb_autopm_put_interface(p->interface); - kref_put(&p->kref, poseidon_delete); - return 0; -} - -static int snd_pd_hw_capture_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int size; - - size = params_buffer_bytes(hw_params); - if (runtime->dma_area) { - if (runtime->dma_bytes > size) - return 0; - vfree(runtime->dma_area); - } - runtime->dma_area = vmalloc(size); - if (!runtime->dma_area) - return -ENOMEM; - else - runtime->dma_bytes = size; - return 0; -} - -static int audio_buf_free(struct poseidon *p) -{ - struct poseidon_audio *pa = &p->audio; - int i; - - for (i = 0; i < AUDIO_BUFS; i++) - if (pa->urb_array[i]) - usb_kill_urb(pa->urb_array[i]); - free_all_urb_generic(pa->urb_array, AUDIO_BUFS); - logpm(); - return 0; -} - -static int snd_pd_hw_capture_free(struct snd_pcm_substream *substream) -{ - struct poseidon *p = snd_pcm_substream_chip(substream); - - logpm(); - audio_buf_free(p); - return 0; -} - -static int snd_pd_prepare(struct snd_pcm_substream *substream) -{ - return 0; -} - -#define AUDIO_TRAILER_SIZE (16) -static inline void handle_audio_data(struct urb *urb, int *period_elapsed) -{ - struct poseidon_audio *pa = urb->context; - struct snd_pcm_runtime *runtime = pa->capture_pcm_substream->runtime; - - int stride = runtime->frame_bits >> 3; - int len = urb->actual_length / stride; - unsigned char *cp = urb->transfer_buffer; - unsigned int oldptr = pa->rcv_position; - - if (urb->actual_length == AUDIO_BUF_SIZE - 4) - len -= (AUDIO_TRAILER_SIZE / stride); - - /* do the copy */ - if (oldptr + len >= runtime->buffer_size) { - unsigned int cnt = runtime->buffer_size - oldptr; - - memcpy(runtime->dma_area + oldptr * stride, cp, cnt * stride); - memcpy(runtime->dma_area, (cp + cnt * stride), - (len * stride - cnt * stride)); - } else - memcpy(runtime->dma_area + oldptr * stride, cp, len * stride); - - /* update the statas */ - snd_pcm_stream_lock(pa->capture_pcm_substream); - pa->rcv_position += len; - if (pa->rcv_position >= runtime->buffer_size) - pa->rcv_position -= runtime->buffer_size; - - pa->copied_position += (len); - if (pa->copied_position >= runtime->period_size) { - pa->copied_position -= runtime->period_size; - *period_elapsed = 1; - } - snd_pcm_stream_unlock(pa->capture_pcm_substream); -} - -static void complete_handler_audio(struct urb *urb) -{ - struct poseidon_audio *pa = urb->context; - struct snd_pcm_substream *substream = pa->capture_pcm_substream; - int period_elapsed = 0; - int ret; - - if (1 == pa->card_close || pa->capture_stream != STREAM_ON) - return; - - if (urb->status != 0) { - /*if (urb->status == -ESHUTDOWN)*/ - return; - } - - if (substream) { - if (urb->actual_length) { - handle_audio_data(urb, &period_elapsed); - if (period_elapsed) - snd_pcm_period_elapsed(substream); - } - } - - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret < 0) - log("audio urb failed (errcod = %i)", ret); - return; -} - -static int fire_audio_urb(struct poseidon *p) -{ - int i, ret = 0; - struct poseidon_audio *pa = &p->audio; - - alloc_bulk_urbs_generic(pa->urb_array, AUDIO_BUFS, - p->udev, AUDIO_EP, - AUDIO_BUF_SIZE, GFP_ATOMIC, - complete_handler_audio, pa); - - for (i = 0; i < AUDIO_BUFS; i++) { - ret = usb_submit_urb(pa->urb_array[i], GFP_KERNEL); - if (ret) - log("urb err : %d", ret); - } - log(); - return ret; -} - -static int snd_pd_capture_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct poseidon *p = snd_pcm_substream_chip(substream); - struct poseidon_audio *pa = &p->audio; - - if (debug_mode) - log("cmd %d, audio stat : %d\n", cmd, pa->capture_stream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_START: - if (pa->capture_stream == STREAM_ON) - return 0; - - pa->rcv_position = pa->copied_position = 0; - pa->capture_stream = STREAM_ON; - - if (in_hibernation(p)) - return 0; - fire_audio_urb(p); - return 0; - - case SNDRV_PCM_TRIGGER_SUSPEND: - pa->capture_stream = STREAM_SUSPEND; - return 0; - case SNDRV_PCM_TRIGGER_STOP: - pa->capture_stream = STREAM_OFF; - return 0; - default: - return -EINVAL; - } -} - -static snd_pcm_uframes_t -snd_pd_capture_pointer(struct snd_pcm_substream *substream) -{ - struct poseidon *p = snd_pcm_substream_chip(substream); - struct poseidon_audio *pa = &p->audio; - return pa->rcv_position; -} - -static struct page *snd_pcm_pd_get_page(struct snd_pcm_substream *subs, - unsigned long offset) -{ - void *pageptr = subs->runtime->dma_area + offset; - return vmalloc_to_page(pageptr); -} - -static struct snd_pcm_ops pcm_capture_ops = { - .open = snd_pd_capture_open, - .close = snd_pd_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_pd_hw_capture_params, - .hw_free = snd_pd_hw_capture_free, - .prepare = snd_pd_prepare, - .trigger = snd_pd_capture_trigger, - .pointer = snd_pd_capture_pointer, - .page = snd_pcm_pd_get_page, -}; - -#ifdef CONFIG_PM -int pm_alsa_suspend(struct poseidon *p) -{ - logpm(p); - audio_buf_free(p); - return 0; -} - -int pm_alsa_resume(struct poseidon *p) -{ - logpm(p); - fire_audio_urb(p); - return 0; -} -#endif - -int poseidon_audio_init(struct poseidon *p) -{ - struct poseidon_audio *pa = &p->audio; - struct snd_card *card; - struct snd_pcm *pcm; - int ret; - - ret = snd_card_create(-1, "Telegent", THIS_MODULE, 0, &card); - if (ret != 0) - return ret; - - ret = snd_pcm_new(card, "poseidon audio", 0, 0, 1, &pcm); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops); - pcm->info_flags = 0; - pcm->private_data = p; - strcpy(pcm->name, "poseidon audio capture"); - - strcpy(card->driver, "ALSA driver"); - strcpy(card->shortname, "poseidon Audio"); - strcpy(card->longname, "poseidon ALSA Audio"); - - if (snd_card_register(card)) { - snd_card_free(card); - return -ENOMEM; - } - pa->card = card; - return 0; -} - -int poseidon_audio_free(struct poseidon *p) -{ - struct poseidon_audio *pa = &p->audio; - - if (pa->card) - snd_card_free(pa->card); - return 0; -} diff --git a/drivers/media/video/tlg2300/pd-common.h b/drivers/media/video/tlg2300/pd-common.h deleted file mode 100644 index 5dd73b7857d1..000000000000 --- a/drivers/media/video/tlg2300/pd-common.h +++ /dev/null @@ -1,281 +0,0 @@ -#ifndef PD_COMMON_H -#define PD_COMMON_H - -#include <linux/fs.h> -#include <linux/wait.h> -#include <linux/list.h> -#include <linux/videodev2.h> -#include <linux/semaphore.h> -#include <linux/usb.h> -#include <linux/poll.h> -#include <media/videobuf-vmalloc.h> -#include <media/v4l2-device.h> - -#include "dvb_frontend.h" -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dmxdev.h" - -#define SBUF_NUM 8 -#define MAX_BUFFER_NUM 6 -#define PK_PER_URB 32 -#define ISO_PKT_SIZE 3072 - -#define POSEIDON_STATE_NONE (0x0000) -#define POSEIDON_STATE_ANALOG (0x0001) -#define POSEIDON_STATE_FM (0x0002) -#define POSEIDON_STATE_DVBT (0x0004) -#define POSEIDON_STATE_VBI (0x0008) -#define POSEIDON_STATE_DISCONNECT (0x0080) - -#define PM_SUSPEND_DELAY 3 - -#define V4L_PAL_VBI_LINES 18 -#define V4L_NTSC_VBI_LINES 12 -#define V4L_PAL_VBI_FRAMESIZE (V4L_PAL_VBI_LINES * 1440 * 2) -#define V4L_NTSC_VBI_FRAMESIZE (V4L_NTSC_VBI_LINES * 1440 * 2) - -#define TUNER_FREQ_MIN (45000000) -#define TUNER_FREQ_MAX (862000000) - -struct vbi_data { - struct video_device *v_dev; - struct video_data *video; - struct front_face *front; - - unsigned int copied; - unsigned int vbi_size; /* the whole size of two fields */ - int users; -}; - -/* - * This is the running context of the video, it is useful for - * resume() - */ -struct running_context { - u32 freq; /* VIDIOC_S_FREQUENCY */ - int audio_idx; /* VIDIOC_S_TUNER */ - v4l2_std_id tvnormid; /* VIDIOC_S_STD */ - int sig_index; /* VIDIOC_S_INPUT */ - struct v4l2_pix_format pix; /* VIDIOC_S_FMT */ -}; - -struct video_data { - /* v4l2 video device */ - struct video_device *v_dev; - - /* the working context */ - struct running_context context; - - /* for data copy */ - int field_count; - - char *dst; - int lines_copied; - int prev_left; - - int lines_per_field; - int lines_size; - - /* for communication */ - u8 endpoint_addr; - struct urb *urb_array[SBUF_NUM]; - struct vbi_data *vbi; - struct poseidon *pd; - struct front_face *front; - - int is_streaming; - int users; - - /* for bubble handler */ - struct work_struct bubble_work; -}; - -enum pcm_stream_state { - STREAM_OFF, - STREAM_ON, - STREAM_SUSPEND, -}; - -#define AUDIO_BUFS (3) -#define CAPTURE_STREAM_EN 1 -struct poseidon_audio { - struct urb *urb_array[AUDIO_BUFS]; - unsigned int copied_position; - struct snd_pcm_substream *capture_pcm_substream; - - unsigned int rcv_position; - struct snd_card *card; - int card_close; - - int users; - int pm_state; - enum pcm_stream_state capture_stream; -}; - -struct radio_data { - __u32 fm_freq; - int users; - unsigned int is_radio_streaming; - int pre_emphasis; - struct video_device *fm_dev; -}; - -#define DVB_SBUF_NUM 4 -#define DVB_URB_BUF_SIZE 0x2000 -struct pd_dvb_adapter { - struct dvb_adapter dvb_adap; - struct dvb_frontend dvb_fe; - struct dmxdev dmxdev; - struct dvb_demux demux; - - atomic_t users; - atomic_t active_feed; - - /* data transfer */ - s32 is_streaming; - struct urb *urb_array[DVB_SBUF_NUM]; - struct poseidon *pd_device; - u8 ep_addr; - u8 reserved[3]; - - /* data for power resume*/ - struct dtv_frontend_properties fe_param; - - /* for channel scanning */ - int prev_freq; - int bandwidth; - unsigned long last_jiffies; -}; - -struct front_face { - /* use this field to distinguish VIDEO and VBI */ - enum v4l2_buf_type type; - - /* for host */ - struct videobuf_queue q; - - /* the bridge for host and device */ - struct videobuf_buffer *curr_frame; - - /* for device */ - spinlock_t queue_lock; - struct list_head active; - struct poseidon *pd; -}; - -struct poseidon { - struct list_head device_list; - - struct mutex lock; - struct kref kref; - - /* for V4L2 */ - struct v4l2_device v4l2_dev; - - /* hardware info */ - struct usb_device *udev; - struct usb_interface *interface; - int cur_transfer_mode; - - struct video_data video_data; /* video */ - struct vbi_data vbi_data; /* vbi */ - struct poseidon_audio audio; /* audio (alsa) */ - struct radio_data radio_data; /* FM */ - struct pd_dvb_adapter dvb_data; /* DVB */ - - u32 state; - struct file *file_for_stream; /* the active stream*/ - -#ifdef CONFIG_PM - int (*pm_suspend)(struct poseidon *); - int (*pm_resume)(struct poseidon *); - pm_message_t msg; - - struct work_struct pm_work; - u8 portnum; -#endif -}; - -struct poseidon_format { - char *name; - int fourcc; /* video4linux 2 */ - int depth; /* bit/pixel */ - int flags; -}; - -struct poseidon_tvnorm { - v4l2_std_id v4l2_id; - char name[12]; - u32 tlg_tvnorm; -}; - -/* video */ -int pd_video_init(struct poseidon *); -void pd_video_exit(struct poseidon *); -int stop_all_video_stream(struct poseidon *); - -/* alsa audio */ -int poseidon_audio_init(struct poseidon *); -int poseidon_audio_free(struct poseidon *); -#ifdef CONFIG_PM -int pm_alsa_suspend(struct poseidon *); -int pm_alsa_resume(struct poseidon *); -#endif - -/* dvb */ -int pd_dvb_usb_device_init(struct poseidon *); -void pd_dvb_usb_device_exit(struct poseidon *); -void pd_dvb_usb_device_cleanup(struct poseidon *); -int pd_dvb_get_adapter_num(struct pd_dvb_adapter *); -void dvb_stop_streaming(struct pd_dvb_adapter *); - -/* FM */ -int poseidon_fm_init(struct poseidon *); -int poseidon_fm_exit(struct poseidon *); -struct video_device *vdev_init(struct poseidon *, struct video_device *); - -/* vendor command ops */ -int send_set_req(struct poseidon*, u8, s32, s32*); -int send_get_req(struct poseidon*, u8, s32, void*, s32*, s32); -s32 set_tuner_mode(struct poseidon*, unsigned char); - -/* bulk urb alloc/free */ -int alloc_bulk_urbs_generic(struct urb **urb_array, int num, - struct usb_device *udev, u8 ep_addr, - int buf_size, gfp_t gfp_flags, - usb_complete_t complete_fn, void *context); -void free_all_urb_generic(struct urb **urb_array, int num); - -/* misc */ -void poseidon_delete(struct kref *kref); -void destroy_video_device(struct video_device **v_dev); -extern int debug_mode; -void set_debug_mode(struct video_device *vfd, int debug_mode); - -#ifdef CONFIG_PM -#define in_hibernation(pd) (pd->msg.event == PM_EVENT_FREEZE) -#else -#define in_hibernation(pd) (0) -#endif -#define get_pm_count(p) (atomic_read(&(p)->interface->pm_usage_cnt)) - -#define log(a, ...) printk(KERN_DEBUG "\t[ %s : %.3d ] "a"\n", \ - __func__, __LINE__, ## __VA_ARGS__) - -/* for power management */ -#define logpm(pd) do {\ - if (debug_mode & 0x10)\ - log();\ - } while (0) - -#define logs(f) do { \ - if ((debug_mode & 0x4) && \ - (f)->type == V4L2_BUF_TYPE_VBI_CAPTURE) \ - log("type : VBI");\ - \ - if ((debug_mode & 0x8) && \ - (f)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) \ - log("type : VIDEO");\ - } while (0) -#endif diff --git a/drivers/media/video/tlg2300/pd-dvb.c b/drivers/media/video/tlg2300/pd-dvb.c deleted file mode 100644 index 30fcb117e898..000000000000 --- a/drivers/media/video/tlg2300/pd-dvb.c +++ /dev/null @@ -1,596 +0,0 @@ -#include "pd-common.h" -#include <linux/kernel.h> -#include <linux/usb.h> -#include <linux/dvb/dmx.h> -#include <linux/delay.h> -#include <linux/gfp.h> - -#include "vendorcmds.h" -#include <linux/sched.h> -#include <linux/atomic.h> - -static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb); - -static int dvb_bandwidth[][2] = { - { TLG_BW_8, 8000000 }, - { TLG_BW_7, 7000000 }, - { TLG_BW_6, 6000000 } -}; -static int dvb_bandwidth_length = ARRAY_SIZE(dvb_bandwidth); - -static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb); -static int poseidon_check_mode_dvbt(struct poseidon *pd) -{ - s32 ret = 0, cmd_status = 0; - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); - - ret = usb_set_interface(pd->udev, 0, BULK_ALTERNATE_IFACE); - if (ret != 0) - return ret; - - ret = set_tuner_mode(pd, TLG_MODE_CAPS_DVB_T); - if (ret) - return ret; - - /* signal source */ - ret = send_set_req(pd, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &cmd_status); - if (ret|cmd_status) - return ret; - - return 0; -} - -/* acquire : - * 1 == open - * 0 == release - */ -static int poseidon_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) -{ - struct poseidon *pd = fe->demodulator_priv; - struct pd_dvb_adapter *pd_dvb; - int ret = 0; - - if (!pd) - return -ENODEV; - - pd_dvb = container_of(fe, struct pd_dvb_adapter, dvb_fe); - if (acquire) { - mutex_lock(&pd->lock); - if (pd->state & POSEIDON_STATE_DISCONNECT) { - ret = -ENODEV; - goto open_out; - } - - if (pd->state && !(pd->state & POSEIDON_STATE_DVBT)) { - ret = -EBUSY; - goto open_out; - } - - usb_autopm_get_interface(pd->interface); - if (0 == pd->state) { - ret = poseidon_check_mode_dvbt(pd); - if (ret < 0) { - usb_autopm_put_interface(pd->interface); - goto open_out; - } - pd->state |= POSEIDON_STATE_DVBT; - pd_dvb->bandwidth = 0; - pd_dvb->prev_freq = 0; - } - atomic_inc(&pd_dvb->users); - kref_get(&pd->kref); -open_out: - mutex_unlock(&pd->lock); - } else { - dvb_stop_streaming(pd_dvb); - - if (atomic_dec_and_test(&pd_dvb->users)) { - mutex_lock(&pd->lock); - pd->state &= ~POSEIDON_STATE_DVBT; - mutex_unlock(&pd->lock); - } - kref_put(&pd->kref, poseidon_delete); - usb_autopm_put_interface(pd->interface); - } - return ret; -} - -#ifdef CONFIG_PM -static void poseidon_fe_release(struct dvb_frontend *fe) -{ - struct poseidon *pd = fe->demodulator_priv; - - pd->pm_suspend = NULL; - pd->pm_resume = NULL; -} -#else -#define poseidon_fe_release NULL -#endif - -static s32 poseidon_fe_sleep(struct dvb_frontend *fe) -{ - return 0; -} - -/* - * return true if we can satisfy the conditions, else return false. - */ -static bool check_scan_ok(__u32 freq, int bandwidth, - struct pd_dvb_adapter *adapter) -{ - if (bandwidth < 0) - return false; - - if (adapter->prev_freq == freq - && adapter->bandwidth == bandwidth) { - long nl = jiffies - adapter->last_jiffies; - unsigned int msec ; - - msec = jiffies_to_msecs(abs(nl)); - return msec > 15000 ? true : false; - } - return true; -} - -/* - * Check if the firmware delays too long for an invalid frequency. - */ -static int fw_delay_overflow(struct pd_dvb_adapter *adapter) -{ - long nl = jiffies - adapter->last_jiffies; - unsigned int msec ; - - msec = jiffies_to_msecs(abs(nl)); - return msec > 800 ? true : false; -} - -static int poseidon_set_fe(struct dvb_frontend *fe) -{ - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; - s32 ret = 0, cmd_status = 0; - s32 i, bandwidth = -1; - struct poseidon *pd = fe->demodulator_priv; - struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; - - if (in_hibernation(pd)) - return -EBUSY; - - mutex_lock(&pd->lock); - for (i = 0; i < dvb_bandwidth_length; i++) - if (fep->bandwidth_hz == dvb_bandwidth[i][1]) - bandwidth = dvb_bandwidth[i][0]; - - if (check_scan_ok(fep->frequency, bandwidth, pd_dvb)) { - ret = send_set_req(pd, TUNE_FREQ_SELECT, - fep->frequency / 1000, &cmd_status); - if (ret | cmd_status) { - log("error line"); - goto front_out; - } - - ret = send_set_req(pd, DVBT_BANDW_SEL, - bandwidth, &cmd_status); - if (ret | cmd_status) { - log("error line"); - goto front_out; - } - - ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); - if (ret | cmd_status) { - log("error line"); - goto front_out; - } - - /* save the context for future */ - memcpy(&pd_dvb->fe_param, fep, sizeof(*fep)); - pd_dvb->bandwidth = bandwidth; - pd_dvb->prev_freq = fep->frequency; - pd_dvb->last_jiffies = jiffies; - } -front_out: - mutex_unlock(&pd->lock); - return ret; -} - -#ifdef CONFIG_PM -static int pm_dvb_suspend(struct poseidon *pd) -{ - struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; - dvb_stop_streaming(pd_dvb); - dvb_urb_cleanup(pd_dvb); - msleep(500); - return 0; -} - -static int pm_dvb_resume(struct poseidon *pd) -{ - struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; - - poseidon_check_mode_dvbt(pd); - msleep(300); - poseidon_set_fe(&pd_dvb->dvb_fe); - - dvb_start_streaming(pd_dvb); - return 0; -} -#endif - -static s32 poseidon_fe_init(struct dvb_frontend *fe) -{ - struct poseidon *pd = fe->demodulator_priv; - struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; - -#ifdef CONFIG_PM - pd->pm_suspend = pm_dvb_suspend; - pd->pm_resume = pm_dvb_resume; -#endif - memset(&pd_dvb->fe_param, 0, - sizeof(struct dtv_frontend_properties)); - return 0; -} - -static int poseidon_get_fe(struct dvb_frontend *fe) -{ - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; - struct poseidon *pd = fe->demodulator_priv; - struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; - - memcpy(fep, &pd_dvb->fe_param, sizeof(*fep)); - return 0; -} - -static int poseidon_fe_get_tune_settings(struct dvb_frontend *fe, - struct dvb_frontend_tune_settings *tune) -{ - tune->min_delay_ms = 1000; - return 0; -} - -static int poseidon_read_status(struct dvb_frontend *fe, fe_status_t *stat) -{ - struct poseidon *pd = fe->demodulator_priv; - s32 ret = -1, cmd_status; - struct tuner_dtv_sig_stat_s status = {}; - - if (in_hibernation(pd)) - return -EBUSY; - mutex_lock(&pd->lock); - - ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_DVB_T, - &status, &cmd_status, sizeof(status)); - if (ret | cmd_status) { - log("get tuner status error"); - goto out; - } - - if (debug_mode) - log("P : %d, L %d, LB :%d", status.sig_present, - status.sig_locked, status.sig_lock_busy); - - if (status.sig_lock_busy) { - goto out; - } else if (status.sig_present || status.sig_locked) { - *stat |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER - | FE_HAS_SYNC | FE_HAS_VITERBI; - } else { - if (fw_delay_overflow(&pd->dvb_data)) - *stat |= FE_TIMEDOUT; - } -out: - mutex_unlock(&pd->lock); - return ret; -} - -static int poseidon_read_ber(struct dvb_frontend *fe, u32 *ber) -{ - struct poseidon *pd = fe->demodulator_priv; - struct tuner_ber_rate_s tlg_ber = {}; - s32 ret = -1, cmd_status; - - mutex_lock(&pd->lock); - ret = send_get_req(pd, TUNER_BER_RATE, 0, - &tlg_ber, &cmd_status, sizeof(tlg_ber)); - if (ret | cmd_status) - goto out; - *ber = tlg_ber.ber_rate; -out: - mutex_unlock(&pd->lock); - return ret; -} - -static s32 poseidon_read_signal_strength(struct dvb_frontend *fe, u16 *strength) -{ - struct poseidon *pd = fe->demodulator_priv; - struct tuner_dtv_sig_stat_s status = {}; - s32 ret = 0, cmd_status; - - mutex_lock(&pd->lock); - ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_DVB_T, - &status, &cmd_status, sizeof(status)); - if (ret | cmd_status) - goto out; - if ((status.sig_present || status.sig_locked) && !status.sig_strength) - *strength = 0xFFFF; - else - *strength = status.sig_strength; -out: - mutex_unlock(&pd->lock); - return ret; -} - -static int poseidon_read_snr(struct dvb_frontend *fe, u16 *snr) -{ - return 0; -} - -static int poseidon_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) -{ - *unc = 0; - return 0; -} - -static struct dvb_frontend_ops poseidon_frontend_ops = { - .delsys = { SYS_DVBT }, - .info = { - .name = "Poseidon DVB-T", - .frequency_min = 174000000, - .frequency_max = 862000000, - .frequency_stepsize = 62500,/* FIXME */ - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | - FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | - FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_RECOVER | - FE_CAN_HIERARCHY_AUTO, - }, - - .release = poseidon_fe_release, - - .init = poseidon_fe_init, - .sleep = poseidon_fe_sleep, - - .set_frontend = poseidon_set_fe, - .get_frontend = poseidon_get_fe, - .get_tune_settings = poseidon_fe_get_tune_settings, - - .read_status = poseidon_read_status, - .read_ber = poseidon_read_ber, - .read_signal_strength = poseidon_read_signal_strength, - .read_snr = poseidon_read_snr, - .read_ucblocks = poseidon_read_unc_blocks, - - .ts_bus_ctrl = poseidon_ts_bus_ctrl, -}; - -static void dvb_urb_irq(struct urb *urb) -{ - struct pd_dvb_adapter *pd_dvb = urb->context; - int len = urb->transfer_buffer_length; - struct dvb_demux *demux = &pd_dvb->demux; - s32 ret; - - if (!pd_dvb->is_streaming || urb->status) { - if (urb->status == -EPROTO) - goto resend; - return; - } - - if (urb->actual_length == len) - dvb_dmx_swfilter(demux, urb->transfer_buffer, len); - else if (urb->actual_length == len - 4) { - int offset; - u8 *buf = urb->transfer_buffer; - - /* - * The packet size is 512, - * last packet contains 456 bytes tsp data - */ - for (offset = 456; offset < len; offset += 512) { - if (!strncmp(buf + offset, "DVHS", 4)) { - dvb_dmx_swfilter(demux, buf, offset); - if (len > offset + 52 + 4) { - /*16 bytes trailer + 36 bytes padding */ - buf += offset + 52; - len -= offset + 52 + 4; - dvb_dmx_swfilter(demux, buf, len); - } - break; - } - } - } - -resend: - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) - log(" usb_submit_urb failed: error %d", ret); -} - -static int dvb_urb_init(struct pd_dvb_adapter *pd_dvb) -{ - if (pd_dvb->urb_array[0]) - return 0; - - alloc_bulk_urbs_generic(pd_dvb->urb_array, DVB_SBUF_NUM, - pd_dvb->pd_device->udev, pd_dvb->ep_addr, - DVB_URB_BUF_SIZE, GFP_KERNEL, - dvb_urb_irq, pd_dvb); - return 0; -} - -static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb) -{ - free_all_urb_generic(pd_dvb->urb_array, DVB_SBUF_NUM); -} - -static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb) -{ - struct poseidon *pd = pd_dvb->pd_device; - int ret = 0; - - if (pd->state & POSEIDON_STATE_DISCONNECT) - return -ENODEV; - - mutex_lock(&pd->lock); - if (!pd_dvb->is_streaming) { - s32 i, cmd_status = 0; - /* - * Once upon a time, there was a difficult bug lying here. - * ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); - */ - - ret = send_set_req(pd, PLAY_SERVICE, 1, &cmd_status); - if (ret | cmd_status) - goto out; - - ret = dvb_urb_init(pd_dvb); - if (ret < 0) - goto out; - - pd_dvb->is_streaming = 1; - for (i = 0; i < DVB_SBUF_NUM; i++) { - ret = usb_submit_urb(pd_dvb->urb_array[i], - GFP_KERNEL); - if (ret) { - log(" submit urb error %d", ret); - goto out; - } - } - } -out: - mutex_unlock(&pd->lock); - return ret; -} - -void dvb_stop_streaming(struct pd_dvb_adapter *pd_dvb) -{ - struct poseidon *pd = pd_dvb->pd_device; - - mutex_lock(&pd->lock); - if (pd_dvb->is_streaming) { - s32 i, ret, cmd_status = 0; - - pd_dvb->is_streaming = 0; - - for (i = 0; i < DVB_SBUF_NUM; i++) - if (pd_dvb->urb_array[i]) - usb_kill_urb(pd_dvb->urb_array[i]); - - ret = send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, - &cmd_status); - if (ret | cmd_status) - log("error"); - } - mutex_unlock(&pd->lock); -} - -static int pd_start_feed(struct dvb_demux_feed *feed) -{ - struct pd_dvb_adapter *pd_dvb = feed->demux->priv; - int ret = 0; - - if (!pd_dvb) - return -1; - if (atomic_inc_return(&pd_dvb->active_feed) == 1) - ret = dvb_start_streaming(pd_dvb); - return ret; -} - -static int pd_stop_feed(struct dvb_demux_feed *feed) -{ - struct pd_dvb_adapter *pd_dvb = feed->demux->priv; - - if (!pd_dvb) - return -1; - if (atomic_dec_and_test(&pd_dvb->active_feed)) - dvb_stop_streaming(pd_dvb); - return 0; -} - -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -int pd_dvb_usb_device_init(struct poseidon *pd) -{ - struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; - struct dvb_demux *dvbdemux; - int ret = 0; - - pd_dvb->ep_addr = 0x82; - atomic_set(&pd_dvb->users, 0); - atomic_set(&pd_dvb->active_feed, 0); - pd_dvb->pd_device = pd; - - ret = dvb_register_adapter(&pd_dvb->dvb_adap, - "Poseidon dvbt adapter", - THIS_MODULE, - NULL /* for hibernation correctly*/, - adapter_nr); - if (ret < 0) - goto error1; - - /* register frontend */ - pd_dvb->dvb_fe.demodulator_priv = pd; - memcpy(&pd_dvb->dvb_fe.ops, &poseidon_frontend_ops, - sizeof(struct dvb_frontend_ops)); - ret = dvb_register_frontend(&pd_dvb->dvb_adap, &pd_dvb->dvb_fe); - if (ret < 0) - goto error2; - - /* register demux device */ - dvbdemux = &pd_dvb->demux; - dvbdemux->dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; - dvbdemux->priv = pd_dvb; - dvbdemux->feednum = dvbdemux->filternum = 64; - dvbdemux->start_feed = pd_start_feed; - dvbdemux->stop_feed = pd_stop_feed; - dvbdemux->write_to_decoder = NULL; - - ret = dvb_dmx_init(dvbdemux); - if (ret < 0) - goto error3; - - pd_dvb->dmxdev.filternum = pd_dvb->demux.filternum; - pd_dvb->dmxdev.demux = &pd_dvb->demux.dmx; - pd_dvb->dmxdev.capabilities = 0; - - ret = dvb_dmxdev_init(&pd_dvb->dmxdev, &pd_dvb->dvb_adap); - if (ret < 0) - goto error3; - return 0; - -error3: - dvb_unregister_frontend(&pd_dvb->dvb_fe); -error2: - dvb_unregister_adapter(&pd_dvb->dvb_adap); -error1: - return ret; -} - -void pd_dvb_usb_device_exit(struct poseidon *pd) -{ - struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; - - while (atomic_read(&pd_dvb->users) != 0 - || atomic_read(&pd_dvb->active_feed) != 0) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); - } - dvb_dmxdev_release(&pd_dvb->dmxdev); - dvb_unregister_frontend(&pd_dvb->dvb_fe); - dvb_unregister_adapter(&pd_dvb->dvb_adap); - pd_dvb_usb_device_cleanup(pd); -} - -void pd_dvb_usb_device_cleanup(struct poseidon *pd) -{ - struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; - - dvb_urb_cleanup(pd_dvb); -} - -int pd_dvb_get_adapter_num(struct pd_dvb_adapter *pd_dvb) -{ - return pd_dvb->dvb_adap.num; -} diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c deleted file mode 100644 index 7b1f6ebd0e2c..000000000000 --- a/drivers/media/video/tlg2300/pd-main.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - * device driver for Telegent tlg2300 based TV cards - * - * Author : - * Kang Yong <kangyong@telegent.com> - * Zhang Xiaobing <xbzhang@telegent.com> - * Huang Shijie <zyziii@telegent.com> or <shijie8@gmail.com> - * - * (c) 2009 Telegent Systems - * (c) 2010 Telegent Systems - * - * 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 <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/kref.h> -#include <linux/suspend.h> -#include <linux/usb/quirks.h> -#include <linux/ctype.h> -#include <linux/string.h> -#include <linux/types.h> -#include <linux/firmware.h> - -#include "vendorcmds.h" -#include "pd-common.h" - -#define VENDOR_ID 0x1B24 -#define PRODUCT_ID 0x4001 -static struct usb_device_id id_table[] = { - { USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 0) }, - { USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 1) }, - { }, -}; -MODULE_DEVICE_TABLE(usb, id_table); - -int debug_mode; -module_param(debug_mode, int, 0644); -MODULE_PARM_DESC(debug_mode, "0 = disable, 1 = enable, 2 = verbose"); - -#define TLG2300_FIRMWARE "tlg2300_firmware.bin" -static const char *firmware_name = TLG2300_FIRMWARE; -static struct usb_driver poseidon_driver; -static LIST_HEAD(pd_device_list); - -/* - * send set request to USB firmware. - */ -s32 send_set_req(struct poseidon *pd, u8 cmdid, s32 param, s32 *cmd_status) -{ - s32 ret; - s8 data[32] = {}; - u16 lower_16, upper_16; - - if (pd->state & POSEIDON_STATE_DISCONNECT) - return -ENODEV; - - mdelay(30); - - if (param == 0) { - upper_16 = lower_16 = 0; - } else { - /* send 32 bit param as two 16 bit param,little endian */ - lower_16 = (unsigned short)(param & 0xffff); - upper_16 = (unsigned short)((param >> 16) & 0xffff); - } - ret = usb_control_msg(pd->udev, - usb_rcvctrlpipe(pd->udev, 0), - REQ_SET_CMD | cmdid, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - lower_16, - upper_16, - &data, - sizeof(*cmd_status), - USB_CTRL_GET_TIMEOUT); - - if (!ret) { - return -ENXIO; - } else { - /* 1st 4 bytes into cmd_status */ - memcpy((char *)cmd_status, &(data[0]), sizeof(*cmd_status)); - } - return 0; -} - -/* - * send get request to Poseidon firmware. - */ -s32 send_get_req(struct poseidon *pd, u8 cmdid, s32 param, - void *buf, s32 *cmd_status, s32 datalen) -{ - s32 ret; - s8 data[128] = {}; - u16 lower_16, upper_16; - - if (pd->state & POSEIDON_STATE_DISCONNECT) - return -ENODEV; - - mdelay(30); - if (param == 0) { - upper_16 = lower_16 = 0; - } else { - /*send 32 bit param as two 16 bit param, little endian */ - lower_16 = (unsigned short)(param & 0xffff); - upper_16 = (unsigned short)((param >> 16) & 0xffff); - } - ret = usb_control_msg(pd->udev, - usb_rcvctrlpipe(pd->udev, 0), - REQ_GET_CMD | cmdid, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - lower_16, - upper_16, - &data, - (datalen + sizeof(*cmd_status)), - USB_CTRL_GET_TIMEOUT); - - if (ret < 0) { - return -ENXIO; - } else { - /* 1st 4 bytes into cmd_status, remaining data into cmd_data */ - memcpy((char *)cmd_status, &data[0], sizeof(*cmd_status)); - memcpy((char *)buf, &data[sizeof(*cmd_status)], datalen); - } - return 0; -} - -static int pm_notifier_block(struct notifier_block *nb, - unsigned long event, void *dummy) -{ - struct poseidon *pd = NULL; - struct list_head *node, *next; - - switch (event) { - case PM_POST_HIBERNATION: - list_for_each_safe(node, next, &pd_device_list) { - struct usb_device *udev; - struct usb_interface *iface; - int rc = 0; - - pd = container_of(node, struct poseidon, device_list); - udev = pd->udev; - iface = pd->interface; - - /* It will cause the system to reload the firmware */ - rc = usb_lock_device_for_reset(udev, iface); - if (rc >= 0) { - usb_reset_device(udev); - usb_unlock_device(udev); - } - } - break; - default: - break; - } - log("event :%ld\n", event); - return 0; -} - -static struct notifier_block pm_notifer = { - .notifier_call = pm_notifier_block, -}; - -int set_tuner_mode(struct poseidon *pd, unsigned char mode) -{ - s32 ret, cmd_status; - - if (pd->state & POSEIDON_STATE_DISCONNECT) - return -ENODEV; - - ret = send_set_req(pd, TUNE_MODE_SELECT, mode, &cmd_status); - if (ret || cmd_status) - return -ENXIO; - return 0; -} - -void poseidon_delete(struct kref *kref) -{ - struct poseidon *pd = container_of(kref, struct poseidon, kref); - - if (!pd) - return; - list_del_init(&pd->device_list); - - pd_dvb_usb_device_cleanup(pd); - /* clean_audio_data(&pd->audio_data);*/ - - if (pd->udev) { - usb_put_dev(pd->udev); - pd->udev = NULL; - } - if (pd->interface) { - usb_put_intf(pd->interface); - pd->interface = NULL; - } - kfree(pd); - log(); -} - -static int firmware_download(struct usb_device *udev) -{ - int ret = 0, actual_length; - const struct firmware *fw = NULL; - void *fwbuf = NULL; - size_t fwlength = 0, offset; - size_t max_packet_size; - - ret = request_firmware(&fw, firmware_name, &udev->dev); - if (ret) { - log("download err : %d", ret); - return ret; - } - - fwlength = fw->size; - - fwbuf = kmemdup(fw->data, fwlength, GFP_KERNEL); - if (!fwbuf) { - ret = -ENOMEM; - goto out; - } - - max_packet_size = udev->ep_out[0x1]->desc.wMaxPacketSize; - log("\t\t download size : %d", (int)max_packet_size); - - for (offset = 0; offset < fwlength; offset += max_packet_size) { - actual_length = 0; - ret = usb_bulk_msg(udev, - usb_sndbulkpipe(udev, 0x01), /* ep 1 */ - fwbuf + offset, - min(max_packet_size, fwlength - offset), - &actual_length, - HZ * 10); - if (ret) - break; - } - kfree(fwbuf); -out: - release_firmware(fw); - return ret; -} - -static inline struct poseidon *get_pd(struct usb_interface *intf) -{ - return usb_get_intfdata(intf); -} - -#ifdef CONFIG_PM -/* one-to-one map : poseidon{} <----> usb_device{}'s port */ -static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev) -{ - pd->portnum = udev->portnum; -} - -static inline int get_autopm_ref(struct poseidon *pd) -{ - return pd->video_data.users + pd->vbi_data.users + pd->audio.users - + atomic_read(&pd->dvb_data.users) + pd->radio_data.users; -} - -/* fixup something for poseidon */ -static inline struct poseidon *fixup(struct poseidon *pd) -{ - int count; - - /* old udev and interface have gone, so put back reference . */ - count = get_autopm_ref(pd); - log("count : %d, ref count : %d", count, get_pm_count(pd)); - while (count--) - usb_autopm_put_interface(pd->interface); - /*usb_autopm_set_interface(pd->interface); */ - - usb_put_dev(pd->udev); - usb_put_intf(pd->interface); - log("event : %d\n", pd->msg.event); - return pd; -} - -static struct poseidon *find_old_poseidon(struct usb_device *udev) -{ - struct poseidon *pd; - - list_for_each_entry(pd, &pd_device_list, device_list) { - if (pd->portnum == udev->portnum && in_hibernation(pd)) - return fixup(pd); - } - return NULL; -} - -/* Is the card working now ? */ -static inline int is_working(struct poseidon *pd) -{ - return get_pm_count(pd) > 0; -} - -static int poseidon_suspend(struct usb_interface *intf, pm_message_t msg) -{ - struct poseidon *pd = get_pd(intf); - - if (!pd) - return 0; - if (!is_working(pd)) { - if (get_pm_count(pd) <= 0 && !in_hibernation(pd)) { - pd->msg.event = PM_EVENT_AUTO_SUSPEND; - pd->pm_resume = NULL; /* a good guard */ - printk(KERN_DEBUG "\n\t+ TLG2300 auto suspend +\n\n"); - } - return 0; - } - pd->msg = msg; /* save it here */ - logpm(pd); - return pd->pm_suspend ? pd->pm_suspend(pd) : 0; -} - -static int poseidon_resume(struct usb_interface *intf) -{ - struct poseidon *pd = get_pd(intf); - - if (!pd) - return 0; - printk(KERN_DEBUG "\n\t ++ TLG2300 resume ++\n\n"); - - if (!is_working(pd)) { - if (PM_EVENT_AUTO_SUSPEND == pd->msg.event) - pd->msg = PMSG_ON; - return 0; - } - if (in_hibernation(pd)) { - logpm(pd); - return 0; - } - logpm(pd); - return pd->pm_resume ? pd->pm_resume(pd) : 0; -} - -static void hibernation_resume(struct work_struct *w) -{ - struct poseidon *pd = container_of(w, struct poseidon, pm_work); - int count; - - pd->msg.event = 0; /* clear it here */ - pd->state &= ~POSEIDON_STATE_DISCONNECT; - - /* set the new interface's reference */ - count = get_autopm_ref(pd); - while (count--) - usb_autopm_get_interface(pd->interface); - - /* resume the context */ - logpm(pd); - if (pd->pm_resume) - pd->pm_resume(pd); -} -#else /* CONFIG_PM is not enabled: */ -static inline struct poseidon *find_old_poseidon(struct usb_device *udev) -{ - return NULL; -} - -static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev) -{ -} -#endif - -static int check_firmware(struct usb_device *udev, int *down_firmware) -{ - void *buf; - int ret; - struct cmd_firmware_vers_s *cmd_firm; - - buf = kzalloc(sizeof(*cmd_firm) + sizeof(u32), GFP_KERNEL); - if (!buf) - return -ENOMEM; - ret = usb_control_msg(udev, - usb_rcvctrlpipe(udev, 0), - REQ_GET_CMD | GET_FW_ID, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, - 0, - buf, - sizeof(*cmd_firm) + sizeof(u32), - USB_CTRL_GET_TIMEOUT); - kfree(buf); - - if (ret < 0) { - *down_firmware = 1; - return firmware_download(udev); - } - return 0; -} - -static int poseidon_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct poseidon *pd = NULL; - int ret = 0; - int new_one = 0; - - /* download firmware */ - check_firmware(udev, &ret); - if (ret) - return 0; - - /* Do I recovery from the hibernate ? */ - pd = find_old_poseidon(udev); - if (!pd) { - pd = kzalloc(sizeof(*pd), GFP_KERNEL); - if (!pd) - return -ENOMEM; - kref_init(&pd->kref); - set_map_flags(pd, udev); - new_one = 1; - } - - pd->udev = usb_get_dev(udev); - pd->interface = usb_get_intf(interface); - usb_set_intfdata(interface, pd); - - if (new_one) { - struct device *dev = &interface->dev; - - logpm(pd); - mutex_init(&pd->lock); - - /* register v4l2 device */ - snprintf(pd->v4l2_dev.name, sizeof(pd->v4l2_dev.name), "%s %s", - dev->driver->name, dev_name(dev)); - ret = v4l2_device_register(NULL, &pd->v4l2_dev); - - /* register devices in directory /dev */ - ret = pd_video_init(pd); - poseidon_audio_init(pd); - poseidon_fm_init(pd); - pd_dvb_usb_device_init(pd); - - INIT_LIST_HEAD(&pd->device_list); - list_add_tail(&pd->device_list, &pd_device_list); - } - - device_init_wakeup(&udev->dev, 1); -#ifdef CONFIG_PM - pm_runtime_set_autosuspend_delay(&pd->udev->dev, - 1000 * PM_SUSPEND_DELAY); - usb_enable_autosuspend(pd->udev); - - if (in_hibernation(pd)) { - INIT_WORK(&pd->pm_work, hibernation_resume); - schedule_work(&pd->pm_work); - } -#endif - return 0; -} - -static void poseidon_disconnect(struct usb_interface *interface) -{ - struct poseidon *pd = get_pd(interface); - - if (!pd) - return; - logpm(pd); - if (in_hibernation(pd)) - return; - - mutex_lock(&pd->lock); - pd->state |= POSEIDON_STATE_DISCONNECT; - mutex_unlock(&pd->lock); - - /* stop urb transferring */ - stop_all_video_stream(pd); - dvb_stop_streaming(&pd->dvb_data); - - /*unregister v4l2 device */ - v4l2_device_unregister(&pd->v4l2_dev); - - pd_dvb_usb_device_exit(pd); - poseidon_fm_exit(pd); - - poseidon_audio_free(pd); - pd_video_exit(pd); - - usb_set_intfdata(interface, NULL); - kref_put(&pd->kref, poseidon_delete); -} - -static struct usb_driver poseidon_driver = { - .name = "poseidon", - .probe = poseidon_probe, - .disconnect = poseidon_disconnect, - .id_table = id_table, -#ifdef CONFIG_PM - .suspend = poseidon_suspend, - .resume = poseidon_resume, -#endif - .supports_autosuspend = 1, -}; - -static int __init poseidon_init(void) -{ - int ret; - - ret = usb_register(&poseidon_driver); - if (ret) - return ret; - register_pm_notifier(&pm_notifer); - return ret; -} - -static void __exit poseidon_exit(void) -{ - log(); - unregister_pm_notifier(&pm_notifer); - usb_deregister(&poseidon_driver); -} - -module_init(poseidon_init); -module_exit(poseidon_exit); - -MODULE_AUTHOR("Telegent Systems"); -MODULE_DESCRIPTION("For tlg2300-based USB device "); -MODULE_LICENSE("GPL"); -MODULE_VERSION("0.0.2"); -MODULE_FIRMWARE(TLG2300_FIRMWARE); diff --git a/drivers/media/video/tlg2300/pd-radio.c b/drivers/media/video/tlg2300/pd-radio.c deleted file mode 100644 index 4fad1dfb92cf..000000000000 --- a/drivers/media/video/tlg2300/pd-radio.c +++ /dev/null @@ -1,421 +0,0 @@ -#include <linux/init.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/bitmap.h> -#include <linux/usb.h> -#include <linux/i2c.h> -#include <media/v4l2-dev.h> -#include <linux/mm.h> -#include <linux/mutex.h> -#include <media/v4l2-ioctl.h> -#include <linux/sched.h> - -#include "pd-common.h" -#include "vendorcmds.h" - -static int set_frequency(struct poseidon *p, __u32 frequency); -static int poseidon_fm_close(struct file *filp); -static int poseidon_fm_open(struct file *filp); - -#define TUNER_FREQ_MIN_FM 76000000 -#define TUNER_FREQ_MAX_FM 108000000 - -#define MAX_PREEMPHASIS (V4L2_PREEMPHASIS_75_uS + 1) -static int preemphasis[MAX_PREEMPHASIS] = { - TLG_TUNE_ASTD_NONE, /* V4L2_PREEMPHASIS_DISABLED */ - TLG_TUNE_ASTD_FM_EUR, /* V4L2_PREEMPHASIS_50_uS */ - TLG_TUNE_ASTD_FM_US, /* V4L2_PREEMPHASIS_75_uS */ -}; - -static int poseidon_check_mode_radio(struct poseidon *p) -{ - int ret; - u32 status; - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/2); - ret = usb_set_interface(p->udev, 0, BULK_ALTERNATE_IFACE); - if (ret < 0) - goto out; - - ret = set_tuner_mode(p, TLG_MODE_FM_RADIO); - if (ret != 0) - goto out; - - ret = send_set_req(p, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &status); - ret = send_set_req(p, TUNER_AUD_ANA_STD, - p->radio_data.pre_emphasis, &status); - ret |= send_set_req(p, TUNER_AUD_MODE, - TLG_TUNE_TVAUDIO_MODE_STEREO, &status); - ret |= send_set_req(p, AUDIO_SAMPLE_RATE_SEL, - ATV_AUDIO_RATE_48K, &status); - ret |= send_set_req(p, TUNE_FREQ_SELECT, TUNER_FREQ_MIN_FM, &status); -out: - return ret; -} - -#ifdef CONFIG_PM -static int pm_fm_suspend(struct poseidon *p) -{ - logpm(p); - pm_alsa_suspend(p); - usb_set_interface(p->udev, 0, 0); - msleep(300); - return 0; -} - -static int pm_fm_resume(struct poseidon *p) -{ - logpm(p); - poseidon_check_mode_radio(p); - set_frequency(p, p->radio_data.fm_freq); - pm_alsa_resume(p); - return 0; -} -#endif - -static int poseidon_fm_open(struct file *filp) -{ - struct video_device *vfd = video_devdata(filp); - struct poseidon *p = video_get_drvdata(vfd); - int ret = 0; - - if (!p) - return -1; - - mutex_lock(&p->lock); - if (p->state & POSEIDON_STATE_DISCONNECT) { - ret = -ENODEV; - goto out; - } - - if (p->state && !(p->state & POSEIDON_STATE_FM)) { - ret = -EBUSY; - goto out; - } - - usb_autopm_get_interface(p->interface); - if (0 == p->state) { - /* default pre-emphasis */ - if (p->radio_data.pre_emphasis == 0) - p->radio_data.pre_emphasis = TLG_TUNE_ASTD_FM_EUR; - set_debug_mode(vfd, debug_mode); - - ret = poseidon_check_mode_radio(p); - if (ret < 0) { - usb_autopm_put_interface(p->interface); - goto out; - } - p->state |= POSEIDON_STATE_FM; - } - p->radio_data.users++; - kref_get(&p->kref); - filp->private_data = p; -out: - mutex_unlock(&p->lock); - return ret; -} - -static int poseidon_fm_close(struct file *filp) -{ - struct poseidon *p = filp->private_data; - struct radio_data *fm = &p->radio_data; - uint32_t status; - - mutex_lock(&p->lock); - fm->users--; - if (0 == fm->users) - p->state &= ~POSEIDON_STATE_FM; - - if (fm->is_radio_streaming && filp == p->file_for_stream) { - fm->is_radio_streaming = 0; - send_set_req(p, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, &status); - } - usb_autopm_put_interface(p->interface); - mutex_unlock(&p->lock); - - kref_put(&p->kref, poseidon_delete); - filp->private_data = NULL; - return 0; -} - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *v) -{ - struct poseidon *p = file->private_data; - - strlcpy(v->driver, "tele-radio", sizeof(v->driver)); - strlcpy(v->card, "Telegent Poseidon", sizeof(v->card)); - usb_make_path(p->udev, v->bus_info, sizeof(v->bus_info)); - v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; - return 0; -} - -static const struct v4l2_file_operations poseidon_fm_fops = { - .owner = THIS_MODULE, - .open = poseidon_fm_open, - .release = poseidon_fm_close, - .ioctl = video_ioctl2, -}; - -static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *vt) -{ - struct tuner_fm_sig_stat_s fm_stat = {}; - int ret, status, count = 5; - struct poseidon *p = file->private_data; - - if (vt->index != 0) - return -EINVAL; - - vt->type = V4L2_TUNER_RADIO; - vt->capability = V4L2_TUNER_CAP_STEREO; - vt->rangelow = TUNER_FREQ_MIN_FM / 62500; - vt->rangehigh = TUNER_FREQ_MAX_FM / 62500; - vt->rxsubchans = V4L2_TUNER_SUB_STEREO; - vt->audmode = V4L2_TUNER_MODE_STEREO; - vt->signal = 0; - vt->afc = 0; - - mutex_lock(&p->lock); - ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO, - &fm_stat, &status, sizeof(fm_stat)); - - while (fm_stat.sig_lock_busy && count-- && !ret) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); - - ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO, - &fm_stat, &status, sizeof(fm_stat)); - } - mutex_unlock(&p->lock); - - if (ret || status) { - vt->signal = 0; - } else if ((fm_stat.sig_present || fm_stat.sig_locked) - && fm_stat.sig_strength == 0) { - vt->signal = 0xffff; - } else - vt->signal = (fm_stat.sig_strength * 255 / 10) << 8; - - return 0; -} - -static int fm_get_freq(struct file *file, void *priv, - struct v4l2_frequency *argp) -{ - struct poseidon *p = file->private_data; - - argp->frequency = p->radio_data.fm_freq; - return 0; -} - -static int set_frequency(struct poseidon *p, __u32 frequency) -{ - __u32 freq ; - int ret, status; - - mutex_lock(&p->lock); - - ret = send_set_req(p, TUNER_AUD_ANA_STD, - p->radio_data.pre_emphasis, &status); - - freq = (frequency * 125) * 500 / 1000;/* kHZ */ - if (freq < TUNER_FREQ_MIN_FM/1000 || freq > TUNER_FREQ_MAX_FM/1000) { - ret = -EINVAL; - goto error; - } - - ret = send_set_req(p, TUNE_FREQ_SELECT, freq, &status); - if (ret < 0) - goto error ; - ret = send_set_req(p, TAKE_REQUEST, 0, &status); - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); - if (!p->radio_data.is_radio_streaming) { - ret = send_set_req(p, TAKE_REQUEST, 0, &status); - ret = send_set_req(p, PLAY_SERVICE, - TLG_TUNE_PLAY_SVC_START, &status); - p->radio_data.is_radio_streaming = 1; - } - p->radio_data.fm_freq = frequency; -error: - mutex_unlock(&p->lock); - return ret; -} - -static int fm_set_freq(struct file *file, void *priv, - struct v4l2_frequency *argp) -{ - struct poseidon *p = file->private_data; - - p->file_for_stream = file; -#ifdef CONFIG_PM - p->pm_suspend = pm_fm_suspend; - p->pm_resume = pm_fm_resume; -#endif - return set_frequency(p, argp->frequency); -} - -static int tlg_fm_vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *arg) -{ - return 0; -} - -static int tlg_fm_vidioc_g_exts_ctrl(struct file *file, void *fh, - struct v4l2_ext_controls *ctrls) -{ - struct poseidon *p = file->private_data; - int i; - - if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) - return -EINVAL; - - for (i = 0; i < ctrls->count; i++) { - struct v4l2_ext_control *ctrl = ctrls->controls + i; - - if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS) - continue; - - if (i < MAX_PREEMPHASIS) - ctrl->value = p->radio_data.pre_emphasis; - } - return 0; -} - -static int tlg_fm_vidioc_s_exts_ctrl(struct file *file, void *fh, - struct v4l2_ext_controls *ctrls) -{ - int i; - - if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) - return -EINVAL; - - for (i = 0; i < ctrls->count; i++) { - struct v4l2_ext_control *ctrl = ctrls->controls + i; - - if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS) - continue; - - if (ctrl->value >= 0 && ctrl->value < MAX_PREEMPHASIS) { - struct poseidon *p = file->private_data; - int pre_emphasis = preemphasis[ctrl->value]; - u32 status; - - send_set_req(p, TUNER_AUD_ANA_STD, - pre_emphasis, &status); - p->radio_data.pre_emphasis = pre_emphasis; - } - } - return 0; -} - -static int tlg_fm_vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - return 0; -} - -static int tlg_fm_vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *ctrl) -{ - if (!(ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL)) - return -EINVAL; - - ctrl->id &= ~V4L2_CTRL_FLAG_NEXT_CTRL; - if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS) { - /* return the next supported control */ - ctrl->id = V4L2_CID_TUNE_PREEMPHASIS; - v4l2_ctrl_query_fill(ctrl, V4L2_PREEMPHASIS_DISABLED, - V4L2_PREEMPHASIS_75_uS, 1, - V4L2_PREEMPHASIS_50_uS); - ctrl->flags = V4L2_CTRL_FLAG_UPDATE; - return 0; - } - return -EINVAL; -} - -static int tlg_fm_vidioc_querymenu(struct file *file, void *fh, - struct v4l2_querymenu *qmenu) -{ - return v4l2_ctrl_query_menu(qmenu, NULL, NULL); -} - -static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) -{ - return vt->index > 0 ? -EINVAL : 0; -} -static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *va) -{ - return (va->index != 0) ? -EINVAL : 0; -} - -static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - a->index = 0; - a->mode = 0; - a->capability = V4L2_AUDCAP_STEREO; - strcpy(a->name, "Radio"); - return 0; -} - -static int vidioc_s_input(struct file *filp, void *priv, u32 i) -{ - return (i != 0) ? -EINVAL : 0; -} - -static int vidioc_g_input(struct file *filp, void *priv, u32 *i) -{ - return (*i != 0) ? -EINVAL : 0; -} - -static const struct v4l2_ioctl_ops poseidon_fm_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_queryctrl = tlg_fm_vidioc_queryctrl, - .vidioc_querymenu = tlg_fm_vidioc_querymenu, - .vidioc_g_ctrl = tlg_fm_vidioc_g_ctrl, - .vidioc_s_ctrl = tlg_fm_vidioc_s_ctrl, - .vidioc_s_ext_ctrls = tlg_fm_vidioc_s_exts_ctrl, - .vidioc_g_ext_ctrls = tlg_fm_vidioc_g_exts_ctrl, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_tuner = tlg_fm_vidioc_g_tuner, - .vidioc_g_frequency = fm_get_freq, - .vidioc_s_frequency = fm_set_freq, -}; - -static struct video_device poseidon_fm_template = { - .name = "Telegent-Radio", - .fops = &poseidon_fm_fops, - .minor = -1, - .release = video_device_release, - .ioctl_ops = &poseidon_fm_ioctl_ops, -}; - -int poseidon_fm_init(struct poseidon *p) -{ - struct video_device *fm_dev; - - fm_dev = vdev_init(p, &poseidon_fm_template); - if (fm_dev == NULL) - return -1; - - if (video_register_device(fm_dev, VFL_TYPE_RADIO, -1) < 0) { - video_device_release(fm_dev); - return -1; - } - p->radio_data.fm_dev = fm_dev; - return 0; -} - -int poseidon_fm_exit(struct poseidon *p) -{ - destroy_video_device(&p->radio_data.fm_dev); - return 0; -} diff --git a/drivers/media/video/tlg2300/pd-video.c b/drivers/media/video/tlg2300/pd-video.c deleted file mode 100644 index bfbf9e56b0a4..000000000000 --- a/drivers/media/video/tlg2300/pd-video.c +++ /dev/null @@ -1,1668 +0,0 @@ -#include <linux/fs.h> -#include <linux/vmalloc.h> -#include <linux/videodev2.h> -#include <linux/usb.h> -#include <linux/mm.h> -#include <linux/sched.h> -#include <linux/slab.h> - -#include <media/v4l2-ioctl.h> -#include <media/v4l2-dev.h> - -#include "pd-common.h" -#include "vendorcmds.h" - -#ifdef CONFIG_PM -static int pm_video_suspend(struct poseidon *pd); -static int pm_video_resume(struct poseidon *pd); -#endif -static void iso_bubble_handler(struct work_struct *w); - -static int usb_transfer_mode; -module_param(usb_transfer_mode, int, 0644); -MODULE_PARM_DESC(usb_transfer_mode, "0 = Bulk, 1 = Isochronous"); - -static const struct poseidon_format poseidon_formats[] = { - { "YUV 422", V4L2_PIX_FMT_YUYV, 16, 0}, - { "RGB565", V4L2_PIX_FMT_RGB565, 16, 0}, -}; - -static const struct poseidon_tvnorm poseidon_tvnorms[] = { - { V4L2_STD_PAL_D, "PAL-D", TLG_TUNE_VSTD_PAL_D }, - { V4L2_STD_PAL_B, "PAL-B", TLG_TUNE_VSTD_PAL_B }, - { V4L2_STD_PAL_G, "PAL-G", TLG_TUNE_VSTD_PAL_G }, - { V4L2_STD_PAL_H, "PAL-H", TLG_TUNE_VSTD_PAL_H }, - { V4L2_STD_PAL_I, "PAL-I", TLG_TUNE_VSTD_PAL_I }, - { V4L2_STD_PAL_M, "PAL-M", TLG_TUNE_VSTD_PAL_M }, - { V4L2_STD_PAL_N, "PAL-N", TLG_TUNE_VSTD_PAL_N_COMBO }, - { V4L2_STD_PAL_Nc, "PAL-Nc", TLG_TUNE_VSTD_PAL_N_COMBO }, - { V4L2_STD_NTSC_M, "NTSC-M", TLG_TUNE_VSTD_NTSC_M }, - { V4L2_STD_NTSC_M_JP, "NTSC-JP", TLG_TUNE_VSTD_NTSC_M_J }, - { V4L2_STD_SECAM_B, "SECAM-B", TLG_TUNE_VSTD_SECAM_B }, - { V4L2_STD_SECAM_D, "SECAM-D", TLG_TUNE_VSTD_SECAM_D }, - { V4L2_STD_SECAM_G, "SECAM-G", TLG_TUNE_VSTD_SECAM_G }, - { V4L2_STD_SECAM_H, "SECAM-H", TLG_TUNE_VSTD_SECAM_H }, - { V4L2_STD_SECAM_K, "SECAM-K", TLG_TUNE_VSTD_SECAM_K }, - { V4L2_STD_SECAM_K1, "SECAM-K1", TLG_TUNE_VSTD_SECAM_K1 }, - { V4L2_STD_SECAM_L, "SECAM-L", TLG_TUNE_VSTD_SECAM_L }, - { V4L2_STD_SECAM_LC, "SECAM-LC", TLG_TUNE_VSTD_SECAM_L1 }, -}; -static const unsigned int POSEIDON_TVNORMS = ARRAY_SIZE(poseidon_tvnorms); - -struct pd_audio_mode { - u32 tlg_audio_mode; - u32 v4l2_audio_sub; - u32 v4l2_audio_mode; -}; - -static const struct pd_audio_mode pd_audio_modes[] = { - { TLG_TUNE_TVAUDIO_MODE_MONO, V4L2_TUNER_SUB_MONO, - V4L2_TUNER_MODE_MONO }, - { TLG_TUNE_TVAUDIO_MODE_STEREO, V4L2_TUNER_SUB_STEREO, - V4L2_TUNER_MODE_STEREO }, - { TLG_TUNE_TVAUDIO_MODE_LANG_A, V4L2_TUNER_SUB_LANG1, - V4L2_TUNER_MODE_LANG1 }, - { TLG_TUNE_TVAUDIO_MODE_LANG_B, V4L2_TUNER_SUB_LANG2, - V4L2_TUNER_MODE_LANG2 }, - { TLG_TUNE_TVAUDIO_MODE_LANG_C, V4L2_TUNER_SUB_LANG1, - V4L2_TUNER_MODE_LANG1_LANG2 } -}; -static const unsigned int POSEIDON_AUDIOMODS = ARRAY_SIZE(pd_audio_modes); - -struct pd_input { - char *name; - uint32_t tlg_src; -}; - -static const struct pd_input pd_inputs[] = { - { "TV Antenna", TLG_SIG_SRC_ANTENNA }, - { "TV Cable", TLG_SIG_SRC_CABLE }, - { "TV SVideo", TLG_SIG_SRC_SVIDEO }, - { "TV Composite", TLG_SIG_SRC_COMPOSITE } -}; -static const unsigned int POSEIDON_INPUTS = ARRAY_SIZE(pd_inputs); - -struct poseidon_control { - struct v4l2_queryctrl v4l2_ctrl; - enum cmd_custom_param_id vc_id; -}; - -static struct poseidon_control controls[] = { - { - { V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER, - "brightness", 0, 10000, 1, 100, 0, }, - CUST_PARM_ID_BRIGHTNESS_CTRL - }, { - { V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER, - "contrast", 0, 10000, 1, 100, 0, }, - CUST_PARM_ID_CONTRAST_CTRL, - }, { - { V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER, - "hue", 0, 10000, 1, 100, 0, }, - CUST_PARM_ID_HUE_CTRL, - }, { - { V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER, - "saturation", 0, 10000, 1, 100, 0, }, - CUST_PARM_ID_SATURATION_CTRL, - }, -}; - -struct video_std_to_audio_std { - v4l2_std_id video_std; - int audio_std; -}; - -static const struct video_std_to_audio_std video_to_audio_map[] = { - /* country : { 27, 32, 33, 34, 36, 44, 45, 46, 47, 48, 64, - 65, 86, 351, 352, 353, 354, 358, 372, 852, 972 } */ - { (V4L2_STD_PAL_I | V4L2_STD_PAL_B | V4L2_STD_PAL_D | - V4L2_STD_SECAM_L | V4L2_STD_SECAM_D), TLG_TUNE_ASTD_NICAM }, - - /* country : { 1, 52, 54, 55, 886 } */ - {V4L2_STD_NTSC_M | V4L2_STD_PAL_N | V4L2_STD_PAL_M, TLG_TUNE_ASTD_BTSC}, - - /* country : { 81 } */ - { V4L2_STD_NTSC_M_JP, TLG_TUNE_ASTD_EIAJ }, - - /* other country : TLG_TUNE_ASTD_A2 */ -}; -static const unsigned int map_size = ARRAY_SIZE(video_to_audio_map); - -static int get_audio_std(v4l2_std_id v4l2_std) -{ - int i = 0; - - for (; i < map_size; i++) { - if (v4l2_std & video_to_audio_map[i].video_std) - return video_to_audio_map[i].audio_std; - } - return TLG_TUNE_ASTD_A2; -} - -static int vidioc_querycap(struct file *file, void *fh, - struct v4l2_capability *cap) -{ - struct front_face *front = fh; - struct poseidon *p = front->pd; - - logs(front); - - strcpy(cap->driver, "tele-video"); - strcpy(cap->card, "Telegent Poseidon"); - usb_make_path(p->udev, cap->bus_info, sizeof(cap->bus_info)); - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | - V4L2_CAP_AUDIO | V4L2_CAP_STREAMING | - V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE; - return 0; -} - -/*====================================================================*/ -static void init_copy(struct video_data *video, bool index) -{ - struct front_face *front = video->front; - - video->field_count = index; - video->lines_copied = 0; - video->prev_left = 0 ; - video->dst = (char *)videobuf_to_vmalloc(front->curr_frame) - + index * video->lines_size; - video->vbi->copied = 0; /* set it here */ -} - -static bool get_frame(struct front_face *front, int *need_init) -{ - struct videobuf_buffer *vb = front->curr_frame; - - if (vb) - return true; - - spin_lock(&front->queue_lock); - if (!list_empty(&front->active)) { - vb = list_entry(front->active.next, - struct videobuf_buffer, queue); - if (need_init) - *need_init = 1; - front->curr_frame = vb; - list_del_init(&vb->queue); - } - spin_unlock(&front->queue_lock); - - return !!vb; -} - -/* check if the video's buffer is ready */ -static bool get_video_frame(struct front_face *front, struct video_data *video) -{ - int need_init = 0; - bool ret = true; - - ret = get_frame(front, &need_init); - if (ret && need_init) - init_copy(video, 0); - return ret; -} - -static void submit_frame(struct front_face *front) -{ - struct videobuf_buffer *vb = front->curr_frame; - - if (vb == NULL) - return; - - front->curr_frame = NULL; - vb->state = VIDEOBUF_DONE; - vb->field_count++; - do_gettimeofday(&vb->ts); - - wake_up(&vb->done); -} - -/* - * A frame is composed of two fields. If we receive all the two fields, - * call the submit_frame() to submit the whole frame to applications. - */ -static void end_field(struct video_data *video) -{ - /* logs(video->front); */ - if (1 == video->field_count) - submit_frame(video->front); - else - init_copy(video, 1); -} - -static void copy_video_data(struct video_data *video, char *src, - unsigned int count) -{ -#define copy_data(len) \ - do { \ - if (++video->lines_copied > video->lines_per_field) \ - goto overflow; \ - memcpy(video->dst, src, len);\ - video->dst += len + video->lines_size; \ - src += len; \ - count -= len; \ - } while (0) - - while (count && count >= video->lines_size) { - if (video->prev_left) { - copy_data(video->prev_left); - video->prev_left = 0; - continue; - } - copy_data(video->lines_size); - } - if (count && count < video->lines_size) { - memcpy(video->dst, src, count); - - video->prev_left = video->lines_size - count; - video->dst += count; - } - return; - -overflow: - end_field(video); -} - -static void check_trailer(struct video_data *video, char *src, int count) -{ - struct vbi_data *vbi = video->vbi; - int offset; /* trailer's offset */ - char *buf; - - offset = (video->context.pix.sizeimage / 2 + vbi->vbi_size / 2) - - (vbi->copied + video->lines_size * video->lines_copied); - if (video->prev_left) - offset -= (video->lines_size - video->prev_left); - - if (offset > count || offset <= 0) - goto short_package; - - buf = src + offset; - - /* trailer : (VFHS) + U32 + U32 + field_num */ - if (!strncmp(buf, "VFHS", 4)) { - int field_num = *((u32 *)(buf + 12)); - - if ((field_num & 1) ^ video->field_count) { - init_copy(video, video->field_count); - return; - } - copy_video_data(video, src, offset); - } -short_package: - end_field(video); -} - -/* ========== Check this more carefully! =========== */ -static inline void copy_vbi_data(struct vbi_data *vbi, - char *src, unsigned int count) -{ - struct front_face *front = vbi->front; - - if (front && get_frame(front, NULL)) { - char *buf = videobuf_to_vmalloc(front->curr_frame); - - if (vbi->video->field_count) - buf += (vbi->vbi_size / 2); - memcpy(buf + vbi->copied, src, count); - } - vbi->copied += count; -} - -/* - * Copy the normal data (VBI or VIDEO) without the trailer. - * VBI is not interlaced, while VIDEO is interlaced. - */ -static inline void copy_vbi_video_data(struct video_data *video, - char *src, unsigned int count) -{ - struct vbi_data *vbi = video->vbi; - unsigned int vbi_delta = (vbi->vbi_size / 2) - vbi->copied; - - if (vbi_delta >= count) { - copy_vbi_data(vbi, src, count); - } else { - if (vbi_delta) { - copy_vbi_data(vbi, src, vbi_delta); - - /* we receive the two fields of the VBI*/ - if (vbi->front && video->field_count) - submit_frame(vbi->front); - } - copy_video_data(video, src + vbi_delta, count - vbi_delta); - } -} - -static void urb_complete_bulk(struct urb *urb) -{ - struct front_face *front = urb->context; - struct video_data *video = &front->pd->video_data; - char *src = (char *)urb->transfer_buffer; - int count = urb->actual_length; - int ret = 0; - - if (!video->is_streaming || urb->status) { - if (urb->status == -EPROTO) - goto resend_it; - return; - } - if (!get_video_frame(front, video)) - goto resend_it; - - if (count == urb->transfer_buffer_length) - copy_vbi_video_data(video, src, count); - else - check_trailer(video, src, count); - -resend_it: - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) - log(" submit failed: error %d", ret); -} - -/************************* for ISO *********************/ -#define GET_SUCCESS (0) -#define GET_TRAILER (1) -#define GET_TOO_MUCH_BUBBLE (2) -#define GET_NONE (3) -static int get_chunk(int start, struct urb *urb, - int *head, int *tail, int *bubble_err) -{ - struct usb_iso_packet_descriptor *pkt = NULL; - int ret = GET_SUCCESS; - - for (*head = *tail = -1; start < urb->number_of_packets; start++) { - pkt = &urb->iso_frame_desc[start]; - - /* handle the bubble of the Hub */ - if (-EOVERFLOW == pkt->status) { - if (++*bubble_err > urb->number_of_packets / 3) - return GET_TOO_MUCH_BUBBLE; - continue; - } - - /* This is the gap */ - if (pkt->status || pkt->actual_length <= 0 - || pkt->actual_length > ISO_PKT_SIZE) { - if (*head != -1) - break; - continue; - } - - /* a good isochronous packet */ - if (pkt->actual_length == ISO_PKT_SIZE) { - if (*head == -1) - *head = start; - *tail = start; - continue; - } - - /* trailer is here */ - if (pkt->actual_length < ISO_PKT_SIZE) { - if (*head == -1) { - *head = start; - *tail = start; - return GET_TRAILER; - } - break; - } - } - - if (*head == -1 && *tail == -1) - ret = GET_NONE; - return ret; -} - -/* - * |__|------|___|-----|_______| - * ^ ^ - * | | - * gap gap - */ -static void urb_complete_iso(struct urb *urb) -{ - struct front_face *front = urb->context; - struct video_data *video = &front->pd->video_data; - int bubble_err = 0, head = 0, tail = 0; - char *src = (char *)urb->transfer_buffer; - int ret = 0; - - if (!video->is_streaming) - return; - - do { - if (!get_video_frame(front, video)) - goto out; - - switch (get_chunk(head, urb, &head, &tail, &bubble_err)) { - case GET_SUCCESS: - copy_vbi_video_data(video, src + (head * ISO_PKT_SIZE), - (tail - head + 1) * ISO_PKT_SIZE); - break; - case GET_TRAILER: - check_trailer(video, src + (head * ISO_PKT_SIZE), - ISO_PKT_SIZE); - break; - case GET_NONE: - goto out; - case GET_TOO_MUCH_BUBBLE: - log("\t We got too much bubble"); - schedule_work(&video->bubble_work); - return; - } - } while (head = tail + 1, head < urb->number_of_packets); - -out: - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) - log("usb_submit_urb err : %d", ret); -} -/*============================= [ end ] =====================*/ - -static int prepare_iso_urb(struct video_data *video) -{ - struct usb_device *udev = video->pd->udev; - int i; - - if (video->urb_array[0]) - return 0; - - for (i = 0; i < SBUF_NUM; i++) { - struct urb *urb; - void *mem; - int j; - - urb = usb_alloc_urb(PK_PER_URB, GFP_KERNEL); - if (urb == NULL) - goto out; - - video->urb_array[i] = urb; - mem = usb_alloc_coherent(udev, - ISO_PKT_SIZE * PK_PER_URB, - GFP_KERNEL, - &urb->transfer_dma); - - urb->complete = urb_complete_iso; /* handler */ - urb->dev = udev; - urb->context = video->front; - urb->pipe = usb_rcvisocpipe(udev, - video->endpoint_addr); - urb->interval = 1; - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - urb->number_of_packets = PK_PER_URB; - urb->transfer_buffer = mem; - urb->transfer_buffer_length = PK_PER_URB * ISO_PKT_SIZE; - - for (j = 0; j < PK_PER_URB; j++) { - urb->iso_frame_desc[j].offset = ISO_PKT_SIZE * j; - urb->iso_frame_desc[j].length = ISO_PKT_SIZE; - } - } - return 0; -out: - for (; i > 0; i--) - ; - return -ENOMEM; -} - -/* return the succeeded number of the allocation */ -int alloc_bulk_urbs_generic(struct urb **urb_array, int num, - struct usb_device *udev, u8 ep_addr, - int buf_size, gfp_t gfp_flags, - usb_complete_t complete_fn, void *context) -{ - int i = 0; - - for (; i < num; i++) { - void *mem; - struct urb *urb = usb_alloc_urb(0, gfp_flags); - if (urb == NULL) - return i; - - mem = usb_alloc_coherent(udev, buf_size, gfp_flags, - &urb->transfer_dma); - if (mem == NULL) { - usb_free_urb(urb); - return i; - } - - usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, ep_addr), - mem, buf_size, complete_fn, context); - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - urb_array[i] = urb; - } - return i; -} - -void free_all_urb_generic(struct urb **urb_array, int num) -{ - int i; - struct urb *urb; - - for (i = 0; i < num; i++) { - urb = urb_array[i]; - if (urb) { - usb_free_coherent(urb->dev, - urb->transfer_buffer_length, - urb->transfer_buffer, - urb->transfer_dma); - usb_free_urb(urb); - urb_array[i] = NULL; - } - } -} - -static int prepare_bulk_urb(struct video_data *video) -{ - if (video->urb_array[0]) - return 0; - - alloc_bulk_urbs_generic(video->urb_array, SBUF_NUM, - video->pd->udev, video->endpoint_addr, - 0x2000, GFP_KERNEL, - urb_complete_bulk, video->front); - return 0; -} - -/* free the URBs */ -static void free_all_urb(struct video_data *video) -{ - free_all_urb_generic(video->urb_array, SBUF_NUM); -} - -static void pd_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - videobuf_vmalloc_free(vb); - vb->state = VIDEOBUF_NEEDS_INIT; -} - -static void pd_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct front_face *front = q->priv_data; - vb->state = VIDEOBUF_QUEUED; - list_add_tail(&vb->queue, &front->active); -} - -static int pd_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct front_face *front = q->priv_data; - int rc; - - switch (front->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (VIDEOBUF_NEEDS_INIT == vb->state) { - struct v4l2_pix_format *pix; - - pix = &front->pd->video_data.context.pix; - vb->size = pix->sizeimage; /* real frame size */ - vb->width = pix->width; - vb->height = pix->height; - rc = videobuf_iolock(q, vb, NULL); - if (rc < 0) - return rc; - } - break; - case V4L2_BUF_TYPE_VBI_CAPTURE: - if (VIDEOBUF_NEEDS_INIT == vb->state) { - vb->size = front->pd->vbi_data.vbi_size; - rc = videobuf_iolock(q, vb, NULL); - if (rc < 0) - return rc; - } - break; - default: - return -EINVAL; - } - vb->field = field; - vb->state = VIDEOBUF_PREPARED; - return 0; -} - -static int fire_all_urb(struct video_data *video) -{ - int i, ret; - - video->is_streaming = 1; - - for (i = 0; i < SBUF_NUM; i++) { - ret = usb_submit_urb(video->urb_array[i], GFP_KERNEL); - if (ret) - log("(%d) failed: error %d", i, ret); - } - return ret; -} - -static int start_video_stream(struct poseidon *pd) -{ - struct video_data *video = &pd->video_data; - s32 cmd_status; - - send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); - send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_START, &cmd_status); - - if (pd->cur_transfer_mode) { - prepare_iso_urb(video); - INIT_WORK(&video->bubble_work, iso_bubble_handler); - } else { - /* The bulk mode does not need a bubble handler */ - prepare_bulk_urb(video); - } - fire_all_urb(video); - return 0; -} - -static int pd_buf_setup(struct videobuf_queue *q, unsigned int *count, - unsigned int *size) -{ - struct front_face *front = q->priv_data; - struct poseidon *pd = front->pd; - - switch (front->type) { - default: - return -EINVAL; - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - struct video_data *video = &pd->video_data; - struct v4l2_pix_format *pix = &video->context.pix; - - *size = PAGE_ALIGN(pix->sizeimage);/* page aligned frame size */ - if (*count < 4) - *count = 4; - if (1) { - /* same in different altersetting */ - video->endpoint_addr = 0x82; - video->vbi = &pd->vbi_data; - video->vbi->video = video; - video->pd = pd; - video->lines_per_field = pix->height / 2; - video->lines_size = pix->width * 2; - video->front = front; - } - return start_video_stream(pd); - } - - case V4L2_BUF_TYPE_VBI_CAPTURE: { - struct vbi_data *vbi = &pd->vbi_data; - - *size = PAGE_ALIGN(vbi->vbi_size); - log("size : %d", *size); - if (*count == 0) - *count = 4; - } - break; - } - return 0; -} - -static struct videobuf_queue_ops pd_video_qops = { - .buf_setup = pd_buf_setup, - .buf_prepare = pd_buf_prepare, - .buf_queue = pd_buf_queue, - .buf_release = pd_buf_release, -}; - -static int vidioc_enum_fmt(struct file *file, void *fh, - struct v4l2_fmtdesc *f) -{ - if (ARRAY_SIZE(poseidon_formats) <= f->index) - return -EINVAL; - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - f->flags = 0; - f->pixelformat = poseidon_formats[f->index].fourcc; - strcpy(f->description, poseidon_formats[f->index].name); - return 0; -} - -static int vidioc_g_fmt(struct file *file, void *fh, struct v4l2_format *f) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - - logs(front); - f->fmt.pix = pd->video_data.context.pix; - return 0; -} - -static int vidioc_try_fmt(struct file *file, void *fh, - struct v4l2_format *f) -{ - return 0; -} - -/* - * VLC calls VIDIOC_S_STD before VIDIOC_S_FMT, while - * Mplayer calls them in the reverse order. - */ -static int pd_vidioc_s_fmt(struct poseidon *pd, struct v4l2_pix_format *pix) -{ - struct video_data *video = &pd->video_data; - struct running_context *context = &video->context; - struct v4l2_pix_format *pix_def = &context->pix; - s32 ret = 0, cmd_status = 0, vid_resol; - - /* set the pixel format to firmware */ - if (pix->pixelformat == V4L2_PIX_FMT_RGB565) { - vid_resol = TLG_TUNER_VID_FORMAT_RGB_565; - } else { - pix->pixelformat = V4L2_PIX_FMT_YUYV; - vid_resol = TLG_TUNER_VID_FORMAT_YUV; - } - ret = send_set_req(pd, VIDEO_STREAM_FMT_SEL, - vid_resol, &cmd_status); - - /* set the resolution to firmware */ - vid_resol = TLG_TUNE_VID_RES_720; - switch (pix->width) { - case 704: - vid_resol = TLG_TUNE_VID_RES_704; - break; - default: - pix->width = 720; - case 720: - break; - } - ret |= send_set_req(pd, VIDEO_ROSOLU_SEL, - vid_resol, &cmd_status); - if (ret || cmd_status) - return -EBUSY; - - pix_def->pixelformat = pix->pixelformat; /* save it */ - pix->height = (context->tvnormid & V4L2_STD_525_60) ? 480 : 576; - - /* Compare with the default setting */ - if ((pix_def->width != pix->width) - || (pix_def->height != pix->height)) { - pix_def->width = pix->width; - pix_def->height = pix->height; - pix_def->bytesperline = pix->width * 2; - pix_def->sizeimage = pix->width * pix->height * 2; - } - *pix = *pix_def; - - return 0; -} - -static int vidioc_s_fmt(struct file *file, void *fh, struct v4l2_format *f) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - - logs(front); - /* stop VBI here */ - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) - return -EINVAL; - - mutex_lock(&pd->lock); - if (pd->file_for_stream == NULL) - pd->file_for_stream = file; - else if (file != pd->file_for_stream) { - mutex_unlock(&pd->lock); - return -EINVAL; - } - - pd_vidioc_s_fmt(pd, &f->fmt.pix); - mutex_unlock(&pd->lock); - return 0; -} - -static int vidioc_g_fmt_vbi(struct file *file, void *fh, - struct v4l2_format *v4l2_f) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - struct v4l2_vbi_format *vbi_fmt = &v4l2_f->fmt.vbi; - - vbi_fmt->samples_per_line = 720 * 2; - vbi_fmt->sampling_rate = 6750000 * 4; - vbi_fmt->sample_format = V4L2_PIX_FMT_GREY; - vbi_fmt->offset = 64 * 4; /*FIXME: why offset */ - if (pd->video_data.context.tvnormid & V4L2_STD_525_60) { - vbi_fmt->start[0] = 10; - vbi_fmt->start[1] = 264; - vbi_fmt->count[0] = V4L_NTSC_VBI_LINES; - vbi_fmt->count[1] = V4L_NTSC_VBI_LINES; - } else { - vbi_fmt->start[0] = 6; - vbi_fmt->start[1] = 314; - vbi_fmt->count[0] = V4L_PAL_VBI_LINES; - vbi_fmt->count[1] = V4L_PAL_VBI_LINES; - } - vbi_fmt->flags = V4L2_VBI_UNSYNC; - logs(front); - return 0; -} - -static int set_std(struct poseidon *pd, v4l2_std_id *norm) -{ - struct video_data *video = &pd->video_data; - struct vbi_data *vbi = &pd->vbi_data; - struct running_context *context; - struct v4l2_pix_format *pix; - s32 i, ret = 0, cmd_status, param; - int height; - - for (i = 0; i < POSEIDON_TVNORMS; i++) { - if (*norm & poseidon_tvnorms[i].v4l2_id) { - param = poseidon_tvnorms[i].tlg_tvnorm; - log("name : %s", poseidon_tvnorms[i].name); - goto found; - } - } - return -EINVAL; -found: - mutex_lock(&pd->lock); - ret = send_set_req(pd, VIDEO_STD_SEL, param, &cmd_status); - if (ret || cmd_status) - goto out; - - /* Set vbi size and check the height of the frame */ - context = &video->context; - context->tvnormid = poseidon_tvnorms[i].v4l2_id; - if (context->tvnormid & V4L2_STD_525_60) { - vbi->vbi_size = V4L_NTSC_VBI_FRAMESIZE; - height = 480; - } else { - vbi->vbi_size = V4L_PAL_VBI_FRAMESIZE; - height = 576; - } - - pix = &context->pix; - if (pix->height != height) { - pix->height = height; - pix->sizeimage = pix->width * pix->height * 2; - } - -out: - mutex_unlock(&pd->lock); - return ret; -} - -static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *norm) -{ - struct front_face *front = fh; - logs(front); - return set_std(front->pd, norm); -} - -static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *in) -{ - struct front_face *front = fh; - - if (in->index < 0 || in->index >= POSEIDON_INPUTS) - return -EINVAL; - strcpy(in->name, pd_inputs[in->index].name); - in->type = V4L2_INPUT_TYPE_TUNER; - - /* - * the audio input index mixed with this video input, - * Poseidon only have one audio/video, set to "0" - */ - in->audioset = 0; - in->tuner = 0; - in->std = V4L2_STD_ALL; - in->status = 0; - logs(front); - return 0; -} - -static int vidioc_g_input(struct file *file, void *fh, unsigned int *i) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - struct running_context *context = &pd->video_data.context; - - logs(front); - *i = context->sig_index; - return 0; -} - -/* We can support several inputs */ -static int vidioc_s_input(struct file *file, void *fh, unsigned int i) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - s32 ret, cmd_status; - - if (i < 0 || i >= POSEIDON_INPUTS) - return -EINVAL; - ret = send_set_req(pd, SGNL_SRC_SEL, - pd_inputs[i].tlg_src, &cmd_status); - if (ret) - return ret; - - pd->video_data.context.sig_index = i; - return 0; -} - -static struct poseidon_control *check_control_id(__u32 id) -{ - struct poseidon_control *control = &controls[0]; - int array_size = ARRAY_SIZE(controls); - - for (; control < &controls[array_size]; control++) - if (control->v4l2_ctrl.id == id) - return control; - return NULL; -} - -static int vidioc_queryctrl(struct file *file, void *fh, - struct v4l2_queryctrl *a) -{ - struct poseidon_control *control = NULL; - - control = check_control_id(a->id); - if (!control) - return -EINVAL; - - *a = control->v4l2_ctrl; - return 0; -} - -static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *ctrl) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - struct poseidon_control *control = NULL; - struct tuner_custom_parameter_s tuner_param; - s32 ret = 0, cmd_status; - - control = check_control_id(ctrl->id); - if (!control) - return -EINVAL; - - mutex_lock(&pd->lock); - ret = send_get_req(pd, TUNER_CUSTOM_PARAMETER, control->vc_id, - &tuner_param, &cmd_status, sizeof(tuner_param)); - mutex_unlock(&pd->lock); - - if (ret || cmd_status) - return -1; - - ctrl->value = tuner_param.param_value; - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a) -{ - struct tuner_custom_parameter_s param = {0}; - struct poseidon_control *control = NULL; - struct front_face *front = fh; - struct poseidon *pd = front->pd; - s32 ret = 0, cmd_status, params; - - control = check_control_id(a->id); - if (!control) - return -EINVAL; - - param.param_value = a->value; - param.param_id = control->vc_id; - params = *(s32 *)¶m; /* temp code */ - - mutex_lock(&pd->lock); - ret = send_set_req(pd, TUNER_CUSTOM_PARAMETER, params, &cmd_status); - ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); - mutex_unlock(&pd->lock); - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); - return ret; -} - -/* Audio ioctls */ -static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a) -{ - if (0 != a->index) - return -EINVAL; - a->capability = V4L2_AUDCAP_STEREO; - strcpy(a->name, "USB audio in"); - /*Poseidon have no AVL function.*/ - a->mode = 0; - return 0; -} - -static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) -{ - a->index = 0; - a->capability = V4L2_AUDCAP_STEREO; - strcpy(a->name, "USB audio in"); - a->mode = 0; - return 0; -} - -static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) -{ - return (0 == a->index) ? 0 : -EINVAL; -} - -/* Tuner ioctls */ -static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *tuner) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - struct tuner_atv_sig_stat_s atv_stat; - s32 count = 5, ret, cmd_status; - int index; - - if (0 != tuner->index) - return -EINVAL; - - mutex_lock(&pd->lock); - ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_ANALOG_TV, - &atv_stat, &cmd_status, sizeof(atv_stat)); - - while (atv_stat.sig_lock_busy && count-- && !ret) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); - - ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_ANALOG_TV, - &atv_stat, &cmd_status, sizeof(atv_stat)); - } - mutex_unlock(&pd->lock); - - if (debug_mode) - log("P:%d,S:%d", atv_stat.sig_present, atv_stat.sig_strength); - - if (ret || cmd_status) - tuner->signal = 0; - else if (atv_stat.sig_present && !atv_stat.sig_strength) - tuner->signal = 0xFFFF; - else - tuner->signal = (atv_stat.sig_strength * 255 / 10) << 8; - - strcpy(tuner->name, "Telegent Systems"); - tuner->type = V4L2_TUNER_ANALOG_TV; - tuner->rangelow = TUNER_FREQ_MIN / 62500; - tuner->rangehigh = TUNER_FREQ_MAX / 62500; - tuner->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; - index = pd->video_data.context.audio_idx; - tuner->rxsubchans = pd_audio_modes[index].v4l2_audio_sub; - tuner->audmode = pd_audio_modes[index].v4l2_audio_mode; - tuner->afc = 0; - logs(front); - return 0; -} - -static int pd_vidioc_s_tuner(struct poseidon *pd, int index) -{ - s32 ret = 0, cmd_status, param, audiomode; - - mutex_lock(&pd->lock); - param = pd_audio_modes[index].tlg_audio_mode; - ret = send_set_req(pd, TUNER_AUD_MODE, param, &cmd_status); - audiomode = get_audio_std(pd->video_data.context.tvnormid); - ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode, - &cmd_status); - if (!ret) - pd->video_data.context.audio_idx = index; - mutex_unlock(&pd->lock); - return ret; -} - -static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *a) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - int index; - - if (0 != a->index) - return -EINVAL; - logs(front); - for (index = 0; index < POSEIDON_AUDIOMODS; index++) - if (a->audmode == pd_audio_modes[index].v4l2_audio_mode) - return pd_vidioc_s_tuner(pd, index); - return -EINVAL; -} - -static int vidioc_g_frequency(struct file *file, void *fh, - struct v4l2_frequency *freq) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - struct running_context *context = &pd->video_data.context; - - if (0 != freq->tuner) - return -EINVAL; - freq->frequency = context->freq; - freq->type = V4L2_TUNER_ANALOG_TV; - return 0; -} - -static int set_frequency(struct poseidon *pd, __u32 frequency) -{ - s32 ret = 0, param, cmd_status; - struct running_context *context = &pd->video_data.context; - - param = frequency * 62500 / 1000; - if (param < TUNER_FREQ_MIN/1000 || param > TUNER_FREQ_MAX / 1000) - return -EINVAL; - - mutex_lock(&pd->lock); - ret = send_set_req(pd, TUNE_FREQ_SELECT, param, &cmd_status); - ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); - - msleep(250); /* wait for a while until the hardware is ready. */ - context->freq = frequency; - mutex_unlock(&pd->lock); - return ret; -} - -static int vidioc_s_frequency(struct file *file, void *fh, - struct v4l2_frequency *freq) -{ - struct front_face *front = fh; - struct poseidon *pd = front->pd; - - logs(front); -#ifdef CONFIG_PM - pd->pm_suspend = pm_video_suspend; - pd->pm_resume = pm_video_resume; -#endif - return set_frequency(pd, freq->frequency); -} - -static int vidioc_reqbufs(struct file *file, void *fh, - struct v4l2_requestbuffers *b) -{ - struct front_face *front = file->private_data; - logs(front); - return videobuf_reqbufs(&front->q, b); -} - -static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *b) -{ - struct front_face *front = file->private_data; - logs(front); - return videobuf_querybuf(&front->q, b); -} - -static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) -{ - struct front_face *front = file->private_data; - return videobuf_qbuf(&front->q, b); -} - -static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) -{ - struct front_face *front = file->private_data; - return videobuf_dqbuf(&front->q, b, file->f_flags & O_NONBLOCK); -} - -/* Just stop the URBs, do not free the URBs */ -static int usb_transfer_stop(struct video_data *video) -{ - if (video->is_streaming) { - int i; - s32 cmd_status; - struct poseidon *pd = video->pd; - - video->is_streaming = 0; - for (i = 0; i < SBUF_NUM; ++i) { - if (video->urb_array[i]) - usb_kill_urb(video->urb_array[i]); - } - - send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, - &cmd_status); - } - return 0; -} - -int stop_all_video_stream(struct poseidon *pd) -{ - struct video_data *video = &pd->video_data; - struct vbi_data *vbi = &pd->vbi_data; - - mutex_lock(&pd->lock); - if (video->is_streaming) { - struct front_face *front = video->front; - - /* stop the URBs */ - usb_transfer_stop(video); - free_all_urb(video); - - /* stop the host side of VIDEO */ - videobuf_stop(&front->q); - videobuf_mmap_free(&front->q); - - /* stop the host side of VBI */ - front = vbi->front; - if (front) { - videobuf_stop(&front->q); - videobuf_mmap_free(&front->q); - } - } - mutex_unlock(&pd->lock); - return 0; -} - -/* - * The bubbles can seriously damage the video's quality, - * though it occurs in very rare situation. - */ -static void iso_bubble_handler(struct work_struct *w) -{ - struct video_data *video; - struct poseidon *pd; - - video = container_of(w, struct video_data, bubble_work); - pd = video->pd; - - mutex_lock(&pd->lock); - usb_transfer_stop(video); - msleep(500); - start_video_stream(pd); - mutex_unlock(&pd->lock); -} - - -static int vidioc_streamon(struct file *file, void *fh, - enum v4l2_buf_type type) -{ - struct front_face *front = fh; - - logs(front); - if (unlikely(type != front->type)) - return -EINVAL; - return videobuf_streamon(&front->q); -} - -static int vidioc_streamoff(struct file *file, void *fh, - enum v4l2_buf_type type) -{ - struct front_face *front = file->private_data; - - logs(front); - if (unlikely(type != front->type)) - return -EINVAL; - return videobuf_streamoff(&front->q); -} - -/* Set the firmware's default values : need altersetting */ -static int pd_video_checkmode(struct poseidon *pd) -{ - s32 ret = 0, cmd_status, audiomode; - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/2); - - /* choose the altersetting */ - ret = usb_set_interface(pd->udev, 0, - (pd->cur_transfer_mode ? - ISO_3K_BULK_ALTERNATE_IFACE : - BULK_ALTERNATE_IFACE)); - if (ret < 0) - goto error; - - /* set default parameters for PAL-D , with the VBI enabled*/ - ret = set_tuner_mode(pd, TLG_MODE_ANALOG_TV); - ret |= send_set_req(pd, SGNL_SRC_SEL, - TLG_SIG_SRC_ANTENNA, &cmd_status); - ret |= send_set_req(pd, VIDEO_STD_SEL, - TLG_TUNE_VSTD_PAL_D, &cmd_status); - ret |= send_set_req(pd, VIDEO_STREAM_FMT_SEL, - TLG_TUNER_VID_FORMAT_YUV, &cmd_status); - ret |= send_set_req(pd, VIDEO_ROSOLU_SEL, - TLG_TUNE_VID_RES_720, &cmd_status); - ret |= send_set_req(pd, TUNE_FREQ_SELECT, TUNER_FREQ_MIN, &cmd_status); - ret |= send_set_req(pd, VBI_DATA_SEL, 1, &cmd_status);/* enable vbi */ - - /* set the audio */ - audiomode = get_audio_std(pd->video_data.context.tvnormid); - ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode, &cmd_status); - ret |= send_set_req(pd, TUNER_AUD_MODE, - TLG_TUNE_TVAUDIO_MODE_STEREO, &cmd_status); - ret |= send_set_req(pd, AUDIO_SAMPLE_RATE_SEL, - ATV_AUDIO_RATE_48K, &cmd_status); -error: - return ret; -} - -#ifdef CONFIG_PM -static int pm_video_suspend(struct poseidon *pd) -{ - /* stop audio */ - pm_alsa_suspend(pd); - - /* stop and free all the URBs */ - usb_transfer_stop(&pd->video_data); - free_all_urb(&pd->video_data); - - /* reset the interface */ - usb_set_interface(pd->udev, 0, 0); - msleep(300); - return 0; -} - -static int restore_v4l2_context(struct poseidon *pd, - struct running_context *context) -{ - struct front_face *front = pd->video_data.front; - - pd_video_checkmode(pd); - - set_std(pd, &context->tvnormid); - vidioc_s_input(NULL, front, context->sig_index); - pd_vidioc_s_tuner(pd, context->audio_idx); - pd_vidioc_s_fmt(pd, &context->pix); - set_frequency(pd, context->freq); - return 0; -} - -static int pm_video_resume(struct poseidon *pd) -{ - struct video_data *video = &pd->video_data; - - /* resume the video */ - /* [1] restore the origin V4L2 parameters */ - restore_v4l2_context(pd, &video->context); - - /* [2] initiate video copy variables */ - if (video->front->curr_frame) - init_copy(video, 0); - - /* [3] fire urbs */ - start_video_stream(pd); - - /* resume the audio */ - pm_alsa_resume(pd); - return 0; -} -#endif - -void set_debug_mode(struct video_device *vfd, int debug_mode) -{ - vfd->debug = 0; - if (debug_mode & 0x1) - vfd->debug = V4L2_DEBUG_IOCTL; - if (debug_mode & 0x2) - vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; -} - -static void init_video_context(struct running_context *context) -{ - context->sig_index = 0; - context->audio_idx = 1; /* stereo */ - context->tvnormid = V4L2_STD_PAL_D; - context->pix = (struct v4l2_pix_format) { - .width = 720, - .height = 576, - .pixelformat = V4L2_PIX_FMT_YUYV, - .field = V4L2_FIELD_INTERLACED, - .bytesperline = 720 * 2, - .sizeimage = 720 * 576 * 2, - .colorspace = V4L2_COLORSPACE_SMPTE170M, - .priv = 0 - }; -} - -static int pd_video_open(struct file *file) -{ - struct video_device *vfd = video_devdata(file); - struct poseidon *pd = video_get_drvdata(vfd); - struct front_face *front = NULL; - int ret = -ENOMEM; - - mutex_lock(&pd->lock); - usb_autopm_get_interface(pd->interface); - - if (vfd->vfl_type == VFL_TYPE_GRABBER - && !(pd->state & POSEIDON_STATE_ANALOG)) { - front = kzalloc(sizeof(struct front_face), GFP_KERNEL); - if (!front) - goto out; - - pd->cur_transfer_mode = usb_transfer_mode;/* bulk or iso */ - init_video_context(&pd->video_data.context); - - ret = pd_video_checkmode(pd); - if (ret < 0) { - kfree(front); - ret = -1; - goto out; - } - - pd->state |= POSEIDON_STATE_ANALOG; - front->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - pd->video_data.users++; - set_debug_mode(vfd, debug_mode); - - videobuf_queue_vmalloc_init(&front->q, &pd_video_qops, - NULL, &front->queue_lock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED,/* video is interlacd */ - sizeof(struct videobuf_buffer),/*it's enough*/ - front, NULL); - } else if (vfd->vfl_type == VFL_TYPE_VBI - && !(pd->state & POSEIDON_STATE_VBI)) { - front = kzalloc(sizeof(struct front_face), GFP_KERNEL); - if (!front) - goto out; - - pd->state |= POSEIDON_STATE_VBI; - front->type = V4L2_BUF_TYPE_VBI_CAPTURE; - pd->vbi_data.front = front; - pd->vbi_data.users++; - - videobuf_queue_vmalloc_init(&front->q, &pd_video_qops, - NULL, &front->queue_lock, - V4L2_BUF_TYPE_VBI_CAPTURE, - V4L2_FIELD_NONE, /* vbi is NONE mode */ - sizeof(struct videobuf_buffer), - front, NULL); - } else { - /* maybe add FM support here */ - log("other "); - ret = -EINVAL; - goto out; - } - - front->pd = pd; - front->curr_frame = NULL; - INIT_LIST_HEAD(&front->active); - spin_lock_init(&front->queue_lock); - - file->private_data = front; - kref_get(&pd->kref); - - mutex_unlock(&pd->lock); - return 0; -out: - usb_autopm_put_interface(pd->interface); - mutex_unlock(&pd->lock); - return ret; -} - -static int pd_video_release(struct file *file) -{ - struct front_face *front = file->private_data; - struct poseidon *pd = front->pd; - s32 cmd_status = 0; - - logs(front); - mutex_lock(&pd->lock); - - if (front->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - pd->state &= ~POSEIDON_STATE_ANALOG; - - /* stop the device, and free the URBs */ - usb_transfer_stop(&pd->video_data); - free_all_urb(&pd->video_data); - - /* stop the firmware */ - send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, - &cmd_status); - - pd->file_for_stream = NULL; - pd->video_data.users--; - } else if (front->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - pd->state &= ~POSEIDON_STATE_VBI; - pd->vbi_data.front = NULL; - pd->vbi_data.users--; - } - videobuf_stop(&front->q); - videobuf_mmap_free(&front->q); - - usb_autopm_put_interface(pd->interface); - mutex_unlock(&pd->lock); - - kfree(front); - file->private_data = NULL; - kref_put(&pd->kref, poseidon_delete); - return 0; -} - -static int pd_video_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct front_face *front = file->private_data; - return videobuf_mmap_mapper(&front->q, vma); -} - -static unsigned int pd_video_poll(struct file *file, poll_table *table) -{ - struct front_face *front = file->private_data; - return videobuf_poll_stream(file, &front->q, table); -} - -static ssize_t pd_video_read(struct file *file, char __user *buffer, - size_t count, loff_t *ppos) -{ - struct front_face *front = file->private_data; - return videobuf_read_stream(&front->q, buffer, count, ppos, - 0, file->f_flags & O_NONBLOCK); -} - -/* This struct works for both VIDEO and VBI */ -static const struct v4l2_file_operations pd_video_fops = { - .owner = THIS_MODULE, - .open = pd_video_open, - .release = pd_video_release, - .read = pd_video_read, - .poll = pd_video_poll, - .mmap = pd_video_mmap, - .ioctl = video_ioctl2, /* maybe changed in future */ -}; - -static const struct v4l2_ioctl_ops pd_video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - - /* Video format */ - .vidioc_g_fmt_vid_cap = vidioc_g_fmt, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt, - .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi, /* VBI */ - .vidioc_try_fmt_vid_cap = vidioc_try_fmt, - - /* Input */ - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_enum_input = vidioc_enum_input, - - /* Audio ioctls */ - .vidioc_enumaudio = vidioc_enumaudio, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - - /* Tuner ioctls */ - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_s_std = vidioc_s_std, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, - - /* Buffer handlers */ - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, - - /* Stream on/off */ - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - - /* Control handling */ - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, -}; - -static struct video_device pd_video_template = { - .name = "Telegent-Video", - .fops = &pd_video_fops, - .minor = -1, - .release = video_device_release, - .tvnorms = V4L2_STD_ALL, - .ioctl_ops = &pd_video_ioctl_ops, -}; - -struct video_device *vdev_init(struct poseidon *pd, struct video_device *tmp) -{ - struct video_device *vfd; - - vfd = video_device_alloc(); - if (vfd == NULL) - return NULL; - *vfd = *tmp; - vfd->minor = -1; - vfd->v4l2_dev = &pd->v4l2_dev; - /*vfd->parent = &(pd->udev->dev); */ - vfd->release = video_device_release; - video_set_drvdata(vfd, pd); - return vfd; -} - -void destroy_video_device(struct video_device **v_dev) -{ - struct video_device *dev = *v_dev; - - if (dev == NULL) - return; - - if (video_is_registered(dev)) - video_unregister_device(dev); - else - video_device_release(dev); - *v_dev = NULL; -} - -void pd_video_exit(struct poseidon *pd) -{ - struct video_data *video = &pd->video_data; - struct vbi_data *vbi = &pd->vbi_data; - - destroy_video_device(&video->v_dev); - destroy_video_device(&vbi->v_dev); - log(); -} - -int pd_video_init(struct poseidon *pd) -{ - struct video_data *video = &pd->video_data; - struct vbi_data *vbi = &pd->vbi_data; - int ret = -ENOMEM; - - video->v_dev = vdev_init(pd, &pd_video_template); - if (video->v_dev == NULL) - goto out; - - ret = video_register_device(video->v_dev, VFL_TYPE_GRABBER, -1); - if (ret != 0) - goto out; - - /* VBI uses the same template as video */ - vbi->v_dev = vdev_init(pd, &pd_video_template); - if (vbi->v_dev == NULL) { - ret = -ENOMEM; - goto out; - } - ret = video_register_device(vbi->v_dev, VFL_TYPE_VBI, -1); - if (ret != 0) - goto out; - log("register VIDEO/VBI devices"); - return 0; -out: - log("VIDEO/VBI devices register failed, : %d", ret); - pd_video_exit(pd); - return ret; -} - diff --git a/drivers/media/video/tlg2300/vendorcmds.h b/drivers/media/video/tlg2300/vendorcmds.h deleted file mode 100644 index ba6f4ae3b2c2..000000000000 --- a/drivers/media/video/tlg2300/vendorcmds.h +++ /dev/null @@ -1,243 +0,0 @@ -#ifndef VENDOR_CMD_H_ -#define VENDOR_CMD_H_ - -#define BULK_ALTERNATE_IFACE (2) -#define ISO_3K_BULK_ALTERNATE_IFACE (1) -#define REQ_SET_CMD (0X00) -#define REQ_GET_CMD (0X80) - -enum tlg__analog_audio_standard { - TLG_TUNE_ASTD_NONE = 0x00000000, - TLG_TUNE_ASTD_A2 = 0x00000001, - TLG_TUNE_ASTD_NICAM = 0x00000002, - TLG_TUNE_ASTD_EIAJ = 0x00000004, - TLG_TUNE_ASTD_BTSC = 0x00000008, - TLG_TUNE_ASTD_FM_US = 0x00000010, - TLG_TUNE_ASTD_FM_EUR = 0x00000020, - TLG_TUNE_ASTD_ALL = 0x0000003f -}; - -/* - * identifiers for Custom Parameter messages. - * @typedef cmd_custom_param_id_t - */ -enum cmd_custom_param_id { - CUST_PARM_ID_NONE = 0x00, - CUST_PARM_ID_BRIGHTNESS_CTRL = 0x01, - CUST_PARM_ID_CONTRAST_CTRL = 0x02, - CUST_PARM_ID_HUE_CTRL = 0x03, - CUST_PARM_ID_SATURATION_CTRL = 0x04, - CUST_PARM_ID_AUDIO_SNR_THRESHOLD = 0x10, - CUST_PARM_ID_AUDIO_AGC_THRESHOLD = 0x11, - CUST_PARM_ID_MAX -}; - -struct tuner_custom_parameter_s { - uint16_t param_id; /* Parameter identifier */ - uint16_t param_value; /* Parameter value */ -}; - -struct tuner_ber_rate_s { - uint32_t ber_rate; /* BER sample rate in seconds */ -}; - -struct tuner_atv_sig_stat_s { - uint32_t sig_present; - uint32_t sig_locked; - uint32_t sig_lock_busy; - uint32_t sig_strength; /* milliDb */ - uint32_t tv_audio_chan; /* mono/stereo/sap*/ - uint32_t mvision_stat; /* macrovision status */ -}; - -struct tuner_dtv_sig_stat_s { - uint32_t sig_present; /* Boolean*/ - uint32_t sig_locked; /* Boolean */ - uint32_t sig_lock_busy; /* Boolean (Can this time-out?) */ - uint32_t sig_strength; /* milliDb*/ -}; - -struct tuner_fm_sig_stat_s { - uint32_t sig_present; /* Boolean*/ - uint32_t sig_locked; /* Boolean */ - uint32_t sig_lock_busy; /* Boolean */ - uint32_t sig_stereo_mono;/* TBD*/ - uint32_t sig_strength; /* milliDb*/ -}; - -enum _tag_tlg_tune_srv_cmd { - TLG_TUNE_PLAY_SVC_START = 1, - TLG_TUNE_PLAY_SVC_STOP -}; - -enum _tag_tune_atv_audio_mode_caps { - TLG_TUNE_TVAUDIO_MODE_MONO = 0x00000001, - TLG_TUNE_TVAUDIO_MODE_STEREO = 0x00000002, - TLG_TUNE_TVAUDIO_MODE_LANG_A = 0x00000010,/* Primary language*/ - TLG_TUNE_TVAUDIO_MODE_LANG_B = 0x00000020,/* 2nd avail language*/ - TLG_TUNE_TVAUDIO_MODE_LANG_C = 0x00000040 -}; - - -enum _tag_tuner_atv_audio_rates { - ATV_AUDIO_RATE_NONE = 0x00,/* Audio not supported*/ - ATV_AUDIO_RATE_32K = 0x01,/* Audio rate = 32 KHz*/ - ATV_AUDIO_RATE_48K = 0x02, /* Audio rate = 48 KHz*/ - ATV_AUDIO_RATE_31_25K = 0x04 /* Audio rate = 31.25KHz */ -}; - -enum _tag_tune_atv_vid_res_caps { - TLG_TUNE_VID_RES_NONE = 0x00000000, - TLG_TUNE_VID_RES_720 = 0x00000001, - TLG_TUNE_VID_RES_704 = 0x00000002, - TLG_TUNE_VID_RES_360 = 0x00000004 -}; - -enum _tag_tuner_analog_video_format { - TLG_TUNER_VID_FORMAT_YUV = 0x00000001, - TLG_TUNER_VID_FORMAT_YCRCB = 0x00000002, - TLG_TUNER_VID_FORMAT_RGB_565 = 0x00000004, -}; - -enum tlg_ext_audio_support { - TLG_EXT_AUDIO_NONE = 0x00,/* No external audio input supported */ - TLG_EXT_AUDIO_LR = 0x01/* LR external audio inputs supported*/ -}; - -enum { - TLG_MODE_NONE = 0x00, /* No Mode specified*/ - TLG_MODE_ANALOG_TV = 0x01, /* Analog Television mode*/ - TLG_MODE_ANALOG_TV_UNCOMP = 0x01, /* Analog Television mode*/ - TLG_MODE_ANALOG_TV_COMP = 0x02, /* Analog TV mode (compressed)*/ - TLG_MODE_FM_RADIO = 0x04, /* FM Radio mode*/ - TLG_MODE_DVB_T = 0x08, /* Digital TV (DVB-T)*/ -}; - -enum tlg_signal_sources_t { - TLG_SIG_SRC_NONE = 0x00,/* Signal source not specified */ - TLG_SIG_SRC_ANTENNA = 0x01,/* Signal src is: Antenna */ - TLG_SIG_SRC_CABLE = 0x02,/* Signal src is: Coax Cable*/ - TLG_SIG_SRC_SVIDEO = 0x04,/* Signal src is: S_VIDEO */ - TLG_SIG_SRC_COMPOSITE = 0x08 /* Signal src is: Composite Video */ -}; - -enum tuner_analog_video_standard { - TLG_TUNE_VSTD_NONE = 0x00000000, - TLG_TUNE_VSTD_NTSC_M = 0x00000001, - TLG_TUNE_VSTD_NTSC_M_J = 0x00000002,/* Japan */ - TLG_TUNE_VSTD_PAL_B = 0x00000010, - TLG_TUNE_VSTD_PAL_D = 0x00000020, - TLG_TUNE_VSTD_PAL_G = 0x00000040, - TLG_TUNE_VSTD_PAL_H = 0x00000080, - TLG_TUNE_VSTD_PAL_I = 0x00000100, - TLG_TUNE_VSTD_PAL_M = 0x00000200, - TLG_TUNE_VSTD_PAL_N = 0x00000400, - TLG_TUNE_VSTD_SECAM_B = 0x00001000, - TLG_TUNE_VSTD_SECAM_D = 0x00002000, - TLG_TUNE_VSTD_SECAM_G = 0x00004000, - TLG_TUNE_VSTD_SECAM_H = 0x00008000, - TLG_TUNE_VSTD_SECAM_K = 0x00010000, - TLG_TUNE_VSTD_SECAM_K1 = 0x00020000, - TLG_TUNE_VSTD_SECAM_L = 0x00040000, - TLG_TUNE_VSTD_SECAM_L1 = 0x00080000, - TLG_TUNE_VSTD_PAL_N_COMBO = 0x00100000 -}; - -enum tlg_mode_caps { - TLG_MODE_CAPS_NONE = 0x00, /* No Mode specified */ - TLG_MODE_CAPS_ANALOG_TV_UNCOMP = 0x01, /* Analog TV mode */ - TLG_MODE_CAPS_ANALOG_TV_COMP = 0x02, /* Analog TV (compressed)*/ - TLG_MODE_CAPS_FM_RADIO = 0x04, /* FM Radio mode */ - TLG_MODE_CAPS_DVB_T = 0x08, /* Digital TV (DVB-T) */ -}; - -enum poseidon_vendor_cmds { - LAST_CMD_STAT = 0x00, - GET_CHIP_ID = 0x01, - GET_FW_ID = 0x02, - PRODUCT_CAPS = 0x03, - - TUNE_MODE_CAP_ATV = 0x10, - TUNE_MODE_CAP_ATVCOMP = 0X10, - TUNE_MODE_CAP_DVBT = 0x10, - TUNE_MODE_CAP_FM = 0x10, - TUNE_MODE_SELECT = 0x11, - TUNE_FREQ_SELECT = 0x12, - SGNL_SRC_SEL = 0x13, - - VIDEO_STD_SEL = 0x14, - VIDEO_STREAM_FMT_SEL = 0x15, - VIDEO_ROSOLU_AVAIL = 0x16, - VIDEO_ROSOLU_SEL = 0x17, - VIDEO_CONT_PROTECT = 0x20, - - VCR_TIMING_MODSEL = 0x21, - EXT_AUDIO_CAP = 0x22, - EXT_AUDIO_SEL = 0x23, - TEST_PATTERN_SEL = 0x24, - VBI_DATA_SEL = 0x25, - AUDIO_SAMPLE_RATE_CAP = 0x28, - AUDIO_SAMPLE_RATE_SEL = 0x29, - TUNER_AUD_MODE = 0x2a, - TUNER_AUD_MODE_AVAIL = 0x2b, - TUNER_AUD_ANA_STD = 0x2c, - TUNER_CUSTOM_PARAMETER = 0x2f, - - DVBT_TUNE_MODE_SEL = 0x30, - DVBT_BANDW_CAP = 0x31, - DVBT_BANDW_SEL = 0x32, - DVBT_GUARD_INTERV_CAP = 0x33, - DVBT_GUARD_INTERV_SEL = 0x34, - DVBT_MODULATION_CAP = 0x35, - DVBT_MODULATION_SEL = 0x36, - DVBT_INNER_FEC_RATE_CAP = 0x37, - DVBT_INNER_FEC_RATE_SEL = 0x38, - DVBT_TRANS_MODE_CAP = 0x39, - DVBT_TRANS_MODE_SEL = 0x3a, - DVBT_SEARCH_RANG = 0x3c, - - TUNER_SETUP_ANALOG = 0x40, - TUNER_SETUP_DIGITAL = 0x41, - TUNER_SETUP_FM_RADIO = 0x42, - TAKE_REQUEST = 0x43, /* Take effect of the command */ - PLAY_SERVICE = 0x44, /* Play start or Play stop */ - TUNER_STATUS = 0x45, - TUNE_PROP_DVBT = 0x46, - ERR_RATE_STATS = 0x47, - TUNER_BER_RATE = 0x48, - - SCAN_CAPS = 0x50, - SCAN_SETUP = 0x51, - SCAN_SERVICE = 0x52, - SCAN_STATS = 0x53, - - PID_SET = 0x58, - PID_UNSET = 0x59, - PID_LIST = 0x5a, - - IRD_CAP = 0x60, - IRD_MODE_SEL = 0x61, - IRD_SETUP = 0x62, - - PTM_MODE_CAP = 0x70, - PTM_MODE_SEL = 0x71, - PTM_SERVICE = 0x72, - TUNER_REG_SCRIPT = 0x73, - CMD_CHIP_RST = 0x74, -}; - -enum tlg_bw { - TLG_BW_5 = 5, - TLG_BW_6 = 6, - TLG_BW_7 = 7, - TLG_BW_8 = 8, - TLG_BW_12 = 12, - TLG_BW_15 = 15 -}; - -struct cmd_firmware_vers_s { - uint8_t fw_rev_major; - uint8_t fw_rev_minor; - uint16_t fw_patch; -}; -#endif /* VENDOR_CMD_H_ */ diff --git a/drivers/media/video/tm6000/Kconfig b/drivers/media/video/tm6000/Kconfig deleted file mode 100644 index a43b77abd931..000000000000 --- a/drivers/media/video/tm6000/Kconfig +++ /dev/null @@ -1,33 +0,0 @@ -config VIDEO_TM6000 - tristate "TV Master TM5600/6000/6010 driver" - depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB - select VIDEO_TUNER - select MEDIA_TUNER_XC2028 - select MEDIA_TUNER_XC5000 - select VIDEOBUF_VMALLOC - help - Support for TM5600/TM6000/TM6010 USB Device - - Since these cards have no MPEG decoder onboard, they transmit - only compressed MPEG data over the usb bus, so you need - an external software decoder to watch TV on your computer. - - Say Y if you own such a device and want to use it. - -config VIDEO_TM6000_ALSA - tristate "TV Master TM5600/6000/6010 audio support" - depends on VIDEO_TM6000 && SND - select SND_PCM - ---help--- - This is a video4linux driver for direct (DMA) audio for - TM5600/TM6000/TM6010 USB Devices. - - To compile this driver as a module, choose M here: the - module will be called tm6000-alsa. - -config VIDEO_TM6000_DVB - tristate "DVB Support for tm6000 based TV cards" - depends on VIDEO_TM6000 && DVB_CORE && USB - select DVB_ZL10353 - ---help--- - This adds support for DVB cards based on the tm5600/tm6000 chip. diff --git a/drivers/media/video/tm6000/Makefile b/drivers/media/video/tm6000/Makefile deleted file mode 100644 index 1feb8c9c816c..000000000000 --- a/drivers/media/video/tm6000/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -tm6000-y := tm6000-cards.o \ - tm6000-core.o \ - tm6000-i2c.o \ - tm6000-video.o \ - tm6000-stds.o \ - tm6000-input.o - -obj-$(CONFIG_VIDEO_TM6000) += tm6000.o -obj-$(CONFIG_VIDEO_TM6000_ALSA) += tm6000-alsa.o -obj-$(CONFIG_VIDEO_TM6000_DVB) += tm6000-dvb.o - -ccflags-y := -Idrivers/media/video -ccflags-y += -Idrivers/media/tuners -ccflags-y += -Idrivers/media/dvb-core -ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/video/tm6000/tm6000-alsa.c b/drivers/media/video/tm6000/tm6000-alsa.c deleted file mode 100644 index bd07ec707956..000000000000 --- a/drivers/media/video/tm6000/tm6000-alsa.c +++ /dev/null @@ -1,528 +0,0 @@ -/* - * - * Support for audio capture for tm5600/6000/6010 - * (c) 2007-2008 Mauro Carvalho Chehab <mchehab@redhat.com> - * - * Based on cx88-alsa.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#include <linux/usb.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> - -#include <linux/delay.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/control.h> -#include <sound/initval.h> - - -#include "tm6000.h" -#include "tm6000-regs.h" - -#undef dprintk - -#define dprintk(level, fmt, arg...) do { \ - if (debug >= level) \ - printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg); \ - } while (0) - -/**************************************************************************** - Module global static vars - ****************************************************************************/ - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ - -static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; - -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable tm6000x soundcard. default enabled."); - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for tm6000x capture interface(s)."); - - -/**************************************************************************** - Module macros - ****************************************************************************/ - -MODULE_DESCRIPTION("ALSA driver module for tm5600/tm6000/tm6010 based TV cards"); -MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Trident,tm5600}," - "{{Trident,tm6000}," - "{{Trident,tm6010}"); -static unsigned int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "enable debug messages"); - -/**************************************************************************** - Module specific funtions - ****************************************************************************/ - -/* - * BOARD Specific: Sets audio DMA - */ - -static int _tm6000_start_audio_dma(struct snd_tm6000_card *chip) -{ - struct tm6000_core *core = chip->core; - - dprintk(1, "Starting audio DMA\n"); - - /* Enables audio */ - tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_IF, 0x40, 0x40); - - tm6000_set_audio_bitrate(core, 48000); - - return 0; -} - -/* - * BOARD Specific: Resets audio DMA - */ -static int _tm6000_stop_audio_dma(struct snd_tm6000_card *chip) -{ - struct tm6000_core *core = chip->core; - - dprintk(1, "Stopping audio DMA\n"); - - /* Disables audio */ - tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_IF, 0x00, 0x40); - - return 0; -} - -static void dsp_buffer_free(struct snd_pcm_substream *substream) -{ - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - - dprintk(2, "Freeing buffer\n"); - - vfree(substream->runtime->dma_area); - substream->runtime->dma_area = NULL; - substream->runtime->dma_bytes = 0; -} - -static int dsp_buffer_alloc(struct snd_pcm_substream *substream, int size) -{ - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - - dprintk(2, "Allocating buffer\n"); - - if (substream->runtime->dma_area) { - if (substream->runtime->dma_bytes > size) - return 0; - - dsp_buffer_free(substream); - } - - substream->runtime->dma_area = vmalloc(size); - if (!substream->runtime->dma_area) - return -ENOMEM; - - substream->runtime->dma_bytes = size; - - return 0; -} - - -/**************************************************************************** - ALSA PCM Interface - ****************************************************************************/ - -/* - * Digital hardware definition - */ -#define DEFAULT_FIFO_SIZE 4096 - -static struct snd_pcm_hardware snd_tm6000_digital_hw = { - .info = SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .period_bytes_min = 64, - .period_bytes_max = 12544, - .periods_min = 2, - .periods_max = 98, - .buffer_bytes_max = 62720 * 8, -}; - -/* - * audio pcm capture open callback - */ -static int snd_tm6000_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - err = snd_pcm_hw_constraint_pow2(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) - goto _error; - - chip->substream = substream; - - runtime->hw = snd_tm6000_digital_hw; - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - - return 0; -_error: - dprintk(1, "Error opening PCM!\n"); - return err; -} - -/* - * audio close callback - */ -static int snd_tm6000_close(struct snd_pcm_substream *substream) -{ - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - struct tm6000_core *core = chip->core; - - if (atomic_read(&core->stream_started) > 0) { - atomic_set(&core->stream_started, 0); - schedule_work(&core->wq_trigger); - } - - return 0; -} - -static int tm6000_fillbuf(struct tm6000_core *core, char *buf, int size) -{ - struct snd_tm6000_card *chip = core->adev; - struct snd_pcm_substream *substream = chip->substream; - struct snd_pcm_runtime *runtime; - int period_elapsed = 0; - unsigned int stride, buf_pos; - int length; - - if (atomic_read(&core->stream_started) == 0) - return 0; - - if (!size || !substream) { - dprintk(1, "substream was NULL\n"); - return -EINVAL; - } - - runtime = substream->runtime; - if (!runtime || !runtime->dma_area) { - dprintk(1, "runtime was NULL\n"); - return -EINVAL; - } - - buf_pos = chip->buf_pos; - stride = runtime->frame_bits >> 3; - - if (stride == 0) { - dprintk(1, "stride is zero\n"); - return -EINVAL; - } - - length = size / stride; - if (length == 0) { - dprintk(1, "%s: length was zero\n", __func__); - return -EINVAL; - } - - dprintk(1, "Copying %d bytes at %p[%d] - buf size=%d x %d\n", size, - runtime->dma_area, buf_pos, - (unsigned int)runtime->buffer_size, stride); - - if (buf_pos + length >= runtime->buffer_size) { - unsigned int cnt = runtime->buffer_size - buf_pos; - memcpy(runtime->dma_area + buf_pos * stride, buf, cnt * stride); - memcpy(runtime->dma_area, buf + cnt * stride, - length * stride - cnt * stride); - } else - memcpy(runtime->dma_area + buf_pos * stride, buf, - length * stride); - - snd_pcm_stream_lock(substream); - - chip->buf_pos += length; - if (chip->buf_pos >= runtime->buffer_size) - chip->buf_pos -= runtime->buffer_size; - - chip->period_pos += length; - if (chip->period_pos >= runtime->period_size) { - chip->period_pos -= runtime->period_size; - period_elapsed = 1; - } - - snd_pcm_stream_unlock(substream); - - if (period_elapsed) - snd_pcm_period_elapsed(substream); - - return 0; -} - -/* - * hw_params callback - */ -static int snd_tm6000_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - int size, rc; - - size = params_period_bytes(hw_params) * params_periods(hw_params); - - rc = dsp_buffer_alloc(substream, size); - if (rc < 0) - return rc; - - return 0; -} - -/* - * hw free callback - */ -static int snd_tm6000_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - struct tm6000_core *core = chip->core; - - if (atomic_read(&core->stream_started) > 0) { - atomic_set(&core->stream_started, 0); - schedule_work(&core->wq_trigger); - } - - dsp_buffer_free(substream); - return 0; -} - -/* - * prepare callback - */ -static int snd_tm6000_prepare(struct snd_pcm_substream *substream) -{ - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - - chip->buf_pos = 0; - chip->period_pos = 0; - - return 0; -} - - -/* - * trigger callback - */ -static void audio_trigger(struct work_struct *work) -{ - struct tm6000_core *core = container_of(work, struct tm6000_core, - wq_trigger); - struct snd_tm6000_card *chip = core->adev; - - if (atomic_read(&core->stream_started)) { - dprintk(1, "starting capture"); - _tm6000_start_audio_dma(chip); - } else { - dprintk(1, "stopping capture"); - _tm6000_stop_audio_dma(chip); - } -} - -static int snd_tm6000_card_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - struct tm6000_core *core = chip->core; - int err = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ - case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ - case SNDRV_PCM_TRIGGER_START: - atomic_set(&core->stream_started, 1); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ - case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ - case SNDRV_PCM_TRIGGER_STOP: - atomic_set(&core->stream_started, 0); - break; - default: - err = -EINVAL; - break; - } - schedule_work(&core->wq_trigger); - - return err; -} -/* - * pointer callback - */ -static snd_pcm_uframes_t snd_tm6000_pointer(struct snd_pcm_substream *substream) -{ - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - - return chip->buf_pos; -} - -static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, - unsigned long offset) -{ - void *pageptr = subs->runtime->dma_area + offset; - - return vmalloc_to_page(pageptr); -} - -/* - * operators - */ -static struct snd_pcm_ops snd_tm6000_pcm_ops = { - .open = snd_tm6000_pcm_open, - .close = snd_tm6000_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_tm6000_hw_params, - .hw_free = snd_tm6000_hw_free, - .prepare = snd_tm6000_prepare, - .trigger = snd_tm6000_card_trigger, - .pointer = snd_tm6000_pointer, - .page = snd_pcm_get_vmalloc_page, -}; - -/* - * create a PCM device - */ - -/* FIXME: Control interface - How to control volume/mute? */ - -/**************************************************************************** - Basic Flow for Sound Devices - ****************************************************************************/ - -/* - * Alsa Constructor - Component probe - */ -static int tm6000_audio_init(struct tm6000_core *dev) -{ - struct snd_card *card; - struct snd_tm6000_card *chip; - int rc; - static int devnr; - char component[14]; - struct snd_pcm *pcm; - - if (!dev) - return 0; - - if (devnr >= SNDRV_CARDS) - return -ENODEV; - - if (!enable[devnr]) - return -ENOENT; - - rc = snd_card_create(index[devnr], "tm6000", THIS_MODULE, 0, &card); - if (rc < 0) { - snd_printk(KERN_ERR "cannot create card instance %d\n", devnr); - return rc; - } - strcpy(card->driver, "tm6000-alsa"); - strcpy(card->shortname, "TM5600/60x0"); - sprintf(card->longname, "TM5600/60x0 Audio at bus %d device %d", - dev->udev->bus->busnum, dev->udev->devnum); - - sprintf(component, "USB%04x:%04x", - le16_to_cpu(dev->udev->descriptor.idVendor), - le16_to_cpu(dev->udev->descriptor.idProduct)); - snd_component_add(card, component); - snd_card_set_dev(card, &dev->udev->dev); - - chip = kzalloc(sizeof(struct snd_tm6000_card), GFP_KERNEL); - if (!chip) { - rc = -ENOMEM; - goto error; - } - - chip->core = dev; - chip->card = card; - dev->adev = chip; - spin_lock_init(&chip->reg_lock); - - rc = snd_pcm_new(card, "TM6000 Audio", 0, 0, 1, &pcm); - if (rc < 0) - goto error_chip; - - pcm->info_flags = 0; - pcm->private_data = chip; - strcpy(pcm->name, "Trident TM5600/60x0"); - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_tm6000_pcm_ops); - - INIT_WORK(&dev->wq_trigger, audio_trigger); - rc = snd_card_register(card); - if (rc < 0) - goto error_chip; - - dprintk(1, "Registered audio driver for %s\n", card->longname); - - return 0; - -error_chip: - kfree(chip); - dev->adev = NULL; -error: - snd_card_free(card); - return rc; -} - -static int tm6000_audio_fini(struct tm6000_core *dev) -{ - struct snd_tm6000_card *chip = dev->adev; - - if (!dev) - return 0; - - if (!chip) - return 0; - - if (!chip->card) - return 0; - - snd_card_free(chip->card); - chip->card = NULL; - kfree(chip); - dev->adev = NULL; - - return 0; -} - -static struct tm6000_ops audio_ops = { - .type = TM6000_AUDIO, - .name = "TM6000 Audio Extension", - .init = tm6000_audio_init, - .fini = tm6000_audio_fini, - .fillbuf = tm6000_fillbuf, -}; - -static int __init tm6000_alsa_register(void) -{ - return tm6000_register_extension(&audio_ops); -} - -static void __exit tm6000_alsa_unregister(void) -{ - tm6000_unregister_extension(&audio_ops); -} - -module_init(tm6000_alsa_register); -module_exit(tm6000_alsa_unregister); diff --git a/drivers/media/video/tm6000/tm6000-cards.c b/drivers/media/video/tm6000/tm6000-cards.c deleted file mode 100644 index 034659b13174..000000000000 --- a/drivers/media/video/tm6000/tm6000-cards.c +++ /dev/null @@ -1,1413 +0,0 @@ -/* - * tm6000-cards.c - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/usb.h> -#include <linux/slab.h> -#include <media/v4l2-common.h> -#include <media/tuner.h> -#include <media/tvaudio.h> -#include <media/i2c-addr.h> -#include <media/rc-map.h> - -#include "tm6000.h" -#include "tm6000-regs.h" -#include "tuner-xc2028.h" -#include "xc5000.h" - -#define TM6000_BOARD_UNKNOWN 0 -#define TM5600_BOARD_GENERIC 1 -#define TM6000_BOARD_GENERIC 2 -#define TM6010_BOARD_GENERIC 3 -#define TM5600_BOARD_10MOONS_UT821 4 -#define TM5600_BOARD_10MOONS_UT330 5 -#define TM6000_BOARD_ADSTECH_DUAL_TV 6 -#define TM6000_BOARD_FREECOM_AND_SIMILAR 7 -#define TM6000_BOARD_ADSTECH_MINI_DUAL_TV 8 -#define TM6010_BOARD_HAUPPAUGE_900H 9 -#define TM6010_BOARD_BEHOLD_WANDER 10 -#define TM6010_BOARD_BEHOLD_VOYAGER 11 -#define TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE 12 -#define TM6010_BOARD_TWINHAN_TU501 13 -#define TM6010_BOARD_BEHOLD_WANDER_LITE 14 -#define TM6010_BOARD_BEHOLD_VOYAGER_LITE 15 -#define TM5600_BOARD_TERRATEC_GRABSTER 16 - -#define is_generic(model) ((model == TM6000_BOARD_UNKNOWN) || \ - (model == TM5600_BOARD_GENERIC) || \ - (model == TM6000_BOARD_GENERIC) || \ - (model == TM6010_BOARD_GENERIC)) - -#define TM6000_MAXBOARDS 16 -static unsigned int card[] = {[0 ... (TM6000_MAXBOARDS - 1)] = UNSET }; - -module_param_array(card, int, NULL, 0444); - -static unsigned long tm6000_devused; - - -struct tm6000_board { - char *name; - char eename[16]; /* EEPROM name */ - unsigned eename_size; /* size of EEPROM name */ - unsigned eename_pos; /* Position where it appears at ROM */ - - struct tm6000_capabilities caps; - - enum tm6000_devtype type; /* variant of the chipset */ - int tuner_type; /* type of the tuner */ - int tuner_addr; /* tuner address */ - int demod_addr; /* demodulator address */ - - struct tm6000_gpio gpio; - - struct tm6000_input vinput[3]; - struct tm6000_input rinput; - - char *ir_codes; -}; - -static struct tm6000_board tm6000_boards[] = { - [TM6000_BOARD_UNKNOWN] = { - .name = "Unknown tm6000 video grabber", - .caps = { - .has_tuner = 1, - .has_eeprom = 1, - }, - .gpio = { - .tuner_reset = TM6000_GPIO_1, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM5600_BOARD_GENERIC] = { - .name = "Generic tm5600 board", - .type = TM5600, - .tuner_type = TUNER_XC2028, - .tuner_addr = 0xc2 >> 1, - .caps = { - .has_tuner = 1, - .has_eeprom = 1, - }, - .gpio = { - .tuner_reset = TM6000_GPIO_1, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6000_BOARD_GENERIC] = { - .name = "Generic tm6000 board", - .tuner_type = TUNER_XC2028, - .tuner_addr = 0xc2 >> 1, - .caps = { - .has_tuner = 1, - .has_eeprom = 1, - }, - .gpio = { - .tuner_reset = TM6000_GPIO_1, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6010_BOARD_GENERIC] = { - .name = "Generic tm6010 board", - .type = TM6010, - .tuner_type = TUNER_XC2028, - .tuner_addr = 0xc2 >> 1, - .demod_addr = 0x1e >> 1, - .caps = { - .has_tuner = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 1, - .has_remote = 1, - }, - .gpio = { - .tuner_reset = TM6010_GPIO_2, - .tuner_on = TM6010_GPIO_3, - .demod_reset = TM6010_GPIO_1, - .demod_on = TM6010_GPIO_4, - .power_led = TM6010_GPIO_7, - .dvb_led = TM6010_GPIO_5, - .ir = TM6010_GPIO_0, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_SIF1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM5600_BOARD_10MOONS_UT821] = { - .name = "10Moons UT 821", - .tuner_type = TUNER_XC2028, - .eename = { '1', '0', 'M', 'O', 'O', 'N', 'S', '5', '6', '0', '0', 0xff, 0x45, 0x5b}, - .eename_size = 14, - .eename_pos = 0x14, - .type = TM5600, - .tuner_addr = 0xc2 >> 1, - .caps = { - .has_tuner = 1, - .has_eeprom = 1, - }, - .gpio = { - .tuner_reset = TM6000_GPIO_1, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM5600_BOARD_10MOONS_UT330] = { - .name = "10Moons UT 330", - .tuner_type = TUNER_PHILIPS_FQ1216AME_MK4, - .tuner_addr = 0xc8 >> 1, - .caps = { - .has_tuner = 1, - .has_dvb = 0, - .has_zl10353 = 0, - .has_eeprom = 1, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6000_BOARD_ADSTECH_DUAL_TV] = { - .name = "ADSTECH Dual TV USB", - .tuner_type = TUNER_XC2028, - .tuner_addr = 0xc8 >> 1, - .caps = { - .has_tuner = 1, - .has_tda9874 = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 1, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6000_BOARD_FREECOM_AND_SIMILAR] = { - .name = "Freecom Hybrid Stick / Moka DVB-T Receiver Dual", - .tuner_type = TUNER_XC2028, /* has a XC3028 */ - .tuner_addr = 0xc2 >> 1, - .demod_addr = 0x1e >> 1, - .caps = { - .has_tuner = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 0, - .has_remote = 1, - }, - .gpio = { - .tuner_reset = TM6000_GPIO_4, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6000_BOARD_ADSTECH_MINI_DUAL_TV] = { - .name = "ADSTECH Mini Dual TV USB", - .tuner_type = TUNER_XC2028, /* has a XC3028 */ - .tuner_addr = 0xc8 >> 1, - .demod_addr = 0x1e >> 1, - .caps = { - .has_tuner = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 0, - }, - .gpio = { - .tuner_reset = TM6000_GPIO_4, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6010_BOARD_HAUPPAUGE_900H] = { - .name = "Hauppauge WinTV HVR-900H / WinTV USB2-Stick", - .eename = { 'H', 0, 'V', 0, 'R', 0, '9', 0, '0', 0, '0', 0, 'H', 0 }, - .eename_size = 14, - .eename_pos = 0x42, - .tuner_type = TUNER_XC2028, /* has a XC3028 */ - .tuner_addr = 0xc2 >> 1, - .demod_addr = 0x1e >> 1, - .type = TM6010, - .ir_codes = RC_MAP_HAUPPAUGE, - .caps = { - .has_tuner = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 1, - .has_remote = 1, - }, - .gpio = { - .tuner_reset = TM6010_GPIO_2, - .tuner_on = TM6010_GPIO_3, - .demod_reset = TM6010_GPIO_1, - .demod_on = TM6010_GPIO_4, - .power_led = TM6010_GPIO_7, - .dvb_led = TM6010_GPIO_5, - .ir = TM6010_GPIO_0, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_SIF1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6010_BOARD_BEHOLD_WANDER] = { - .name = "Beholder Wander DVB-T/TV/FM USB2.0", - .tuner_type = TUNER_XC5000, - .tuner_addr = 0xc2 >> 1, - .demod_addr = 0x1e >> 1, - .type = TM6010, - .caps = { - .has_tuner = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 1, - .has_remote = 1, - .has_radio = 1, - }, - .gpio = { - .tuner_reset = TM6010_GPIO_0, - .demod_reset = TM6010_GPIO_1, - .power_led = TM6010_GPIO_6, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_SIF1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - .rinput = { - .type = TM6000_INPUT_RADIO, - .amux = TM6000_AMUX_ADC1, - }, - }, - [TM6010_BOARD_BEHOLD_VOYAGER] = { - .name = "Beholder Voyager TV/FM USB2.0", - .tuner_type = TUNER_XC5000, - .tuner_addr = 0xc2 >> 1, - .type = TM6010, - .caps = { - .has_tuner = 1, - .has_dvb = 0, - .has_zl10353 = 0, - .has_eeprom = 1, - .has_remote = 1, - .has_radio = 1, - }, - .gpio = { - .tuner_reset = TM6010_GPIO_0, - .power_led = TM6010_GPIO_6, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_SIF1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - .rinput = { - .type = TM6000_INPUT_RADIO, - .amux = TM6000_AMUX_ADC1, - }, - }, - [TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE] = { - .name = "Terratec Cinergy Hybrid XE / Cinergy Hybrid-Stick", - .tuner_type = TUNER_XC2028, /* has a XC3028 */ - .tuner_addr = 0xc2 >> 1, - .demod_addr = 0x1e >> 1, - .type = TM6010, - .caps = { - .has_tuner = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 1, - .has_remote = 1, - .has_radio = 1, - }, - .gpio = { - .tuner_reset = TM6010_GPIO_2, - .tuner_on = TM6010_GPIO_3, - .demod_reset = TM6010_GPIO_1, - .demod_on = TM6010_GPIO_4, - .power_led = TM6010_GPIO_7, - .dvb_led = TM6010_GPIO_5, - .ir = TM6010_GPIO_0, - }, - .ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_SIF1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - .rinput = { - .type = TM6000_INPUT_RADIO, - .amux = TM6000_AMUX_SIF1, - }, - }, - [TM5600_BOARD_TERRATEC_GRABSTER] = { - .name = "Terratec Grabster AV 150/250 MX", - .type = TM5600, - .tuner_type = TUNER_ABSENT, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_ADC1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6010_BOARD_TWINHAN_TU501] = { - .name = "Twinhan TU501(704D1)", - .tuner_type = TUNER_XC2028, /* has a XC3028 */ - .tuner_addr = 0xc2 >> 1, - .demod_addr = 0x1e >> 1, - .type = TM6010, - .caps = { - .has_tuner = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 1, - .has_remote = 1, - }, - .gpio = { - .tuner_reset = TM6010_GPIO_2, - .tuner_on = TM6010_GPIO_3, - .demod_reset = TM6010_GPIO_1, - .demod_on = TM6010_GPIO_4, - .power_led = TM6010_GPIO_7, - .dvb_led = TM6010_GPIO_5, - .ir = TM6010_GPIO_0, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_SIF1, - }, { - .type = TM6000_INPUT_COMPOSITE1, - .vmux = TM6000_VMUX_VIDEO_A, - .amux = TM6000_AMUX_ADC2, - }, { - .type = TM6000_INPUT_SVIDEO, - .vmux = TM6000_VMUX_VIDEO_AB, - .amux = TM6000_AMUX_ADC2, - }, - }, - }, - [TM6010_BOARD_BEHOLD_WANDER_LITE] = { - .name = "Beholder Wander Lite DVB-T/TV/FM USB2.0", - .tuner_type = TUNER_XC5000, - .tuner_addr = 0xc2 >> 1, - .demod_addr = 0x1e >> 1, - .type = TM6010, - .caps = { - .has_tuner = 1, - .has_dvb = 1, - .has_zl10353 = 1, - .has_eeprom = 1, - .has_remote = 0, - .has_radio = 1, - }, - .gpio = { - .tuner_reset = TM6010_GPIO_0, - .demod_reset = TM6010_GPIO_1, - .power_led = TM6010_GPIO_6, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_SIF1, - }, - }, - .rinput = { - .type = TM6000_INPUT_RADIO, - .amux = TM6000_AMUX_ADC1, - }, - }, - [TM6010_BOARD_BEHOLD_VOYAGER_LITE] = { - .name = "Beholder Voyager Lite TV/FM USB2.0", - .tuner_type = TUNER_XC5000, - .tuner_addr = 0xc2 >> 1, - .type = TM6010, - .caps = { - .has_tuner = 1, - .has_dvb = 0, - .has_zl10353 = 0, - .has_eeprom = 1, - .has_remote = 0, - .has_radio = 1, - }, - .gpio = { - .tuner_reset = TM6010_GPIO_0, - .power_led = TM6010_GPIO_6, - }, - .vinput = { { - .type = TM6000_INPUT_TV, - .vmux = TM6000_VMUX_VIDEO_B, - .amux = TM6000_AMUX_SIF1, - }, - }, - .rinput = { - .type = TM6000_INPUT_RADIO, - .amux = TM6000_AMUX_ADC1, - }, - }, -}; - -/* table of devices that work with this driver */ -static struct usb_device_id tm6000_id_table[] = { - { USB_DEVICE(0x6000, 0x0001), .driver_info = TM5600_BOARD_GENERIC }, - { USB_DEVICE(0x6000, 0x0002), .driver_info = TM6010_BOARD_GENERIC }, - { USB_DEVICE(0x06e1, 0xf332), .driver_info = TM6000_BOARD_ADSTECH_DUAL_TV }, - { USB_DEVICE(0x14aa, 0x0620), .driver_info = TM6000_BOARD_FREECOM_AND_SIMILAR }, - { USB_DEVICE(0x06e1, 0xb339), .driver_info = TM6000_BOARD_ADSTECH_MINI_DUAL_TV }, - { USB_DEVICE(0x2040, 0x6600), .driver_info = TM6010_BOARD_HAUPPAUGE_900H }, - { USB_DEVICE(0x2040, 0x6601), .driver_info = TM6010_BOARD_HAUPPAUGE_900H }, - { USB_DEVICE(0x2040, 0x6610), .driver_info = TM6010_BOARD_HAUPPAUGE_900H }, - { USB_DEVICE(0x2040, 0x6611), .driver_info = TM6010_BOARD_HAUPPAUGE_900H }, - { USB_DEVICE(0x6000, 0xdec0), .driver_info = TM6010_BOARD_BEHOLD_WANDER }, - { USB_DEVICE(0x6000, 0xdec1), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER }, - { USB_DEVICE(0x0ccd, 0x0086), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE }, - { USB_DEVICE(0x0ccd, 0x00A5), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE }, - { USB_DEVICE(0x0ccd, 0x0079), .driver_info = TM5600_BOARD_TERRATEC_GRABSTER }, - { USB_DEVICE(0x13d3, 0x3240), .driver_info = TM6010_BOARD_TWINHAN_TU501 }, - { USB_DEVICE(0x13d3, 0x3241), .driver_info = TM6010_BOARD_TWINHAN_TU501 }, - { USB_DEVICE(0x13d3, 0x3243), .driver_info = TM6010_BOARD_TWINHAN_TU501 }, - { USB_DEVICE(0x13d3, 0x3264), .driver_info = TM6010_BOARD_TWINHAN_TU501 }, - { USB_DEVICE(0x6000, 0xdec2), .driver_info = TM6010_BOARD_BEHOLD_WANDER_LITE }, - { USB_DEVICE(0x6000, 0xdec3), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER_LITE }, - { } -}; -MODULE_DEVICE_TABLE(usb, tm6000_id_table); - -/* Control power led for show some activity */ -void tm6000_flash_led(struct tm6000_core *dev, u8 state) -{ - /* Power LED unconfigured */ - if (!dev->gpio.power_led) - return; - - /* ON Power LED */ - if (state) { - switch (dev->model) { - case TM6010_BOARD_HAUPPAUGE_900H: - case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: - case TM6010_BOARD_TWINHAN_TU501: - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.power_led, 0x00); - break; - case TM6010_BOARD_BEHOLD_WANDER: - case TM6010_BOARD_BEHOLD_VOYAGER: - case TM6010_BOARD_BEHOLD_WANDER_LITE: - case TM6010_BOARD_BEHOLD_VOYAGER_LITE: - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.power_led, 0x01); - break; - } - } - /* OFF Power LED */ - else { - switch (dev->model) { - case TM6010_BOARD_HAUPPAUGE_900H: - case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: - case TM6010_BOARD_TWINHAN_TU501: - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.power_led, 0x01); - break; - case TM6010_BOARD_BEHOLD_WANDER: - case TM6010_BOARD_BEHOLD_VOYAGER: - case TM6010_BOARD_BEHOLD_WANDER_LITE: - case TM6010_BOARD_BEHOLD_VOYAGER_LITE: - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.power_led, 0x00); - break; - } - } -} - -/* Tuner callback to provide the proper gpio changes needed for xc5000 */ -int tm6000_xc5000_callback(void *ptr, int component, int command, int arg) -{ - int rc = 0; - struct tm6000_core *dev = ptr; - - if (dev->tuner_type != TUNER_XC5000) - return 0; - - switch (command) { - case XC5000_TUNER_RESET: - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x01); - msleep(15); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x00); - msleep(15); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x01); - break; - } - return rc; -} -EXPORT_SYMBOL_GPL(tm6000_xc5000_callback); - -/* Tuner callback to provide the proper gpio changes needed for xc2028 */ - -int tm6000_tuner_callback(void *ptr, int component, int command, int arg) -{ - int rc = 0; - struct tm6000_core *dev = ptr; - - if (dev->tuner_type != TUNER_XC2028) - return 0; - - switch (command) { - case XC2028_RESET_CLK: - tm6000_ir_wait(dev, 0); - - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, - 0x02, arg); - msleep(10); - rc = tm6000_i2c_reset(dev, 10); - break; - case XC2028_TUNER_RESET: - /* Reset codes during load firmware */ - switch (arg) { - case 0: - /* newer tuner can faster reset */ - switch (dev->model) { - case TM5600_BOARD_10MOONS_UT821: - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x01); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - 0x300, 0x01); - msleep(10); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x00); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - 0x300, 0x00); - msleep(10); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x01); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - 0x300, 0x01); - break; - case TM6010_BOARD_HAUPPAUGE_900H: - case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: - case TM6010_BOARD_TWINHAN_TU501: - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x01); - msleep(60); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x00); - msleep(75); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x01); - msleep(60); - break; - default: - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x00); - msleep(130); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x01); - msleep(130); - break; - } - - tm6000_ir_wait(dev, 1); - break; - case 1: - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, - 0x02, 0x01); - msleep(10); - break; - case 2: - rc = tm6000_i2c_reset(dev, 100); - break; - } - break; - case XC2028_I2C_FLUSH: - tm6000_set_reg(dev, REQ_50_SET_START, 0, 0); - tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0); - break; - } - return rc; -} -EXPORT_SYMBOL_GPL(tm6000_tuner_callback); - -int tm6000_cards_setup(struct tm6000_core *dev) -{ - /* - * Board-specific initialization sequence. Handles all GPIO - * initialization sequences that are board-specific. - * Up to now, all found devices use GPIO1 and GPIO4 at the same way. - * Probably, they're all based on some reference device. Due to that, - * there's a common routine at the end to handle those GPIO's. Devices - * that use different pinups or init sequences can just return at - * the board-specific session. - */ - switch (dev->model) { - case TM6010_BOARD_HAUPPAUGE_900H: - case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: - case TM6010_BOARD_TWINHAN_TU501: - case TM6010_BOARD_GENERIC: - /* Turn xceive 3028 on */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.tuner_on, 0x01); - msleep(15); - /* Turn zarlink zl10353 on */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x00); - msleep(15); - /* Reset zarlink zl10353 */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x00); - msleep(50); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x01); - msleep(15); - /* Turn zarlink zl10353 off */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x01); - msleep(15); - /* ir ? */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.ir, 0x01); - msleep(15); - /* Power led on (blue) */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x00); - msleep(15); - /* DVB led off (orange) */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.dvb_led, 0x01); - msleep(15); - /* Turn zarlink zl10353 on */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x00); - msleep(15); - break; - case TM6010_BOARD_BEHOLD_WANDER: - case TM6010_BOARD_BEHOLD_WANDER_LITE: - /* Power led on (blue) */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x01); - msleep(15); - /* Reset zarlink zl10353 */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x00); - msleep(50); - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x01); - msleep(15); - break; - case TM6010_BOARD_BEHOLD_VOYAGER: - case TM6010_BOARD_BEHOLD_VOYAGER_LITE: - /* Power led on (blue) */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x01); - msleep(15); - break; - default: - break; - } - - /* - * Default initialization. Most of the devices seem to use GPIO1 - * and GPIO4.on the same way, so, this handles the common sequence - * used by most devices. - * If a device uses a different sequence or different GPIO pins for - * reset, just add the code at the board-specific part - */ - - if (dev->gpio.tuner_reset) { - int rc; - int i; - - for (i = 0; i < 2; i++) { - rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x00); - if (rc < 0) { - printk(KERN_ERR "Error %i doing tuner reset\n", rc); - return rc; - } - - msleep(10); /* Just to be conservative */ - rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.tuner_reset, 0x01); - if (rc < 0) { - printk(KERN_ERR "Error %i doing tuner reset\n", rc); - return rc; - } - } - } else { - printk(KERN_ERR "Tuner reset is not configured\n"); - return -1; - } - - msleep(50); - - return 0; -}; - -static void tm6000_config_tuner(struct tm6000_core *dev) -{ - struct tuner_setup tun_setup; - - /* Load tuner module */ - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tuner", dev->tuner_addr, NULL); - - memset(&tun_setup, 0, sizeof(tun_setup)); - tun_setup.type = dev->tuner_type; - tun_setup.addr = dev->tuner_addr; - - tun_setup.mode_mask = 0; - if (dev->caps.has_tuner) - tun_setup.mode_mask |= (T_ANALOG_TV | T_RADIO); - - switch (dev->tuner_type) { - case TUNER_XC2028: - tun_setup.tuner_callback = tm6000_tuner_callback; - break; - case TUNER_XC5000: - tun_setup.tuner_callback = tm6000_xc5000_callback; - break; - } - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup); - - switch (dev->tuner_type) { - case TUNER_XC2028: { - struct v4l2_priv_tun_config xc2028_cfg; - struct xc2028_ctrl ctl; - - memset(&xc2028_cfg, 0, sizeof(xc2028_cfg)); - memset(&ctl, 0, sizeof(ctl)); - - ctl.demod = XC3028_FE_ZARLINK456; - - xc2028_cfg.tuner = TUNER_XC2028; - xc2028_cfg.priv = &ctl; - - switch (dev->model) { - case TM6010_BOARD_HAUPPAUGE_900H: - case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: - case TM6010_BOARD_TWINHAN_TU501: - ctl.max_len = 80; - ctl.fname = "xc3028L-v36.fw"; - break; - default: - if (dev->dev_type == TM6010) - ctl.fname = "xc3028-v27.fw"; - else - ctl.fname = "xc3028-v24.fw"; - } - - printk(KERN_INFO "Setting firmware parameters for xc2028\n"); - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, - &xc2028_cfg); - - } - break; - case TUNER_XC5000: - { - struct v4l2_priv_tun_config xc5000_cfg; - struct xc5000_config ctl = { - .i2c_address = dev->tuner_addr, - .if_khz = 4570, - .radio_input = XC5000_RADIO_FM1_MONO, - }; - - xc5000_cfg.tuner = TUNER_XC5000; - xc5000_cfg.priv = &ctl; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, - &xc5000_cfg); - } - break; - default: - printk(KERN_INFO "Unknown tuner type. Tuner is not configured.\n"); - break; - } -} - -static int fill_board_specific_data(struct tm6000_core *dev) -{ - int rc; - - dev->dev_type = tm6000_boards[dev->model].type; - dev->tuner_type = tm6000_boards[dev->model].tuner_type; - dev->tuner_addr = tm6000_boards[dev->model].tuner_addr; - - dev->gpio = tm6000_boards[dev->model].gpio; - - dev->ir_codes = tm6000_boards[dev->model].ir_codes; - - dev->demod_addr = tm6000_boards[dev->model].demod_addr; - - dev->caps = tm6000_boards[dev->model].caps; - - dev->vinput[0] = tm6000_boards[dev->model].vinput[0]; - dev->vinput[1] = tm6000_boards[dev->model].vinput[1]; - dev->vinput[2] = tm6000_boards[dev->model].vinput[2]; - dev->rinput = tm6000_boards[dev->model].rinput; - - /* setup per-model quirks */ - switch (dev->model) { - case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: - case TM6010_BOARD_HAUPPAUGE_900H: - dev->quirks |= TM6000_QUIRK_NO_USB_DELAY; - break; - - default: - break; - } - - /* initialize hardware */ - rc = tm6000_init(dev); - if (rc < 0) - return rc; - - return v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev); -} - - -static void use_alternative_detection_method(struct tm6000_core *dev) -{ - int i, model = -1; - - if (!dev->eedata_size) - return; - - for (i = 0; i < ARRAY_SIZE(tm6000_boards); i++) { - if (!tm6000_boards[i].eename_size) - continue; - if (dev->eedata_size < tm6000_boards[i].eename_pos + - tm6000_boards[i].eename_size) - continue; - - if (!memcmp(&dev->eedata[tm6000_boards[i].eename_pos], - tm6000_boards[i].eename, - tm6000_boards[i].eename_size)) { - model = i; - break; - } - } - if (model < 0) { - printk(KERN_INFO "Device has eeprom but is currently unknown\n"); - return; - } - - dev->model = model; - - printk(KERN_INFO "Device identified via eeprom as %s (type = %d)\n", - tm6000_boards[model].name, model); -} - -#if defined(CONFIG_MODULES) && defined(MODULE) -static void request_module_async(struct work_struct *work) -{ - struct tm6000_core *dev = container_of(work, struct tm6000_core, - request_module_wk); - - request_module("tm6000-alsa"); - - if (dev->caps.has_dvb) - request_module("tm6000-dvb"); -} - -static void request_modules(struct tm6000_core *dev) -{ - INIT_WORK(&dev->request_module_wk, request_module_async); - schedule_work(&dev->request_module_wk); -} - -static void flush_request_modules(struct tm6000_core *dev) -{ - flush_work_sync(&dev->request_module_wk); -} -#else -#define request_modules(dev) -#define flush_request_modules(dev) -#endif /* CONFIG_MODULES */ - -static int tm6000_init_dev(struct tm6000_core *dev) -{ - struct v4l2_frequency f; - int rc = 0; - - mutex_init(&dev->lock); - mutex_lock(&dev->lock); - - if (!is_generic(dev->model)) { - rc = fill_board_specific_data(dev); - if (rc < 0) - goto err; - - /* register i2c bus */ - rc = tm6000_i2c_register(dev); - if (rc < 0) - goto err; - } else { - /* register i2c bus */ - rc = tm6000_i2c_register(dev); - if (rc < 0) - goto err; - - use_alternative_detection_method(dev); - - rc = fill_board_specific_data(dev); - if (rc < 0) - goto err; - } - - /* Default values for STD and resolutions */ - dev->width = 720; - dev->height = 480; - dev->norm = V4L2_STD_PAL_M; - - /* Configure tuner */ - tm6000_config_tuner(dev); - - /* Set video standard */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); - - /* Set tuner frequency - also loads firmware on xc2028/xc3028 */ - f.tuner = 0; - f.type = V4L2_TUNER_ANALOG_TV; - f.frequency = 3092; /* 193.25 MHz */ - dev->freq = f.frequency; - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); - - if (dev->caps.has_tda9874) - v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tvaudio", I2C_ADDR_TDA9874, NULL); - - /* register and initialize V4L2 */ - rc = tm6000_v4l2_register(dev); - if (rc < 0) - goto err; - - tm6000_add_into_devlist(dev); - tm6000_init_extension(dev); - - tm6000_ir_init(dev); - - request_modules(dev); - - mutex_unlock(&dev->lock); - return 0; - -err: - mutex_unlock(&dev->lock); - return rc; -} - -/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */ -#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) - -static void get_max_endpoint(struct usb_device *udev, - struct usb_host_interface *alt, - char *msgtype, - struct usb_host_endpoint *curr_e, - struct tm6000_endpoint *tm_ep) -{ - u16 tmp = le16_to_cpu(curr_e->desc.wMaxPacketSize); - unsigned int size = tmp & 0x7ff; - - if (udev->speed == USB_SPEED_HIGH) - size = size * hb_mult(tmp); - - if (size > tm_ep->maxsize) { - tm_ep->endp = curr_e; - tm_ep->maxsize = size; - tm_ep->bInterfaceNumber = alt->desc.bInterfaceNumber; - tm_ep->bAlternateSetting = alt->desc.bAlternateSetting; - - printk(KERN_INFO "tm6000: %s endpoint: 0x%02x (max size=%u bytes)\n", - msgtype, curr_e->desc.bEndpointAddress, - size); - } -} - -/* - * tm6000_usb_probe() - * checks for supported devices - */ -static int tm6000_usb_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_device *usbdev; - struct tm6000_core *dev = NULL; - int i, rc = 0; - int nr = 0; - char *speed; - - usbdev = usb_get_dev(interface_to_usbdev(interface)); - - /* Selects the proper interface */ - rc = usb_set_interface(usbdev, 0, 1); - if (rc < 0) - goto err; - - /* Check to see next free device and mark as used */ - nr = find_first_zero_bit(&tm6000_devused, TM6000_MAXBOARDS); - if (nr >= TM6000_MAXBOARDS) { - printk(KERN_ERR "tm6000: Supports only %i tm60xx boards.\n", TM6000_MAXBOARDS); - usb_put_dev(usbdev); - return -ENOMEM; - } - - /* Create and initialize dev struct */ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - printk(KERN_ERR "tm6000" ": out of memory!\n"); - usb_put_dev(usbdev); - return -ENOMEM; - } - spin_lock_init(&dev->slock); - mutex_init(&dev->usb_lock); - - /* Increment usage count */ - set_bit(nr, &tm6000_devused); - snprintf(dev->name, 29, "tm6000 #%d", nr); - - dev->model = id->driver_info; - if (card[nr] < ARRAY_SIZE(tm6000_boards)) - dev->model = card[nr]; - - dev->udev = usbdev; - dev->devno = nr; - - switch (usbdev->speed) { - case USB_SPEED_LOW: - speed = "1.5"; - break; - case USB_SPEED_UNKNOWN: - case USB_SPEED_FULL: - speed = "12"; - break; - case USB_SPEED_HIGH: - speed = "480"; - break; - default: - speed = "unknown"; - } - - /* Get endpoints */ - for (i = 0; i < interface->num_altsetting; i++) { - int ep; - - for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) { - struct usb_host_endpoint *e; - int dir_out; - - e = &interface->altsetting[i].endpoint[ep]; - - dir_out = ((e->desc.bEndpointAddress & - USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); - - printk(KERN_INFO "tm6000: alt %d, interface %i, class %i\n", - i, - interface->altsetting[i].desc.bInterfaceNumber, - interface->altsetting[i].desc.bInterfaceClass); - - switch (e->desc.bmAttributes) { - case USB_ENDPOINT_XFER_BULK: - if (!dir_out) { - get_max_endpoint(usbdev, - &interface->altsetting[i], - "Bulk IN", e, - &dev->bulk_in); - } else { - get_max_endpoint(usbdev, - &interface->altsetting[i], - "Bulk OUT", e, - &dev->bulk_out); - } - break; - case USB_ENDPOINT_XFER_ISOC: - if (!dir_out) { - get_max_endpoint(usbdev, - &interface->altsetting[i], - "ISOC IN", e, - &dev->isoc_in); - } else { - get_max_endpoint(usbdev, - &interface->altsetting[i], - "ISOC OUT", e, - &dev->isoc_out); - } - break; - case USB_ENDPOINT_XFER_INT: - if (!dir_out) { - get_max_endpoint(usbdev, - &interface->altsetting[i], - "INT IN", e, - &dev->int_in); - } else { - get_max_endpoint(usbdev, - &interface->altsetting[i], - "INT OUT", e, - &dev->int_out); - } - break; - } - } - } - - - printk(KERN_INFO "tm6000: New video device @ %s Mbps (%04x:%04x, ifnum %d)\n", - speed, - le16_to_cpu(dev->udev->descriptor.idVendor), - le16_to_cpu(dev->udev->descriptor.idProduct), - interface->altsetting->desc.bInterfaceNumber); - -/* check if the the device has the iso in endpoint at the correct place */ - if (!dev->isoc_in.endp) { - printk(KERN_ERR "tm6000: probing error: no IN ISOC endpoint!\n"); - rc = -ENODEV; - - goto err; - } - - /* save our data pointer in this interface device */ - usb_set_intfdata(interface, dev); - - printk(KERN_INFO "tm6000: Found %s\n", tm6000_boards[dev->model].name); - - rc = tm6000_init_dev(dev); - if (rc < 0) - goto err; - - return 0; - -err: - printk(KERN_ERR "tm6000: Error %d while registering\n", rc); - - clear_bit(nr, &tm6000_devused); - usb_put_dev(usbdev); - - kfree(dev); - return rc; -} - -/* - * tm6000_usb_disconnect() - * called when the device gets diconencted - * video device will be unregistered on v4l2_close in case it is still open - */ -static void tm6000_usb_disconnect(struct usb_interface *interface) -{ - struct tm6000_core *dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - if (!dev) - return; - - printk(KERN_INFO "tm6000: disconnecting %s\n", dev->name); - - flush_request_modules(dev); - - tm6000_ir_fini(dev); - - if (dev->gpio.power_led) { - switch (dev->model) { - case TM6010_BOARD_HAUPPAUGE_900H: - case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: - case TM6010_BOARD_TWINHAN_TU501: - /* Power led off */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.power_led, 0x01); - msleep(15); - break; - case TM6010_BOARD_BEHOLD_WANDER: - case TM6010_BOARD_BEHOLD_VOYAGER: - case TM6010_BOARD_BEHOLD_WANDER_LITE: - case TM6010_BOARD_BEHOLD_VOYAGER_LITE: - /* Power led off */ - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.power_led, 0x00); - msleep(15); - break; - } - } - tm6000_v4l2_unregister(dev); - - tm6000_i2c_unregister(dev); - - v4l2_device_unregister(&dev->v4l2_dev); - - dev->state |= DEV_DISCONNECTED; - - usb_put_dev(dev->udev); - - tm6000_close_extension(dev); - tm6000_remove_from_devlist(dev); - - clear_bit(dev->devno, &tm6000_devused); - kfree(dev); -} - -static struct usb_driver tm6000_usb_driver = { - .name = "tm6000", - .probe = tm6000_usb_probe, - .disconnect = tm6000_usb_disconnect, - .id_table = tm6000_id_table, -}; - -module_usb_driver(tm6000_usb_driver); - -MODULE_DESCRIPTION("Trident TVMaster TM5600/TM6000/TM6010 USB2 adapter"); -MODULE_AUTHOR("Mauro Carvalho Chehab"); -MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/tm6000/tm6000-core.c b/drivers/media/video/tm6000/tm6000-core.c deleted file mode 100644 index 22cc0116deb6..000000000000 --- a/drivers/media/video/tm6000/tm6000-core.c +++ /dev/null @@ -1,935 +0,0 @@ -/* - * tm6000-core.c - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> - * - * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com> - * - DVB-T support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/i2c.h> -#include "tm6000.h" -#include "tm6000-regs.h" -#include <media/v4l2-common.h> -#include <media/tuner.h> - -#define USB_TIMEOUT (5 * HZ) /* ms */ - -int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req, - u16 value, u16 index, u8 *buf, u16 len) -{ - int ret, i; - unsigned int pipe; - u8 *data = NULL; - int delay = 5000; - - mutex_lock(&dev->usb_lock); - - if (len) - data = kzalloc(len, GFP_KERNEL); - - if (req_type & USB_DIR_IN) - pipe = usb_rcvctrlpipe(dev->udev, 0); - else { - pipe = usb_sndctrlpipe(dev->udev, 0); - memcpy(data, buf, len); - } - - if (tm6000_debug & V4L2_DEBUG_I2C) { - printk(KERN_DEBUG "(dev %p, pipe %08x): ", dev->udev, pipe); - - printk(KERN_CONT "%s: %02x %02x %02x %02x %02x %02x %02x %02x ", - (req_type & USB_DIR_IN) ? " IN" : "OUT", - req_type, req, value&0xff, value>>8, index&0xff, - index>>8, len&0xff, len>>8); - - if (!(req_type & USB_DIR_IN)) { - printk(KERN_CONT ">>> "); - for (i = 0; i < len; i++) - printk(KERN_CONT " %02x", buf[i]); - printk(KERN_CONT "\n"); - } - } - - ret = usb_control_msg(dev->udev, pipe, req, req_type, value, index, - data, len, USB_TIMEOUT); - - if (req_type & USB_DIR_IN) - memcpy(buf, data, len); - - if (tm6000_debug & V4L2_DEBUG_I2C) { - if (ret < 0) { - if (req_type & USB_DIR_IN) - printk(KERN_DEBUG "<<< (len=%d)\n", len); - - printk(KERN_CONT "%s: Error #%d\n", __func__, ret); - } else if (req_type & USB_DIR_IN) { - printk(KERN_CONT "<<< "); - for (i = 0; i < len; i++) - printk(KERN_CONT " %02x", buf[i]); - printk(KERN_CONT "\n"); - } - } - - kfree(data); - - if (dev->quirks & TM6000_QUIRK_NO_USB_DELAY) - delay = 0; - - if (req == REQ_16_SET_GET_I2C_WR1_RDN && !(req_type & USB_DIR_IN)) { - unsigned int tsleep; - /* Calculate delay time, 14000us for 64 bytes */ - tsleep = (len * 200) + 200; - if (tsleep < delay) - tsleep = delay; - usleep_range(tsleep, tsleep + 1000); - } - else if (delay) - usleep_range(delay, delay + 1000); - - mutex_unlock(&dev->usb_lock); - return ret; -} - -int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index) -{ - return - tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR, - req, value, index, NULL, 0); -} -EXPORT_SYMBOL_GPL(tm6000_set_reg); - -int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index) -{ - int rc; - u8 buf[1]; - - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req, - value, index, buf, 1); - - if (rc < 0) - return rc; - - return *buf; -} -EXPORT_SYMBOL_GPL(tm6000_get_reg); - -int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value, - u16 index, u16 mask) -{ - int rc; - u8 buf[1]; - u8 new_index; - - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req, - value, 0, buf, 1); - - if (rc < 0) - return rc; - - new_index = (buf[0] & ~mask) | (index & mask); - - if (new_index == buf[0]) - return 0; - - return tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR, - req, value, new_index, NULL, 0); -} -EXPORT_SYMBOL_GPL(tm6000_set_reg_mask); - -int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index) -{ - int rc; - u8 buf[2]; - - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req, - value, index, buf, 2); - - if (rc < 0) - return rc; - - return buf[1]|buf[0]<<8; -} - -int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index) -{ - int rc; - u8 buf[4]; - - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req, - value, index, buf, 4); - - if (rc < 0) - return rc; - - return buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24; -} - -int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep) -{ - int rc; - - rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0); - if (rc < 0) - return rc; - - msleep(tsleep); - - rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1); - msleep(tsleep); - - return rc; -} - -void tm6000_set_fourcc_format(struct tm6000_core *dev) -{ - if (dev->dev_type == TM6010) { - int val; - - val = tm6000_get_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, 0) & 0xfc; - if (dev->fourcc == V4L2_PIX_FMT_UYVY) - tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val); - else - tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val | 1); - } else { - if (dev->fourcc == V4L2_PIX_FMT_UYVY) - tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0); - else - tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0x90); - } -} - -static void tm6000_set_vbi(struct tm6000_core *dev) -{ - /* - * FIXME: - * VBI lines and start/end are different between 60Hz and 50Hz - * So, it is very likely that we need to change the config to - * something that takes it into account, doing something different - * if (dev->norm & V4L2_STD_525_60) - */ - - if (dev->dev_type == TM6010) { - tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01); - tm6000_set_reg(dev, TM6010_REQ07_R41_TELETEXT_VBI_CODE1, 0x27); - tm6000_set_reg(dev, TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55); - tm6000_set_reg(dev, TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7, 0x66); - tm6000_set_reg(dev, TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8, 0x66); - tm6000_set_reg(dev, TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22, 0x66); - tm6000_set_reg(dev, - TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23, 0x00); - tm6000_set_reg(dev, - TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES, 0x00); - tm6000_set_reg(dev, - TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01); - tm6000_set_reg(dev, - TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN, 0x00); - tm6000_set_reg(dev, - TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02); - tm6000_set_reg(dev, TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35); - tm6000_set_reg(dev, TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0); - tm6000_set_reg(dev, TM6010_REQ07_R5A_VBI_TELETEXT_DTO1, 0x11); - tm6000_set_reg(dev, TM6010_REQ07_R5B_VBI_TELETEXT_DTO0, 0x4c); - tm6000_set_reg(dev, TM6010_REQ07_R40_TELETEXT_VBI_CODE0, 0x01); - tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00); - } -} - -int tm6000_init_analog_mode(struct tm6000_core *dev) -{ - struct v4l2_frequency f; - - if (dev->dev_type == TM6010) { - u8 active = TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE; - - if (!dev->radio) - active |= TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE; - - /* Enable video and audio */ - tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF, - active, 0x60); - /* Disable TS input */ - tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, - 0x00, 0x40); - } else { - /* Enables soft reset */ - tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01); - - if (dev->scaler) - /* Disable Hfilter and Enable TS Drop err */ - tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x20); - else /* Enable Hfilter and disable TS Drop err */ - tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x80); - - tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x88); - tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x23); - tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xc0); - tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xd8); - tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x06); - tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f); - - /* AP Software reset */ - tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08); - tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00); - - tm6000_set_fourcc_format(dev); - - /* Disables soft reset */ - tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00); - } - msleep(20); - - /* Tuner firmware can now be loaded */ - - /* - * FIXME: This is a hack! xc3028 "sleeps" when no channel is detected - * for more than a few seconds. Not sure why, as this behavior does - * not happen on other devices with xc3028. So, I suspect that it - * is yet another bug at tm6000. After start sleeping, decoding - * doesn't start automatically. Instead, it requires some - * I2C commands to wake it up. As we want to have image at the - * beginning, we needed to add this hack. The better would be to - * discover some way to make tm6000 to wake up without this hack. - */ - f.frequency = dev->freq; - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); - - msleep(100); - tm6000_set_standard(dev); - tm6000_set_vbi(dev); - tm6000_set_audio_bitrate(dev, 48000); - - /* switch dvb led off */ - if (dev->gpio.dvb_led) { - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.dvb_led, 0x01); - } - - return 0; -} - -int tm6000_init_digital_mode(struct tm6000_core *dev) -{ - if (dev->dev_type == TM6010) { - /* Disable video and audio */ - tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF, - 0x00, 0x60); - /* Enable TS input */ - tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, - 0x40, 0x40); - /* all power down, but not the digital data port */ - tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0x28); - tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xfc); - tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0xff); - } else { - tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08); - tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00); - tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01); - tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x08); - tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c); - tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff); - tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0xd8); - tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x40); - tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0); - tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x09); - tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x37); - tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xd8); - tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xc0); - tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x60); - - tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c); - tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff); - tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0x08); - msleep(50); - - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00); - msleep(50); - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x01); - msleep(50); - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00); - msleep(100); - } - - /* switch dvb led on */ - if (dev->gpio.dvb_led) { - tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - dev->gpio.dvb_led, 0x00); - } - - return 0; -} -EXPORT_SYMBOL(tm6000_init_digital_mode); - -struct reg_init { - u8 req; - u8 reg; - u8 val; -}; - -/* The meaning of those initializations are unknown */ -static struct reg_init tm6000_init_tab[] = { - /* REG VALUE */ - { TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f }, - { TM6010_REQ07_RFF_SOFT_RESET, 0x08 }, - { TM6010_REQ07_RFF_SOFT_RESET, 0x00 }, - { TM6010_REQ07_RD5_POWERSAVE, 0x4f }, - { TM6000_REQ07_RDA_CLK_SEL, 0x23 }, - { TM6000_REQ07_RDB_OUT_SEL, 0x08 }, - { TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x00 }, - { TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10 }, - { TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00 }, - { TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00 }, - { TM6000_REQ07_REB_VADC_AADC_MODE, 0x64 }, /* 48000 bits/sample, external input */ - { TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL, 0xc2 }, - - { TM6010_REQ07_R3F_RESET, 0x01 }, /* Start of soft reset */ - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 }, - { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 }, - { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 }, - { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 }, - { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 }, - { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a }, - { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 }, - { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 }, - { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b }, - { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 }, - { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f }, - { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c }, - { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c }, - { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 }, - { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c }, - { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a }, - { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 }, - { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 }, - { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a }, - { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 }, - { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 }, - { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 }, - { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 }, - { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 }, - { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 }, - { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 }, - { TM6010_REQ07_RC1_TRESHOLD, 0xd0 }, - { TM6010_REQ07_RC3_HSTART1, 0x88 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, /* End of the soft reset */ - { TM6010_REQ05_R18_IMASK7, 0x00 }, -}; - -static struct reg_init tm6010_init_tab[] = { - { TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x00 }, - { TM6010_REQ07_RC4_HSTART0, 0xa0 }, - { TM6010_REQ07_RC6_HEND0, 0x40 }, - { TM6010_REQ07_RCA_VEND0, 0x31 }, - { TM6010_REQ07_RCC_ACTIVE_IF, 0xe1 }, - { TM6010_REQ07_RE0_DVIDEO_SOURCE, 0x03 }, - { TM6010_REQ07_RFE_POWER_DOWN, 0x7f }, - - { TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0 }, - { TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4 }, - { TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8 }, - { TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x00 }, - { TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2 }, - { TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0 }, - { TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2 }, - { TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x60 }, - { TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc }, - - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 }, - { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 }, - { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 }, - { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 }, - { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 }, - { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a }, - { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 }, - { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 }, - { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b }, - { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 }, - { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f }, - { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c }, - { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c }, - { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 }, - { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c }, - { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a }, - { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 }, - { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 }, - { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a }, - { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 }, - { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 }, - { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 }, - { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 }, - { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 }, - { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 }, - { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 }, - { TM6010_REQ07_RC1_TRESHOLD, 0xd0 }, - { TM6010_REQ07_RC3_HSTART1, 0x88 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - - { TM6010_REQ05_R18_IMASK7, 0x00 }, - - { TM6010_REQ07_RDC_IR_LEADER1, 0xaa }, - { TM6010_REQ07_RDD_IR_LEADER0, 0x30 }, - { TM6010_REQ07_RDE_IR_PULSE_CNT1, 0x20 }, - { TM6010_REQ07_RDF_IR_PULSE_CNT0, 0xd0 }, - { REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 }, - { TM6010_REQ07_RD8_IR, 0x0f }, - - /* set remote wakeup key:any key wakeup */ - { TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe }, - { TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff }, -}; - -int tm6000_init(struct tm6000_core *dev) -{ - int board, rc = 0, i, size; - struct reg_init *tab; - - /* Check board revision */ - board = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0); - if (board >= 0) { - switch (board & 0xff) { - case 0xf3: - printk(KERN_INFO "Found tm6000\n"); - if (dev->dev_type != TM6000) - dev->dev_type = TM6000; - break; - case 0xf4: - printk(KERN_INFO "Found tm6010\n"); - if (dev->dev_type != TM6010) - dev->dev_type = TM6010; - break; - default: - printk(KERN_INFO "Unknown board version = 0x%08x\n", board); - } - } else - printk(KERN_ERR "Error %i while retrieving board version\n", board); - - if (dev->dev_type == TM6010) { - tab = tm6010_init_tab; - size = ARRAY_SIZE(tm6010_init_tab); - } else { - tab = tm6000_init_tab; - size = ARRAY_SIZE(tm6000_init_tab); - } - - /* Load board's initialization table */ - for (i = 0; i < size; i++) { - rc = tm6000_set_reg(dev, tab[i].req, tab[i].reg, tab[i].val); - if (rc < 0) { - printk(KERN_ERR "Error %i while setting req %d, " - "reg %d to value %d\n", rc, - tab[i].req, tab[i].reg, tab[i].val); - return rc; - } - } - - msleep(5); /* Just to be conservative */ - - rc = tm6000_cards_setup(dev); - - return rc; -} - - -int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate) -{ - int val = 0; - u8 areg_f0 = 0x60; /* ADC MCLK = 250 Fs */ - u8 areg_0a = 0x91; /* SIF 48KHz */ - - switch (bitrate) { - case 48000: - areg_f0 = 0x60; /* ADC MCLK = 250 Fs */ - areg_0a = 0x91; /* SIF 48KHz */ - dev->audio_bitrate = bitrate; - break; - case 32000: - areg_f0 = 0x00; /* ADC MCLK = 375 Fs */ - areg_0a = 0x90; /* SIF 32KHz */ - dev->audio_bitrate = bitrate; - break; - default: - return -EINVAL; - } - - - /* enable I2S, if we use sif or external I2S device */ - if (dev->dev_type == TM6010) { - val = tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, areg_0a); - if (val < 0) - return val; - - val = tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, - areg_f0, 0xf0); - if (val < 0) - return val; - } else { - val = tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE, - areg_f0, 0xf0); - if (val < 0) - return val; - } - return 0; -} -EXPORT_SYMBOL_GPL(tm6000_set_audio_bitrate); - -int tm6000_set_audio_rinput(struct tm6000_core *dev) -{ - if (dev->dev_type == TM6010) { - /* Audio crossbar setting, default SIF1 */ - u8 areg_f0; - u8 areg_07 = 0x10; - - switch (dev->rinput.amux) { - case TM6000_AMUX_SIF1: - case TM6000_AMUX_SIF2: - areg_f0 = 0x03; - areg_07 = 0x30; - break; - case TM6000_AMUX_ADC1: - areg_f0 = 0x00; - break; - case TM6000_AMUX_ADC2: - areg_f0 = 0x08; - break; - case TM6000_AMUX_I2S: - areg_f0 = 0x04; - break; - default: - printk(KERN_INFO "%s: audio input dosn't support\n", - dev->name); - return 0; - break; - } - /* Set audio input crossbar */ - tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, - areg_f0, 0x0f); - /* Mux overflow workaround */ - tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL, - areg_07, 0xf0); - } else { - u8 areg_eb; - /* Audio setting, default LINE1 */ - switch (dev->rinput.amux) { - case TM6000_AMUX_ADC1: - areg_eb = 0x00; - break; - case TM6000_AMUX_ADC2: - areg_eb = 0x04; - break; - default: - printk(KERN_INFO "%s: audio input dosn't support\n", - dev->name); - return 0; - break; - } - /* Set audio input */ - tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE, - areg_eb, 0x0f); - } - return 0; -} - -static void tm6010_set_mute_sif(struct tm6000_core *dev, u8 mute) -{ - u8 mute_reg = 0; - - if (mute) - mute_reg = 0x08; - - tm6000_set_reg_mask(dev, TM6010_REQ08_R0A_A_I2S_MOD, mute_reg, 0x08); -} - -static void tm6010_set_mute_adc(struct tm6000_core *dev, u8 mute) -{ - u8 mute_reg = 0; - - if (mute) - mute_reg = 0x20; - - if (dev->dev_type == TM6010) { - tm6000_set_reg_mask(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL, - mute_reg, 0x20); - tm6000_set_reg_mask(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL, - mute_reg, 0x20); - } else { - tm6000_set_reg_mask(dev, TM6000_REQ07_REC_VADC_AADC_LVOL, - mute_reg, 0x20); - tm6000_set_reg_mask(dev, TM6000_REQ07_RED_VADC_AADC_RVOL, - mute_reg, 0x20); - } -} - -int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute) -{ - enum tm6000_mux mux; - - if (dev->radio) - mux = dev->rinput.amux; - else - mux = dev->vinput[dev->input].amux; - - switch (mux) { - case TM6000_AMUX_SIF1: - case TM6000_AMUX_SIF2: - if (dev->dev_type == TM6010) - tm6010_set_mute_sif(dev, mute); - else { - printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has" - " SIF audio inputs. Please check the %s" - " configuration.\n", dev->name); - return -EINVAL; - } - break; - case TM6000_AMUX_ADC1: - case TM6000_AMUX_ADC2: - tm6010_set_mute_adc(dev, mute); - break; - default: - return -EINVAL; - break; - } - return 0; -} - -static void tm6010_set_volume_sif(struct tm6000_core *dev, int vol) -{ - u8 vol_reg; - - vol_reg = vol & 0x0F; - - if (vol < 0) - vol_reg |= 0x40; - - tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, vol_reg); - tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, vol_reg); -} - -static void tm6010_set_volume_adc(struct tm6000_core *dev, int vol) -{ - u8 vol_reg; - - vol_reg = (vol + 0x10) & 0x1f; - - if (dev->dev_type == TM6010) { - tm6000_set_reg(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL, vol_reg); - tm6000_set_reg(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL, vol_reg); - } else { - tm6000_set_reg(dev, TM6000_REQ07_REC_VADC_AADC_LVOL, vol_reg); - tm6000_set_reg(dev, TM6000_REQ07_RED_VADC_AADC_RVOL, vol_reg); - } -} - -void tm6000_set_volume(struct tm6000_core *dev, int vol) -{ - enum tm6000_mux mux; - - if (dev->radio) { - mux = dev->rinput.amux; - vol += 8; /* Offset to 0 dB */ - } else - mux = dev->vinput[dev->input].amux; - - switch (mux) { - case TM6000_AMUX_SIF1: - case TM6000_AMUX_SIF2: - if (dev->dev_type == TM6010) - tm6010_set_volume_sif(dev, vol); - else - printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has" - " SIF audio inputs. Please check the %s" - " configuration.\n", dev->name); - break; - case TM6000_AMUX_ADC1: - case TM6000_AMUX_ADC2: - tm6010_set_volume_adc(dev, vol); - break; - default: - break; - } -} - -static LIST_HEAD(tm6000_devlist); -static DEFINE_MUTEX(tm6000_devlist_mutex); - -/* - * tm6000_realease_resource() - */ - -void tm6000_remove_from_devlist(struct tm6000_core *dev) -{ - mutex_lock(&tm6000_devlist_mutex); - list_del(&dev->devlist); - mutex_unlock(&tm6000_devlist_mutex); -}; - -void tm6000_add_into_devlist(struct tm6000_core *dev) -{ - mutex_lock(&tm6000_devlist_mutex); - list_add_tail(&dev->devlist, &tm6000_devlist); - mutex_unlock(&tm6000_devlist_mutex); -}; - -/* - * Extension interface - */ - -static LIST_HEAD(tm6000_extension_devlist); - -int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type, - char *buf, int size) -{ - struct tm6000_ops *ops = NULL; - - /* FIXME: tm6000_extension_devlist_lock should be a spinlock */ - - if (!list_empty(&tm6000_extension_devlist)) { - list_for_each_entry(ops, &tm6000_extension_devlist, next) { - if (ops->fillbuf && ops->type == type) - ops->fillbuf(dev, buf, size); - } - } - - return 0; -} - -int tm6000_register_extension(struct tm6000_ops *ops) -{ - struct tm6000_core *dev = NULL; - - mutex_lock(&tm6000_devlist_mutex); - list_add_tail(&ops->next, &tm6000_extension_devlist); - list_for_each_entry(dev, &tm6000_devlist, devlist) { - ops->init(dev); - printk(KERN_INFO "%s: Initialized (%s) extension\n", - dev->name, ops->name); - } - mutex_unlock(&tm6000_devlist_mutex); - return 0; -} -EXPORT_SYMBOL(tm6000_register_extension); - -void tm6000_unregister_extension(struct tm6000_ops *ops) -{ - struct tm6000_core *dev = NULL; - - mutex_lock(&tm6000_devlist_mutex); - list_for_each_entry(dev, &tm6000_devlist, devlist) - ops->fini(dev); - - printk(KERN_INFO "tm6000: Remove (%s) extension\n", ops->name); - list_del(&ops->next); - mutex_unlock(&tm6000_devlist_mutex); -} -EXPORT_SYMBOL(tm6000_unregister_extension); - -void tm6000_init_extension(struct tm6000_core *dev) -{ - struct tm6000_ops *ops = NULL; - - mutex_lock(&tm6000_devlist_mutex); - if (!list_empty(&tm6000_extension_devlist)) { - list_for_each_entry(ops, &tm6000_extension_devlist, next) { - if (ops->init) - ops->init(dev); - } - } - mutex_unlock(&tm6000_devlist_mutex); -} - -void tm6000_close_extension(struct tm6000_core *dev) -{ - struct tm6000_ops *ops = NULL; - - mutex_lock(&tm6000_devlist_mutex); - if (!list_empty(&tm6000_extension_devlist)) { - list_for_each_entry(ops, &tm6000_extension_devlist, next) { - if (ops->fini) - ops->fini(dev); - } - } - mutex_unlock(&tm6000_devlist_mutex); -} diff --git a/drivers/media/video/tm6000/tm6000-dvb.c b/drivers/media/video/tm6000/tm6000-dvb.c deleted file mode 100644 index e1f3f66e1e63..000000000000 --- a/drivers/media/video/tm6000/tm6000-dvb.c +++ /dev/null @@ -1,467 +0,0 @@ -/* - * tm6000-dvb.c - dvb-t support for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/usb.h> - -#include "tm6000.h" -#include "tm6000-regs.h" - -#include "zl10353.h" - -#include <media/tuner.h> - -#include "tuner-xc2028.h" -#include "xc5000.h" - -MODULE_DESCRIPTION("DVB driver extension module for tm5600/6000/6010 based TV cards"); -MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); -MODULE_LICENSE("GPL"); - -MODULE_SUPPORTED_DEVICE("{{Trident, tm5600}," - "{{Trident, tm6000}," - "{{Trident, tm6010}"); - -static int debug; - -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "enable debug message"); - -static inline void print_err_status(struct tm6000_core *dev, - int packet, int status) -{ - char *errmsg = "Unknown"; - - switch (status) { - case -ENOENT: - errmsg = "unlinked synchronuously"; - break; - case -ECONNRESET: - errmsg = "unlinked asynchronuously"; - break; - case -ENOSR: - errmsg = "Buffer error (overrun)"; - break; - case -EPIPE: - errmsg = "Stalled (device not responding)"; - break; - case -EOVERFLOW: - errmsg = "Babble (bad cable?)"; - break; - case -EPROTO: - errmsg = "Bit-stuff error (bad cable?)"; - break; - case -EILSEQ: - errmsg = "CRC/Timeout (could be anything)"; - break; - case -ETIME: - errmsg = "Device does not respond"; - break; - } - if (packet < 0) { - dprintk(dev, 1, "URB status %d [%s].\n", - status, errmsg); - } else { - dprintk(dev, 1, "URB packet %d, status %d [%s].\n", - packet, status, errmsg); - } -} - -static void tm6000_urb_received(struct urb *urb) -{ - int ret; - struct tm6000_core *dev = urb->context; - - switch (urb->status) { - case 0: - case -ETIMEDOUT: - break; - case -ENOENT: - case -ECONNRESET: - case -ESHUTDOWN: - return; - default: - print_err_status(dev, 0, urb->status); - } - - if (urb->actual_length > 0) - dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer, - urb->actual_length); - - if (dev->dvb->streams > 0) { - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret < 0) { - printk(KERN_ERR "tm6000: error %s\n", __func__); - kfree(urb->transfer_buffer); - usb_free_urb(urb); - } - } -} - -static int tm6000_start_stream(struct tm6000_core *dev) -{ - int ret; - unsigned int pipe, size; - struct tm6000_dvb *dvb = dev->dvb; - - printk(KERN_INFO "tm6000: got start stream request %s\n", __func__); - - if (dev->mode != TM6000_MODE_DIGITAL) { - tm6000_init_digital_mode(dev); - dev->mode = TM6000_MODE_DIGITAL; - } - - dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL); - if (dvb->bulk_urb == NULL) { - printk(KERN_ERR "tm6000: couldn't allocate urb\n"); - return -ENOMEM; - } - - pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress - & USB_ENDPOINT_NUMBER_MASK); - - size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); - size = size * 15; /* 512 x 8 or 12 or 15 */ - - dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); - if (dvb->bulk_urb->transfer_buffer == NULL) { - usb_free_urb(dvb->bulk_urb); - printk(KERN_ERR "tm6000: couldn't allocate transfer buffer!\n"); - return -ENOMEM; - } - - usb_fill_bulk_urb(dvb->bulk_urb, dev->udev, pipe, - dvb->bulk_urb->transfer_buffer, - size, - tm6000_urb_received, dev); - - ret = usb_clear_halt(dev->udev, pipe); - if (ret < 0) { - printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n", - ret, __func__); - return ret; - } else - printk(KERN_ERR "tm6000: pipe resetted\n"); - -/* mutex_lock(&tm6000_driver.open_close_mutex); */ - ret = usb_submit_urb(dvb->bulk_urb, GFP_ATOMIC); - -/* mutex_unlock(&tm6000_driver.open_close_mutex); */ - if (ret) { - printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n", - ret); - - kfree(dvb->bulk_urb->transfer_buffer); - usb_free_urb(dvb->bulk_urb); - return ret; - } - - return 0; -} - -static void tm6000_stop_stream(struct tm6000_core *dev) -{ - struct tm6000_dvb *dvb = dev->dvb; - - if (dvb->bulk_urb) { - printk(KERN_INFO "urb killing\n"); - usb_kill_urb(dvb->bulk_urb); - printk(KERN_INFO "urb buffer free\n"); - kfree(dvb->bulk_urb->transfer_buffer); - usb_free_urb(dvb->bulk_urb); - dvb->bulk_urb = NULL; - } -} - -static int tm6000_start_feed(struct dvb_demux_feed *feed) -{ - struct dvb_demux *demux = feed->demux; - struct tm6000_core *dev = demux->priv; - struct tm6000_dvb *dvb = dev->dvb; - printk(KERN_INFO "tm6000: got start feed request %s\n", __func__); - - mutex_lock(&dvb->mutex); - if (dvb->streams == 0) { - dvb->streams = 1; -/* mutex_init(&tm6000_dev->streming_mutex); */ - tm6000_start_stream(dev); - } else - ++(dvb->streams); - mutex_unlock(&dvb->mutex); - - return 0; -} - -static int tm6000_stop_feed(struct dvb_demux_feed *feed) -{ - struct dvb_demux *demux = feed->demux; - struct tm6000_core *dev = demux->priv; - struct tm6000_dvb *dvb = dev->dvb; - - printk(KERN_INFO "tm6000: got stop feed request %s\n", __func__); - - mutex_lock(&dvb->mutex); - - printk(KERN_INFO "stream %#x\n", dvb->streams); - --(dvb->streams); - if (dvb->streams == 0) { - printk(KERN_INFO "stop stream\n"); - tm6000_stop_stream(dev); -/* mutex_destroy(&tm6000_dev->streaming_mutex); */ - } - mutex_unlock(&dvb->mutex); -/* mutex_destroy(&tm6000_dev->streaming_mutex); */ - - return 0; -} - -static int tm6000_dvb_attach_frontend(struct tm6000_core *dev) -{ - struct tm6000_dvb *dvb = dev->dvb; - - if (dev->caps.has_zl10353) { - struct zl10353_config config = { - .demod_address = dev->demod_addr, - .no_tuner = 1, - .parallel_ts = 1, - .if2 = 45700, - .disable_i2c_gate_ctrl = 1, - }; - - dvb->frontend = dvb_attach(zl10353_attach, &config, - &dev->i2c_adap); - } else { - printk(KERN_ERR "tm6000: no frontend defined for the device!\n"); - return -1; - } - - return (!dvb->frontend) ? -1 : 0; -} - -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - -static int register_dvb(struct tm6000_core *dev) -{ - int ret = -1; - struct tm6000_dvb *dvb = dev->dvb; - - mutex_init(&dvb->mutex); - - dvb->streams = 0; - - /* attach the frontend */ - ret = tm6000_dvb_attach_frontend(dev); - if (ret < 0) { - printk(KERN_ERR "tm6000: couldn't attach the frontend!\n"); - goto err; - } - - ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T", - THIS_MODULE, &dev->udev->dev, adapter_nr); - dvb->adapter.priv = dev; - - if (dvb->frontend) { - switch (dev->tuner_type) { - case TUNER_XC2028: { - struct xc2028_config cfg = { - .i2c_adap = &dev->i2c_adap, - .i2c_addr = dev->tuner_addr, - }; - - dvb->frontend->callback = tm6000_tuner_callback; - ret = dvb_register_frontend(&dvb->adapter, dvb->frontend); - if (ret < 0) { - printk(KERN_ERR - "tm6000: couldn't register frontend\n"); - goto adapter_err; - } - - if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) { - printk(KERN_ERR "tm6000: couldn't register " - "frontend (xc3028)\n"); - ret = -EINVAL; - goto frontend_err; - } - printk(KERN_INFO "tm6000: XC2028/3028 asked to be " - "attached to frontend!\n"); - break; - } - case TUNER_XC5000: { - struct xc5000_config cfg = { - .i2c_address = dev->tuner_addr, - }; - - dvb->frontend->callback = tm6000_xc5000_callback; - ret = dvb_register_frontend(&dvb->adapter, dvb->frontend); - if (ret < 0) { - printk(KERN_ERR - "tm6000: couldn't register frontend\n"); - goto adapter_err; - } - - if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) { - printk(KERN_ERR "tm6000: couldn't register " - "frontend (xc5000)\n"); - ret = -EINVAL; - goto frontend_err; - } - printk(KERN_INFO "tm6000: XC5000 asked to be " - "attached to frontend!\n"); - break; - } - } - } else - printk(KERN_ERR "tm6000: no frontend found\n"); - - dvb->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING - | DMX_MEMORY_BASED_FILTERING; - dvb->demux.priv = dev; - dvb->demux.filternum = 8; - dvb->demux.feednum = 8; - dvb->demux.start_feed = tm6000_start_feed; - dvb->demux.stop_feed = tm6000_stop_feed; - dvb->demux.write_to_decoder = NULL; - ret = dvb_dmx_init(&dvb->demux); - if (ret < 0) { - printk(KERN_ERR "tm6000: dvb_dmx_init failed (errno = %d)\n", ret); - goto frontend_err; - } - - dvb->dmxdev.filternum = dev->dvb->demux.filternum; - dvb->dmxdev.demux = &dev->dvb->demux.dmx; - dvb->dmxdev.capabilities = 0; - - ret = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); - if (ret < 0) { - printk(KERN_ERR "tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret); - goto dvb_dmx_err; - } - - return 0; - -dvb_dmx_err: - dvb_dmx_release(&dvb->demux); -frontend_err: - if (dvb->frontend) { - dvb_frontend_detach(dvb->frontend); - dvb_unregister_frontend(dvb->frontend); - } -adapter_err: - dvb_unregister_adapter(&dvb->adapter); -err: - return ret; -} - -static void unregister_dvb(struct tm6000_core *dev) -{ - struct tm6000_dvb *dvb = dev->dvb; - - if (dvb->bulk_urb != NULL) { - struct urb *bulk_urb = dvb->bulk_urb; - - kfree(bulk_urb->transfer_buffer); - bulk_urb->transfer_buffer = NULL; - usb_unlink_urb(bulk_urb); - usb_free_urb(bulk_urb); - } - -/* mutex_lock(&tm6000_driver.open_close_mutex); */ - if (dvb->frontend) { - dvb_frontend_detach(dvb->frontend); - dvb_unregister_frontend(dvb->frontend); - } - - dvb_dmxdev_release(&dvb->dmxdev); - dvb_dmx_release(&dvb->demux); - dvb_unregister_adapter(&dvb->adapter); - mutex_destroy(&dvb->mutex); -/* mutex_unlock(&tm6000_driver.open_close_mutex); */ -} - -static int dvb_init(struct tm6000_core *dev) -{ - struct tm6000_dvb *dvb; - int rc; - - if (!dev) - return 0; - - if (!dev->caps.has_dvb) - return 0; - - if (dev->udev->speed == USB_SPEED_FULL) { - printk(KERN_INFO "This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)\n"); - return 0; - } - - dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL); - if (!dvb) { - printk(KERN_INFO "Cannot allocate memory\n"); - return -ENOMEM; - } - - dev->dvb = dvb; - - rc = register_dvb(dev); - if (rc < 0) { - kfree(dvb); - dev->dvb = NULL; - return 0; - } - - return 0; -} - -static int dvb_fini(struct tm6000_core *dev) -{ - if (!dev) - return 0; - - if (!dev->caps.has_dvb) - return 0; - - if (dev->dvb) { - unregister_dvb(dev); - kfree(dev->dvb); - dev->dvb = NULL; - } - - return 0; -} - -static struct tm6000_ops dvb_ops = { - .type = TM6000_DVB, - .name = "TM6000 dvb Extension", - .init = dvb_init, - .fini = dvb_fini, -}; - -static int __init tm6000_dvb_register(void) -{ - return tm6000_register_extension(&dvb_ops); -} - -static void __exit tm6000_dvb_unregister(void) -{ - tm6000_unregister_extension(&dvb_ops); -} - -module_init(tm6000_dvb_register); -module_exit(tm6000_dvb_unregister); diff --git a/drivers/media/video/tm6000/tm6000-i2c.c b/drivers/media/video/tm6000/tm6000-i2c.c deleted file mode 100644 index c7e23e3dd75e..000000000000 --- a/drivers/media/video/tm6000/tm6000-i2c.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - * tm6000-i2c.c - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> - * - * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com> - * - Fix SMBus Read Byte command - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/usb.h> -#include <linux/i2c.h> - -#include "tm6000.h" -#include "tm6000-regs.h" -#include <media/v4l2-common.h> -#include <media/tuner.h> -#include "tuner-xc2028.h" - - -/* ----------------------------------------------------------- */ - -static unsigned int i2c_debug; -module_param(i2c_debug, int, 0644); -MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); - -#define i2c_dprintk(lvl, fmt, args...) if (i2c_debug >= lvl) do { \ - printk(KERN_DEBUG "%s at %s: " fmt, \ - dev->name, __func__, ##args); } while (0) - -static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr, - __u8 reg, char *buf, int len) -{ - int rc; - unsigned int i2c_packet_limit = 16; - - if (dev->dev_type == TM6010) - i2c_packet_limit = 80; - - if (!buf) - return -1; - - if (len < 1 || len > i2c_packet_limit) { - printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n", - len, i2c_packet_limit); - return -1; - } - - /* capture mutex */ - rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN, - addr | reg << 8, 0, buf, len); - - if (rc < 0) { - /* release mutex */ - return rc; - } - - /* release mutex */ - return rc; -} - -/* Generic read - doesn't work fine with 16bit registers */ -static int tm6000_i2c_recv_regs(struct tm6000_core *dev, unsigned char addr, - __u8 reg, char *buf, int len) -{ - int rc; - u8 b[2]; - unsigned int i2c_packet_limit = 16; - - if (dev->dev_type == TM6010) - i2c_packet_limit = 64; - - if (!buf) - return -1; - - if (len < 1 || len > i2c_packet_limit) { - printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n", - len, i2c_packet_limit); - return -1; - } - - /* capture mutex */ - if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) { - /* - * Workaround an I2C bug when reading from zl10353 - */ - reg -= 1; - len += 1; - - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len); - - *buf = b[1]; - } else { - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len); - } - - /* release mutex */ - return rc; -} - -/* - * read from a 16bit register - * for example xc2028, xc3028 or xc3028L - */ -static int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr, - __u16 reg, char *buf, int len) -{ - int rc; - unsigned char ureg; - - if (!buf || len != 2) - return -1; - - /* capture mutex */ - if (dev->dev_type == TM6010) { - ureg = reg & 0xFF; - rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN, - addr | (reg & 0xFF00), 0, &ureg, 1); - - if (rc < 0) { - /* release mutex */ - return rc; - } - - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ, - reg, 0, buf, len); - } else { - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, REQ_14_SET_GET_I2C_WR2_RDN, - addr, reg, buf, len); - } - - /* release mutex */ - return rc; -} - -static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msgs[], int num) -{ - struct tm6000_core *dev = i2c_adap->algo_data; - int addr, rc, i, byte; - - if (num <= 0) - return 0; - for (i = 0; i < num; i++) { - addr = (msgs[i].addr << 1) & 0xff; - i2c_dprintk(2, "%s %s addr=0x%x len=%d:", - (msgs[i].flags & I2C_M_RD) ? "read" : "write", - i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); - if (msgs[i].flags & I2C_M_RD) { - /* read request without preceding register selection */ - /* - * The TM6000 only supports a read transaction - * immediately after a 1 or 2 byte write to select - * a register. We cannot fulfil this request. - */ - i2c_dprintk(2, " read without preceding write not" - " supported"); - rc = -EOPNOTSUPP; - goto err; - } else if (i + 1 < num && msgs[i].len <= 2 && - (msgs[i + 1].flags & I2C_M_RD) && - msgs[i].addr == msgs[i + 1].addr) { - /* 1 or 2 byte write followed by a read */ - if (i2c_debug >= 2) - for (byte = 0; byte < msgs[i].len; byte++) - printk(KERN_CONT " %02x", msgs[i].buf[byte]); - i2c_dprintk(2, "; joined to read %s len=%d:", - i == num - 2 ? "stop" : "nonstop", - msgs[i + 1].len); - - if (msgs[i].len == 2) { - rc = tm6000_i2c_recv_regs16(dev, addr, - msgs[i].buf[0] << 8 | msgs[i].buf[1], - msgs[i + 1].buf, msgs[i + 1].len); - } else { - rc = tm6000_i2c_recv_regs(dev, addr, msgs[i].buf[0], - msgs[i + 1].buf, msgs[i + 1].len); - } - - i++; - - if (addr == dev->tuner_addr << 1) { - tm6000_set_reg(dev, REQ_50_SET_START, 0, 0); - tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0); - } - if (i2c_debug >= 2) - for (byte = 0; byte < msgs[i].len; byte++) - printk(KERN_CONT " %02x", msgs[i].buf[byte]); - } else { - /* write bytes */ - if (i2c_debug >= 2) - for (byte = 0; byte < msgs[i].len; byte++) - printk(KERN_CONT " %02x", msgs[i].buf[byte]); - rc = tm6000_i2c_send_regs(dev, addr, msgs[i].buf[0], - msgs[i].buf + 1, msgs[i].len - 1); - } - if (i2c_debug >= 2) - printk(KERN_CONT "\n"); - if (rc < 0) - goto err; - } - - return num; -err: - i2c_dprintk(2, " ERROR: %i\n", rc); - return rc; -} - -static int tm6000_i2c_eeprom(struct tm6000_core *dev) -{ - int i, rc; - unsigned char *p = dev->eedata; - unsigned char bytes[17]; - - dev->i2c_client.addr = 0xa0 >> 1; - dev->eedata_size = 0; - - bytes[16] = '\0'; - for (i = 0; i < sizeof(dev->eedata); ) { - *p = i; - rc = tm6000_i2c_recv_regs(dev, 0xa0, i, p, 1); - if (rc < 1) { - if (p == dev->eedata) - goto noeeprom; - else { - printk(KERN_WARNING - "%s: i2c eeprom read error (err=%d)\n", - dev->name, rc); - } - return -EINVAL; - } - dev->eedata_size++; - p++; - if (0 == (i % 16)) - printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i); - printk(KERN_CONT " %02x", dev->eedata[i]); - if ((dev->eedata[i] >= ' ') && (dev->eedata[i] <= 'z')) - bytes[i%16] = dev->eedata[i]; - else - bytes[i%16] = '.'; - - i++; - - if (0 == (i % 16)) { - bytes[16] = '\0'; - printk(KERN_CONT " %s\n", bytes); - } - } - if (0 != (i%16)) { - bytes[i%16] = '\0'; - for (i %= 16; i < 16; i++) - printk(KERN_CONT " "); - printk(KERN_CONT " %s\n", bytes); - } - - return 0; - -noeeprom: - printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", - dev->name, rc); - return -EINVAL; -} - -/* ----------------------------------------------------------- */ - -/* - * functionality() - */ -static u32 functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm tm6000_algo = { - .master_xfer = tm6000_i2c_xfer, - .functionality = functionality, -}; - -/* ----------------------------------------------------------- */ - -/* - * tm6000_i2c_register() - * register i2c bus - */ -int tm6000_i2c_register(struct tm6000_core *dev) -{ - int rc; - - dev->i2c_adap.owner = THIS_MODULE; - dev->i2c_adap.algo = &tm6000_algo; - dev->i2c_adap.dev.parent = &dev->udev->dev; - strlcpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name)); - dev->i2c_adap.algo_data = dev; - i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); - rc = i2c_add_adapter(&dev->i2c_adap); - if (rc) - return rc; - - dev->i2c_client.adapter = &dev->i2c_adap; - strlcpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE); - tm6000_i2c_eeprom(dev); - - return 0; -} - -/* - * tm6000_i2c_unregister() - * unregister i2c_bus - */ -int tm6000_i2c_unregister(struct tm6000_core *dev) -{ - i2c_del_adapter(&dev->i2c_adap); - return 0; -} diff --git a/drivers/media/video/tm6000/tm6000-input.c b/drivers/media/video/tm6000/tm6000-input.c deleted file mode 100644 index e80b7e190471..000000000000 --- a/drivers/media/video/tm6000/tm6000-input.c +++ /dev/null @@ -1,498 +0,0 @@ -/* - * tm6000-input.c - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2010 Stefan Ringel <stefan.ringel@arcor.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/delay.h> - -#include <linux/input.h> -#include <linux/usb.h> - -#include <media/rc-core.h> - -#include "tm6000.h" -#include "tm6000-regs.h" - -static unsigned int ir_debug; -module_param(ir_debug, int, 0644); -MODULE_PARM_DESC(ir_debug, "debug message level"); - -static unsigned int enable_ir = 1; -module_param(enable_ir, int, 0644); -MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)"); - -static unsigned int ir_clock_mhz = 12; -module_param(ir_clock_mhz, int, 0644); -MODULE_PARM_DESC(enable_ir, "ir clock, in MHz"); - -#define URB_SUBMIT_DELAY 100 /* ms - Delay to submit an URB request on retrial and init */ -#define URB_INT_LED_DELAY 100 /* ms - Delay to turn led on again on int mode */ - -#undef dprintk - -#define dprintk(level, fmt, arg...) do {\ - if (ir_debug >= level) \ - printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ - } while (0) - -struct tm6000_ir_poll_result { - u16 rc_data; -}; - -struct tm6000_IR { - struct tm6000_core *dev; - struct rc_dev *rc; - char name[32]; - char phys[32]; - - /* poll expernal decoder */ - int polling; - struct delayed_work work; - u8 wait:1; - u8 pwled:2; - u8 submit_urb:1; - u16 key_addr; - struct urb *int_urb; - - /* IR device properties */ - u64 rc_type; -}; - -void tm6000_ir_wait(struct tm6000_core *dev, u8 state) -{ - struct tm6000_IR *ir = dev->ir; - - if (!dev->ir) - return; - - dprintk(2, "%s: %i\n",__func__, ir->wait); - - if (state) - ir->wait = 1; - else - ir->wait = 0; -} - -static int tm6000_ir_config(struct tm6000_IR *ir) -{ - struct tm6000_core *dev = ir->dev; - u32 pulse = 0, leader = 0; - - dprintk(2, "%s\n",__func__); - - /* - * The IR decoder supports RC-5 or NEC, with a configurable timing. - * The timing configuration there is not that accurate, as it uses - * approximate values. The NEC spec mentions a 562.5 unit period, - * and RC-5 uses a 888.8 period. - * Currently, driver assumes a clock provided by a 12 MHz XTAL, but - * a modprobe parameter can adjust it. - * Adjustments are required for other timings. - * It seems that the 900ms timing for NEC is used to detect a RC-5 - * IR, in order to discard such decoding - */ - - switch (ir->rc_type) { - case RC_TYPE_NEC: - leader = 900; /* ms */ - pulse = 700; /* ms - the actual value would be 562 */ - break; - default: - case RC_TYPE_RC5: - leader = 900; /* ms - from the NEC decoding */ - pulse = 1780; /* ms - The actual value would be 1776 */ - break; - } - - pulse = ir_clock_mhz * pulse; - leader = ir_clock_mhz * leader; - if (ir->rc_type == RC_TYPE_NEC) - leader = leader | 0x8000; - - dprintk(2, "%s: %s, %d MHz, leader = 0x%04x, pulse = 0x%06x \n", - __func__, - (ir->rc_type == RC_TYPE_NEC) ? "NEC" : "RC-5", - ir_clock_mhz, leader, pulse); - - /* Remote WAKEUP = enable, normal mode, from IR decoder output */ - tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe); - - /* Enable IR reception on non-busrt mode */ - tm6000_set_reg(dev, TM6010_REQ07_RD8_IR, 0x2f); - - /* IR_WKUP_SEL = Low byte in decoded IR data */ - tm6000_set_reg(dev, TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff); - /* IR_WKU_ADD code */ - tm6000_set_reg(dev, TM6010_REQ07_RDB_IR_WAKEUP_ADD, 0xff); - - tm6000_set_reg(dev, TM6010_REQ07_RDC_IR_LEADER1, leader >> 8); - tm6000_set_reg(dev, TM6010_REQ07_RDD_IR_LEADER0, leader); - - tm6000_set_reg(dev, TM6010_REQ07_RDE_IR_PULSE_CNT1, pulse >> 8); - tm6000_set_reg(dev, TM6010_REQ07_RDF_IR_PULSE_CNT0, pulse); - - if (!ir->polling) - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); - else - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1); - msleep(10); - - /* Shows that IR is working via the LED */ - tm6000_flash_led(dev, 0); - msleep(100); - tm6000_flash_led(dev, 1); - ir->pwled = 1; - - return 0; -} - -static void tm6000_ir_urb_received(struct urb *urb) -{ - struct tm6000_core *dev = urb->context; - struct tm6000_IR *ir = dev->ir; - struct tm6000_ir_poll_result poll_result; - char *buf; - - dprintk(2, "%s\n",__func__); - if (urb->status < 0 || urb->actual_length <= 0) { - printk(KERN_INFO "tm6000: IR URB failure: status: %i, length %i\n", - urb->status, urb->actual_length); - ir->submit_urb = 1; - schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY)); - return; - } - buf = urb->transfer_buffer; - - if (ir_debug) - print_hex_dump(KERN_DEBUG, "tm6000: IR data: ", - DUMP_PREFIX_OFFSET,16, 1, - buf, urb->actual_length, false); - - poll_result.rc_data = buf[0]; - if (urb->actual_length > 1) - poll_result.rc_data |= buf[1] << 8; - - dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data); - rc_keydown(ir->rc, poll_result.rc_data, 0); - - usb_submit_urb(urb, GFP_ATOMIC); - /* - * Flash the led. We can't do it here, as it is running on IRQ context. - * So, use the scheduler to do it, in a few ms. - */ - ir->pwled = 2; - schedule_delayed_work(&ir->work, msecs_to_jiffies(10)); -} - -static void tm6000_ir_handle_key(struct work_struct *work) -{ - struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work); - struct tm6000_core *dev = ir->dev; - struct tm6000_ir_poll_result poll_result; - int rc; - u8 buf[2]; - - if (ir->wait) - return; - - dprintk(3, "%s\n",__func__); - - rc = tm6000_read_write_usb(dev, USB_DIR_IN | - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - REQ_02_GET_IR_CODE, 0, 0, buf, 2); - if (rc < 0) - return; - - if (rc > 1) - poll_result.rc_data = buf[0] | buf[1] << 8; - else - poll_result.rc_data = buf[0]; - - /* Check if something was read */ - if ((poll_result.rc_data & 0xff) == 0xff) { - if (!ir->pwled) { - tm6000_flash_led(dev, 1); - ir->pwled = 1; - } - return; - } - - dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data); - rc_keydown(ir->rc, poll_result.rc_data, 0); - tm6000_flash_led(dev, 0); - ir->pwled = 0; - - /* Re-schedule polling */ - schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); -} - -static void tm6000_ir_int_work(struct work_struct *work) -{ - struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work); - struct tm6000_core *dev = ir->dev; - int rc; - - dprintk(3, "%s, submit_urb = %d, pwled = %d\n",__func__, ir->submit_urb, - ir->pwled); - - if (ir->submit_urb) { - dprintk(3, "Resubmit urb\n"); - tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); - - rc = usb_submit_urb(ir->int_urb, GFP_ATOMIC); - if (rc < 0) { - printk(KERN_ERR "tm6000: Can't submit an IR interrupt. Error %i\n", - rc); - /* Retry in 100 ms */ - schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY)); - return; - } - ir->submit_urb = 0; - } - - /* Led is enabled only if USB submit doesn't fail */ - if (ir->pwled == 2) { - tm6000_flash_led(dev, 0); - ir->pwled = 0; - schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_INT_LED_DELAY)); - } else if (!ir->pwled) { - tm6000_flash_led(dev, 1); - ir->pwled = 1; - } -} - -static int tm6000_ir_start(struct rc_dev *rc) -{ - struct tm6000_IR *ir = rc->priv; - - dprintk(2, "%s\n",__func__); - - schedule_delayed_work(&ir->work, 0); - - return 0; -} - -static void tm6000_ir_stop(struct rc_dev *rc) -{ - struct tm6000_IR *ir = rc->priv; - - dprintk(2, "%s\n",__func__); - - cancel_delayed_work_sync(&ir->work); -} - -static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type) -{ - struct tm6000_IR *ir = rc->priv; - - if (!ir) - return 0; - - dprintk(2, "%s\n",__func__); - - if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC)) - ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff); - - ir->rc_type = rc_type; - - tm6000_ir_config(ir); - /* TODO */ - return 0; -} - -static int __tm6000_ir_int_start(struct rc_dev *rc) -{ - struct tm6000_IR *ir = rc->priv; - struct tm6000_core *dev = ir->dev; - int pipe, size; - int err = -ENOMEM; - - if (!ir) - return -ENODEV; - - dprintk(2, "%s\n",__func__); - - ir->int_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!ir->int_urb) - return -ENOMEM; - - pipe = usb_rcvintpipe(dev->udev, - dev->int_in.endp->desc.bEndpointAddress - & USB_ENDPOINT_NUMBER_MASK); - - size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); - dprintk(1, "IR max size: %d\n", size); - - ir->int_urb->transfer_buffer = kzalloc(size, GFP_ATOMIC); - if (ir->int_urb->transfer_buffer == NULL) { - usb_free_urb(ir->int_urb); - return err; - } - dprintk(1, "int interval: %d\n", dev->int_in.endp->desc.bInterval); - - usb_fill_int_urb(ir->int_urb, dev->udev, pipe, - ir->int_urb->transfer_buffer, size, - tm6000_ir_urb_received, dev, - dev->int_in.endp->desc.bInterval); - - ir->submit_urb = 1; - schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY)); - - return 0; -} - -static void __tm6000_ir_int_stop(struct rc_dev *rc) -{ - struct tm6000_IR *ir = rc->priv; - - if (!ir || !ir->int_urb) - return; - - dprintk(2, "%s\n",__func__); - - usb_kill_urb(ir->int_urb); - kfree(ir->int_urb->transfer_buffer); - usb_free_urb(ir->int_urb); - ir->int_urb = NULL; -} - -int tm6000_ir_int_start(struct tm6000_core *dev) -{ - struct tm6000_IR *ir = dev->ir; - - if (!ir) - return 0; - - return __tm6000_ir_int_start(ir->rc); -} - -void tm6000_ir_int_stop(struct tm6000_core *dev) -{ - struct tm6000_IR *ir = dev->ir; - - if (!ir || !ir->rc) - return; - - __tm6000_ir_int_stop(ir->rc); -} - -int tm6000_ir_init(struct tm6000_core *dev) -{ - struct tm6000_IR *ir; - struct rc_dev *rc; - int err = -ENOMEM; - - if (!enable_ir) - return -ENODEV; - - if (!dev->caps.has_remote) - return 0; - - if (!dev->ir_codes) - return 0; - - ir = kzalloc(sizeof(*ir), GFP_ATOMIC); - rc = rc_allocate_device(); - if (!ir || !rc) - goto out; - - dprintk(2, "%s\n", __func__); - - /* record handles to ourself */ - ir->dev = dev; - dev->ir = ir; - ir->rc = rc; - - /* input setup */ - rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC; - /* Neded, in order to support NEC remotes with 24 or 32 bits */ - rc->scanmask = 0xffff; - rc->priv = ir; - rc->change_protocol = tm6000_ir_change_protocol; - if (dev->int_in.endp) { - rc->open = __tm6000_ir_int_start; - rc->close = __tm6000_ir_int_stop; - INIT_DELAYED_WORK(&ir->work, tm6000_ir_int_work); - } else { - rc->open = tm6000_ir_start; - rc->close = tm6000_ir_stop; - ir->polling = 50; - INIT_DELAYED_WORK(&ir->work, tm6000_ir_handle_key); - } - rc->driver_type = RC_DRIVER_SCANCODE; - - snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)", - dev->name); - - usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); - strlcat(ir->phys, "/input0", sizeof(ir->phys)); - - tm6000_ir_change_protocol(rc, RC_TYPE_UNKNOWN); - - rc->input_name = ir->name; - rc->input_phys = ir->phys; - rc->input_id.bustype = BUS_USB; - rc->input_id.version = 1; - rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); - rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct); - rc->map_name = dev->ir_codes; - rc->driver_name = "tm6000"; - rc->dev.parent = &dev->udev->dev; - - /* ir register */ - err = rc_register_device(rc); - if (err) - goto out; - - return 0; - -out: - dev->ir = NULL; - rc_free_device(rc); - kfree(ir); - return err; -} - -int tm6000_ir_fini(struct tm6000_core *dev) -{ - struct tm6000_IR *ir = dev->ir; - - /* skip detach on non attached board */ - - if (!ir) - return 0; - - dprintk(2, "%s\n",__func__); - - if (!ir->polling) - __tm6000_ir_int_stop(ir->rc); - - tm6000_ir_stop(ir->rc); - - /* Turn off the led */ - tm6000_flash_led(dev, 0); - ir->pwled = 0; - - rc_unregister_device(ir->rc); - - kfree(ir); - dev->ir = NULL; - - return 0; -} diff --git a/drivers/media/video/tm6000/tm6000-regs.h b/drivers/media/video/tm6000/tm6000-regs.h deleted file mode 100644 index a38c251ed57b..000000000000 --- a/drivers/media/video/tm6000/tm6000-regs.h +++ /dev/null @@ -1,600 +0,0 @@ -/* - * tm6000-regs.h - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * 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. - */ - -/* - * Define TV Master TM5600/TM6000/TM6010 Request codes - */ -#define REQ_00_SET_IR_VALUE 0 -#define REQ_01_SET_WAKEUP_IRCODE 1 -#define REQ_02_GET_IR_CODE 2 -#define REQ_03_SET_GET_MCU_PIN 3 -#define REQ_04_EN_DISABLE_MCU_INT 4 -#define REQ_05_SET_GET_USBREG 5 - /* Write: RegNum, Value, 0 */ - /* Read : RegNum, Value, 1, RegStatus */ -#define REQ_06_SET_GET_USBREG_BIT 6 -#define REQ_07_SET_GET_AVREG 7 - /* Write: RegNum, Value, 0 */ - /* Read : RegNum, Value, 1, RegStatus */ -#define REQ_08_SET_GET_AVREG_BIT 8 -#define REQ_09_SET_GET_TUNER_FQ 9 -#define REQ_10_SET_TUNER_SYSTEM 10 -#define REQ_11_SET_EEPROM_ADDR 11 -#define REQ_12_SET_GET_EEPROMBYTE 12 -#define REQ_13_GET_EEPROM_SEQREAD 13 -#define REQ_14_SET_GET_I2C_WR2_RDN 14 -#define REQ_15_SET_GET_I2CBYTE 15 - /* Write: Subaddr, Slave Addr, value, 0 */ - /* Read : Subaddr, Slave Addr, value, 1 */ -#define REQ_16_SET_GET_I2C_WR1_RDN 16 - /* Subaddr, Slave Addr, 0, length */ -#define REQ_17_SET_GET_I2CFP 17 - /* Write: Slave Addr, register, value */ - /* Read : Slave Addr, register, 2, data */ -#define REQ_20_DATA_TRANSFER 20 -#define REQ_30_I2C_WRITE 30 -#define REQ_31_I2C_READ 31 -#define REQ_35_AFTEK_TUNER_READ 35 -#define REQ_40_GET_VERSION 40 -#define REQ_50_SET_START 50 -#define REQ_51_SET_STOP 51 -#define REQ_52_TRANSMIT_DATA 52 -#define REQ_53_SPI_INITIAL 53 -#define REQ_54_SPI_SETSTART 54 -#define REQ_55_SPI_INOUTDATA 55 -#define REQ_56_SPI_SETSTOP 56 - -/* - * Define TV Master TM5600/TM6000/TM6010 GPIO lines - */ - -#define TM6000_GPIO_CLK 0x101 -#define TM6000_GPIO_DATA 0x100 - -#define TM6000_GPIO_1 0x102 -#define TM6000_GPIO_2 0x103 -#define TM6000_GPIO_3 0x104 -#define TM6000_GPIO_4 0x300 -#define TM6000_GPIO_5 0x301 -#define TM6000_GPIO_6 0x304 -#define TM6000_GPIO_7 0x305 - -/* tm6010 defines GPIO with different values */ -#define TM6010_GPIO_0 0x0102 -#define TM6010_GPIO_1 0x0103 -#define TM6010_GPIO_2 0x0104 -#define TM6010_GPIO_3 0x0105 -#define TM6010_GPIO_4 0x0106 -#define TM6010_GPIO_5 0x0107 -#define TM6010_GPIO_6 0x0300 -#define TM6010_GPIO_7 0x0301 -#define TM6010_GPIO_9 0x0305 -/* - * Define TV Master TM5600/TM6000/TM6010 URB message codes and length - */ - -enum { - TM6000_URB_MSG_VIDEO = 1, - TM6000_URB_MSG_AUDIO, - TM6000_URB_MSG_VBI, - TM6000_URB_MSG_PTS, - TM6000_URB_MSG_ERR, -}; - -/* Define specific TM6000 Video decoder registers */ -#define TM6000_REQ07_RD8_TEST_SEL 0x07, 0xd8 -#define TM6000_REQ07_RD9_A_SIM_SEL 0x07, 0xd9 -#define TM6000_REQ07_RDA_CLK_SEL 0x07, 0xda -#define TM6000_REQ07_RDB_OUT_SEL 0x07, 0xdb -#define TM6000_REQ07_RDC_NSEL_I2S 0x07, 0xdc -#define TM6000_REQ07_RDD_GPIO2_MDRV 0x07, 0xdd -#define TM6000_REQ07_RDE_GPIO1_MDRV 0x07, 0xde -#define TM6000_REQ07_RDF_PWDOWN_ACLK 0x07, 0xdf -#define TM6000_REQ07_RE0_VADC_REF_CTL 0x07, 0xe0 -#define TM6000_REQ07_RE1_VADC_DACLIMP 0x07, 0xe1 -#define TM6000_REQ07_RE2_VADC_STATUS_CTL 0x07, 0xe2 -#define TM6000_REQ07_RE3_VADC_INP_LPF_SEL1 0x07, 0xe3 -#define TM6000_REQ07_RE4_VADC_TARGET1 0x07, 0xe4 -#define TM6000_REQ07_RE5_VADC_INP_LPF_SEL2 0x07, 0xe5 -#define TM6000_REQ07_RE6_VADC_TARGET2 0x07, 0xe6 -#define TM6000_REQ07_RE7_VADC_AGAIN_CTL 0x07, 0xe7 -#define TM6000_REQ07_RE8_VADC_PWDOWN_CTL 0x07, 0xe8 -#define TM6000_REQ07_RE9_VADC_INPUT_CTL1 0x07, 0xe9 -#define TM6000_REQ07_REA_VADC_INPUT_CTL2 0x07, 0xea -#define TM6000_REQ07_REB_VADC_AADC_MODE 0x07, 0xeb -#define TM6000_REQ07_REC_VADC_AADC_LVOL 0x07, 0xec -#define TM6000_REQ07_RED_VADC_AADC_RVOL 0x07, 0xed -#define TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL 0x07, 0xee -#define TM6000_REQ07_REF_VADC_GAIN_MAP_CTL 0x07, 0xef -#define TM6000_REQ07_RFD_BIST_ERR_VST_LOW 0x07, 0xfd -#define TM6000_REQ07_RFE_BIST_ERR_VST_HIGH 0x07, 0xfe - -/* Define TM6000/TM6010 Video decoder registers */ -#define TM6010_REQ07_R00_VIDEO_CONTROL0 0x07, 0x00 -#define TM6010_REQ07_R01_VIDEO_CONTROL1 0x07, 0x01 -#define TM6010_REQ07_R02_VIDEO_CONTROL2 0x07, 0x02 -#define TM6010_REQ07_R03_YC_SEP_CONTROL 0x07, 0x03 -#define TM6010_REQ07_R04_LUMA_HAGC_CONTROL 0x07, 0x04 -#define TM6010_REQ07_R05_NOISE_THRESHOLD 0x07, 0x05 -#define TM6010_REQ07_R06_AGC_GATE_THRESHOLD 0x07, 0x06 -#define TM6010_REQ07_R07_OUTPUT_CONTROL 0x07, 0x07 -#define TM6010_REQ07_R08_LUMA_CONTRAST_ADJ 0x07, 0x08 -#define TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ 0x07, 0x09 -#define TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ 0x07, 0x0a -#define TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ 0x07, 0x0b -#define TM6010_REQ07_R0C_CHROMA_AGC_CONTROL 0x07, 0x0c -#define TM6010_REQ07_R0D_CHROMA_KILL_LEVEL 0x07, 0x0d -#define TM6010_REQ07_R0F_CHROMA_AUTO_POSITION 0x07, 0x0f -#define TM6010_REQ07_R10_AGC_PEAK_NOMINAL 0x07, 0x10 -#define TM6010_REQ07_R11_AGC_PEAK_CONTROL 0x07, 0x11 -#define TM6010_REQ07_R12_AGC_GATE_STARTH 0x07, 0x12 -#define TM6010_REQ07_R13_AGC_GATE_STARTL 0x07, 0x13 -#define TM6010_REQ07_R14_AGC_GATE_WIDTH 0x07, 0x14 -#define TM6010_REQ07_R15_AGC_BP_DELAY 0x07, 0x15 -#define TM6010_REQ07_R16_LOCK_COUNT 0x07, 0x16 -#define TM6010_REQ07_R17_HLOOP_MAXSTATE 0x07, 0x17 -#define TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3 0x07, 0x18 -#define TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2 0x07, 0x19 -#define TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1 0x07, 0x1a -#define TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0 0x07, 0x1b -#define TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3 0x07, 0x1c -#define TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2 0x07, 0x1d -#define TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1 0x07, 0x1e -#define TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0 0x07, 0x1f -#define TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME 0x07, 0x20 -#define TM6010_REQ07_R21_HSYNC_PHASE_OFFSET 0x07, 0x21 -#define TM6010_REQ07_R22_HSYNC_PLL_START_TIME 0x07, 0x22 -#define TM6010_REQ07_R23_HSYNC_PLL_END_TIME 0x07, 0x23 -#define TM6010_REQ07_R24_HSYNC_TIP_START_TIME 0x07, 0x24 -#define TM6010_REQ07_R25_HSYNC_TIP_END_TIME 0x07, 0x25 -#define TM6010_REQ07_R26_HSYNC_RISING_EDGE_START 0x07, 0x26 -#define TM6010_REQ07_R27_HSYNC_RISING_EDGE_END 0x07, 0x27 -#define TM6010_REQ07_R28_BACKPORCH_START 0x07, 0x28 -#define TM6010_REQ07_R29_BACKPORCH_END 0x07, 0x29 -#define TM6010_REQ07_R2A_HSYNC_FILTER_START 0x07, 0x2a -#define TM6010_REQ07_R2B_HSYNC_FILTER_END 0x07, 0x2b -#define TM6010_REQ07_R2C_CHROMA_BURST_START 0x07, 0x2c -#define TM6010_REQ07_R2D_CHROMA_BURST_END 0x07, 0x2d -#define TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART 0x07, 0x2e -#define TM6010_REQ07_R2F_ACTIVE_VIDEO_HWIDTH 0x07, 0x2f -#define TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART 0x07, 0x30 -#define TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT 0x07, 0x31 -#define TM6010_REQ07_R32_VSYNC_HLOCK_MIN 0x07, 0x32 -#define TM6010_REQ07_R33_VSYNC_HLOCK_MAX 0x07, 0x33 -#define TM6010_REQ07_R34_VSYNC_AGC_MIN 0x07, 0x34 -#define TM6010_REQ07_R35_VSYNC_AGC_MAX 0x07, 0x35 -#define TM6010_REQ07_R36_VSYNC_VBI_MIN 0x07, 0x36 -#define TM6010_REQ07_R37_VSYNC_VBI_MAX 0x07, 0x37 -#define TM6010_REQ07_R38_VSYNC_THRESHOLD 0x07, 0x38 -#define TM6010_REQ07_R39_VSYNC_TIME_CONSTANT 0x07, 0x39 -#define TM6010_REQ07_R3A_STATUS1 0x07, 0x3a -#define TM6010_REQ07_R3B_STATUS2 0x07, 0x3b -#define TM6010_REQ07_R3C_STATUS3 0x07, 0x3c -#define TM6010_REQ07_R3F_RESET 0x07, 0x3f -#define TM6010_REQ07_R40_TELETEXT_VBI_CODE0 0x07, 0x40 -#define TM6010_REQ07_R41_TELETEXT_VBI_CODE1 0x07, 0x41 -#define TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL 0x07, 0x42 -#define TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7 0x07, 0x43 -#define TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8 0x07, 0x44 -#define TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9 0x07, 0x45 -#define TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10 0x07, 0x46 -#define TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11 0x07, 0x47 -#define TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12 0x07, 0x48 -#define TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13 0x07, 0x49 -#define TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14 0x07, 0x4a -#define TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15 0x07, 0x4b -#define TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16 0x07, 0x4c -#define TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17 0x07, 0x4d -#define TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18 0x07, 0x4e -#define TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19 0x07, 0x4f -#define TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20 0x07, 0x50 -#define TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21 0x07, 0x51 -#define TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22 0x07, 0x52 -#define TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23 0x07, 0x53 -#define TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES 0x07, 0x54 -#define TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN 0x07, 0x55 -#define TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN 0x07, 0x56 -#define TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN 0x07, 0x57 -#define TM6010_REQ07_R58_VBI_CAPTION_DTO1 0x07, 0x58 -#define TM6010_REQ07_R59_VBI_CAPTION_DTO0 0x07, 0x59 -#define TM6010_REQ07_R5A_VBI_TELETEXT_DTO1 0x07, 0x5a -#define TM6010_REQ07_R5B_VBI_TELETEXT_DTO0 0x07, 0x5b -#define TM6010_REQ07_R5C_VBI_WSS625_DTO1 0x07, 0x5c -#define TM6010_REQ07_R5D_VBI_WSS625_DTO0 0x07, 0x5d -#define TM6010_REQ07_R5E_VBI_CAPTION_FRAME_START 0x07, 0x5e -#define TM6010_REQ07_R5F_VBI_WSS625_FRAME_START 0x07, 0x5f -#define TM6010_REQ07_R60_TELETEXT_FRAME_START 0x07, 0x60 -#define TM6010_REQ07_R61_VBI_CCDATA1 0x07, 0x61 -#define TM6010_REQ07_R62_VBI_CCDATA2 0x07, 0x62 -#define TM6010_REQ07_R63_VBI_WSS625_DATA1 0x07, 0x63 -#define TM6010_REQ07_R64_VBI_WSS625_DATA2 0x07, 0x64 -#define TM6010_REQ07_R65_VBI_DATA_STATUS 0x07, 0x65 -#define TM6010_REQ07_R66_VBI_CAPTION_START 0x07, 0x66 -#define TM6010_REQ07_R67_VBI_WSS625_START 0x07, 0x67 -#define TM6010_REQ07_R68_VBI_TELETEXT_START 0x07, 0x68 -#define TM6010_REQ07_R70_HSYNC_DTO_INC_STATUS3 0x07, 0x70 -#define TM6010_REQ07_R71_HSYNC_DTO_INC_STATUS2 0x07, 0x71 -#define TM6010_REQ07_R72_HSYNC_DTO_INC_STATUS1 0x07, 0x72 -#define TM6010_REQ07_R73_HSYNC_DTO_INC_STATUS0 0x07, 0x73 -#define TM6010_REQ07_R74_CHROMA_DTO_INC_STATUS3 0x07, 0x74 -#define TM6010_REQ07_R75_CHROMA_DTO_INC_STATUS2 0x07, 0x75 -#define TM6010_REQ07_R76_CHROMA_DTO_INC_STATUS1 0x07, 0x76 -#define TM6010_REQ07_R77_CHROMA_DTO_INC_STATUS0 0x07, 0x77 -#define TM6010_REQ07_R78_AGC_AGAIN_STATUS 0x07, 0x78 -#define TM6010_REQ07_R79_AGC_DGAIN_STATUS 0x07, 0x79 -#define TM6010_REQ07_R7A_CHROMA_MAG_STATUS 0x07, 0x7a -#define TM6010_REQ07_R7B_CHROMA_GAIN_STATUS1 0x07, 0x7b -#define TM6010_REQ07_R7C_CHROMA_GAIN_STATUS0 0x07, 0x7c -#define TM6010_REQ07_R7D_CORDIC_FREQ_STATUS 0x07, 0x7d -#define TM6010_REQ07_R7F_STATUS_NOISE 0x07, 0x7f -#define TM6010_REQ07_R80_COMB_FILTER_TRESHOLD 0x07, 0x80 -#define TM6010_REQ07_R82_COMB_FILTER_CONFIG 0x07, 0x82 -#define TM6010_REQ07_R83_CHROMA_LOCK_CONFIG 0x07, 0x83 -#define TM6010_REQ07_R84_NOISE_NTSC_C 0x07, 0x84 -#define TM6010_REQ07_R85_NOISE_PAL_C 0x07, 0x85 -#define TM6010_REQ07_R86_NOISE_PHASE_C 0x07, 0x86 -#define TM6010_REQ07_R87_NOISE_PHASE_Y 0x07, 0x87 -#define TM6010_REQ07_R8A_CHROMA_LOOPFILTER_STATE 0x07, 0x8a -#define TM6010_REQ07_R8B_CHROMA_HRESAMPLER 0x07, 0x8b -#define TM6010_REQ07_R8D_CPUMP_DELAY_ADJ 0x07, 0x8d -#define TM6010_REQ07_R8E_CPUMP_ADJ 0x07, 0x8e -#define TM6010_REQ07_R8F_CPUMP_DELAY 0x07, 0x8f - -/* Define TM6000/TM6010 Miscellaneous registers */ -#define TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE 0x07, 0xc0 -#define TM6010_REQ07_RC1_TRESHOLD 0x07, 0xc1 -#define TM6010_REQ07_RC2_HSYNC_WIDTH 0x07, 0xc2 -#define TM6010_REQ07_RC3_HSTART1 0x07, 0xc3 -#define TM6010_REQ07_RC4_HSTART0 0x07, 0xc4 -#define TM6010_REQ07_RC5_HEND1 0x07, 0xc5 -#define TM6010_REQ07_RC6_HEND0 0x07, 0xc6 -#define TM6010_REQ07_RC7_VSTART1 0x07, 0xc7 -#define TM6010_REQ07_RC8_VSTART0 0x07, 0xc8 -#define TM6010_REQ07_RC9_VEND1 0x07, 0xc9 -#define TM6010_REQ07_RCA_VEND0 0x07, 0xca -#define TM6010_REQ07_RCB_DELAY 0x07, 0xcb -/* ONLY for TM6010 */ -#define TM6010_REQ07_RCC_ACTIVE_IF 0x07, 0xcc -#define TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE (1 << 5) -#define TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE (1 << 6) -#define TM6010_REQ07_RD0_USB_PERIPHERY_CONTROL 0x07, 0xd0 -#define TM6010_REQ07_RD1_ADDR_FOR_REQ1 0x07, 0xd1 -#define TM6010_REQ07_RD2_ADDR_FOR_REQ2 0x07, 0xd2 -#define TM6010_REQ07_RD3_ADDR_FOR_REQ3 0x07, 0xd3 -#define TM6010_REQ07_RD4_ADDR_FOR_REQ4 0x07, 0xd4 -#define TM6010_REQ07_RD5_POWERSAVE 0x07, 0xd5 -#define TM6010_REQ07_RD6_ENDP_REQ1_REQ2 0x07, 0xd6 -#define TM6010_REQ07_RD7_ENDP_REQ3_REQ4 0x07, 0xd7 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RD8_IR 0x07, 0xd8 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RD9_IR_BSIZE 0x07, 0xd9 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RDA_IR_WAKEUP_SEL 0x07, 0xda -/* ONLY for TM6010 */ -#define TM6010_REQ07_RDB_IR_WAKEUP_ADD 0x07, 0xdb -/* ONLY for TM6010 */ -#define TM6010_REQ07_RDC_IR_LEADER1 0x07, 0xdc -/* ONLY for TM6010 */ -#define TM6010_REQ07_RDD_IR_LEADER0 0x07, 0xdd -/* ONLY for TM6010 */ -#define TM6010_REQ07_RDE_IR_PULSE_CNT1 0x07, 0xde -/* ONLY for TM6010 */ -#define TM6010_REQ07_RDF_IR_PULSE_CNT0 0x07, 0xdf -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE0_DVIDEO_SOURCE 0x07, 0xe0 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE0_DVIDEO_SOURCE_IF 0x07, 0xe1 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE2_OUT_SEL2 0x07, 0xe2 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE3_OUT_SEL1 0x07, 0xe3 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE4_OUT_SEL0 0x07, 0xe4 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE5_REMOTE_WAKEUP 0x07, 0xe5 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE7_PUB_GPIO 0x07, 0xe7 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE8_TYPESEL_MOS_I2S 0x07, 0xe8 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RE9_TYPESEL_MOS_TS 0x07, 0xe9 -/* ONLY for TM6010 */ -#define TM6010_REQ07_REA_TYPESEL_MOS_CCIR 0x07, 0xea -/* ONLY for TM6010 */ -#define TM6010_REQ07_RF0_BIST_CRC_RESULT0 0x07, 0xf0 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RF1_BIST_CRC_RESULT1 0x07, 0xf1 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RF2_BIST_CRC_RESULT2 0x07, 0xf2 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RF3_BIST_CRC_RESULT3 0x07, 0xf3 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RF4_BIST_ERR_VST2 0x07, 0xf4 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RF5_BIST_ERR_VST1 0x07, 0xf5 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RF6_BIST_ERR_VST0 0x07, 0xf6 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RF7_BIST 0x07, 0xf7 -/* ONLY for TM6010 */ -#define TM6010_REQ07_RFE_POWER_DOWN 0x07, 0xfe -#define TM6010_REQ07_RFF_SOFT_RESET 0x07, 0xff - -/* Define TM6000/TM6010 USB registers */ -#define TM6010_REQ05_R00_MAIN_CTRL 0x05, 0x00 -#define TM6010_REQ05_R01_DEVADDR 0x05, 0x01 -#define TM6010_REQ05_R02_TEST 0x05, 0x02 -#define TM6010_REQ05_R04_SOFN0 0x05, 0x04 -#define TM6010_REQ05_R05_SOFN1 0x05, 0x05 -#define TM6010_REQ05_R06_SOFTM0 0x05, 0x06 -#define TM6010_REQ05_R07_SOFTM1 0x05, 0x07 -#define TM6010_REQ05_R08_PHY_TEST 0x05, 0x08 -#define TM6010_REQ05_R09_VCTL 0x05, 0x09 -#define TM6010_REQ05_R0A_VSTA 0x05, 0x0a -#define TM6010_REQ05_R0B_CX_CFG 0x05, 0x0b -#define TM6010_REQ05_R0C_ENDP0_REG0 0x05, 0x0c -#define TM6010_REQ05_R10_GMASK 0x05, 0x10 -#define TM6010_REQ05_R11_IMASK0 0x05, 0x11 -#define TM6010_REQ05_R12_IMASK1 0x05, 0x12 -#define TM6010_REQ05_R13_IMASK2 0x05, 0x13 -#define TM6010_REQ05_R14_IMASK3 0x05, 0x14 -#define TM6010_REQ05_R15_IMASK4 0x05, 0x15 -#define TM6010_REQ05_R16_IMASK5 0x05, 0x16 -#define TM6010_REQ05_R17_IMASK6 0x05, 0x17 -#define TM6010_REQ05_R18_IMASK7 0x05, 0x18 -#define TM6010_REQ05_R19_ZEROP0 0x05, 0x19 -#define TM6010_REQ05_R1A_ZEROP1 0x05, 0x1a -#define TM6010_REQ05_R1C_FIFO_EMP0 0x05, 0x1c -#define TM6010_REQ05_R1D_FIFO_EMP1 0x05, 0x1d -#define TM6010_REQ05_R20_IRQ_GROUP 0x05, 0x20 -#define TM6010_REQ05_R21_IRQ_SOURCE0 0x05, 0x21 -#define TM6010_REQ05_R22_IRQ_SOURCE1 0x05, 0x22 -#define TM6010_REQ05_R23_IRQ_SOURCE2 0x05, 0x23 -#define TM6010_REQ05_R24_IRQ_SOURCE3 0x05, 0x24 -#define TM6010_REQ05_R25_IRQ_SOURCE4 0x05, 0x25 -#define TM6010_REQ05_R26_IRQ_SOURCE5 0x05, 0x26 -#define TM6010_REQ05_R27_IRQ_SOURCE6 0x05, 0x27 -#define TM6010_REQ05_R28_IRQ_SOURCE7 0x05, 0x28 -#define TM6010_REQ05_R29_SEQ_ERR0 0x05, 0x29 -#define TM6010_REQ05_R2A_SEQ_ERR1 0x05, 0x2a -#define TM6010_REQ05_R2B_SEQ_ABORT0 0x05, 0x2b -#define TM6010_REQ05_R2C_SEQ_ABORT1 0x05, 0x2c -#define TM6010_REQ05_R2D_TX_ZERO0 0x05, 0x2d -#define TM6010_REQ05_R2E_TX_ZERO1 0x05, 0x2e -#define TM6010_REQ05_R2F_IDLE_CNT 0x05, 0x2f -#define TM6010_REQ05_R30_FNO_P1 0x05, 0x30 -#define TM6010_REQ05_R31_FNO_P2 0x05, 0x31 -#define TM6010_REQ05_R32_FNO_P3 0x05, 0x32 -#define TM6010_REQ05_R33_FNO_P4 0x05, 0x33 -#define TM6010_REQ05_R34_FNO_P5 0x05, 0x34 -#define TM6010_REQ05_R35_FNO_P6 0x05, 0x35 -#define TM6010_REQ05_R36_FNO_P7 0x05, 0x36 -#define TM6010_REQ05_R37_FNO_P8 0x05, 0x37 -#define TM6010_REQ05_R38_FNO_P9 0x05, 0x38 -#define TM6010_REQ05_R30_FNO_P10 0x05, 0x39 -#define TM6010_REQ05_R30_FNO_P11 0x05, 0x3a -#define TM6010_REQ05_R30_FNO_P12 0x05, 0x3b -#define TM6010_REQ05_R30_FNO_P13 0x05, 0x3c -#define TM6010_REQ05_R30_FNO_P14 0x05, 0x3d -#define TM6010_REQ05_R30_FNO_P15 0x05, 0x3e -#define TM6010_REQ05_R40_IN_MAXPS_LOW1 0x05, 0x40 -#define TM6010_REQ05_R41_IN_MAXPS_HIGH1 0x05, 0x41 -#define TM6010_REQ05_R42_IN_MAXPS_LOW2 0x05, 0x42 -#define TM6010_REQ05_R43_IN_MAXPS_HIGH2 0x05, 0x43 -#define TM6010_REQ05_R44_IN_MAXPS_LOW3 0x05, 0x44 -#define TM6010_REQ05_R45_IN_MAXPS_HIGH3 0x05, 0x45 -#define TM6010_REQ05_R46_IN_MAXPS_LOW4 0x05, 0x46 -#define TM6010_REQ05_R47_IN_MAXPS_HIGH4 0x05, 0x47 -#define TM6010_REQ05_R48_IN_MAXPS_LOW5 0x05, 0x48 -#define TM6010_REQ05_R49_IN_MAXPS_HIGH5 0x05, 0x49 -#define TM6010_REQ05_R4A_IN_MAXPS_LOW6 0x05, 0x4a -#define TM6010_REQ05_R4B_IN_MAXPS_HIGH6 0x05, 0x4b -#define TM6010_REQ05_R4C_IN_MAXPS_LOW7 0x05, 0x4c -#define TM6010_REQ05_R4D_IN_MAXPS_HIGH7 0x05, 0x4d -#define TM6010_REQ05_R4E_IN_MAXPS_LOW8 0x05, 0x4e -#define TM6010_REQ05_R4F_IN_MAXPS_HIGH8 0x05, 0x4f -#define TM6010_REQ05_R50_IN_MAXPS_LOW9 0x05, 0x50 -#define TM6010_REQ05_R51_IN_MAXPS_HIGH9 0x05, 0x51 -#define TM6010_REQ05_R40_IN_MAXPS_LOW10 0x05, 0x52 -#define TM6010_REQ05_R41_IN_MAXPS_HIGH10 0x05, 0x53 -#define TM6010_REQ05_R40_IN_MAXPS_LOW11 0x05, 0x54 -#define TM6010_REQ05_R41_IN_MAXPS_HIGH11 0x05, 0x55 -#define TM6010_REQ05_R40_IN_MAXPS_LOW12 0x05, 0x56 -#define TM6010_REQ05_R41_IN_MAXPS_HIGH12 0x05, 0x57 -#define TM6010_REQ05_R40_IN_MAXPS_LOW13 0x05, 0x58 -#define TM6010_REQ05_R41_IN_MAXPS_HIGH13 0x05, 0x59 -#define TM6010_REQ05_R40_IN_MAXPS_LOW14 0x05, 0x5a -#define TM6010_REQ05_R41_IN_MAXPS_HIGH14 0x05, 0x5b -#define TM6010_REQ05_R40_IN_MAXPS_LOW15 0x05, 0x5c -#define TM6010_REQ05_R41_IN_MAXPS_HIGH15 0x05, 0x5d -#define TM6010_REQ05_R60_OUT_MAXPS_LOW1 0x05, 0x60 -#define TM6010_REQ05_R61_OUT_MAXPS_HIGH1 0x05, 0x61 -#define TM6010_REQ05_R62_OUT_MAXPS_LOW2 0x05, 0x62 -#define TM6010_REQ05_R63_OUT_MAXPS_HIGH2 0x05, 0x63 -#define TM6010_REQ05_R64_OUT_MAXPS_LOW3 0x05, 0x64 -#define TM6010_REQ05_R65_OUT_MAXPS_HIGH3 0x05, 0x65 -#define TM6010_REQ05_R66_OUT_MAXPS_LOW4 0x05, 0x66 -#define TM6010_REQ05_R67_OUT_MAXPS_HIGH4 0x05, 0x67 -#define TM6010_REQ05_R68_OUT_MAXPS_LOW5 0x05, 0x68 -#define TM6010_REQ05_R69_OUT_MAXPS_HIGH5 0x05, 0x69 -#define TM6010_REQ05_R6A_OUT_MAXPS_LOW6 0x05, 0x6a -#define TM6010_REQ05_R6B_OUT_MAXPS_HIGH6 0x05, 0x6b -#define TM6010_REQ05_R6C_OUT_MAXPS_LOW7 0x05, 0x6c -#define TM6010_REQ05_R6D_OUT_MAXPS_HIGH7 0x05, 0x6d -#define TM6010_REQ05_R6E_OUT_MAXPS_LOW8 0x05, 0x6e -#define TM6010_REQ05_R6F_OUT_MAXPS_HIGH8 0x05, 0x6f -#define TM6010_REQ05_R70_OUT_MAXPS_LOW9 0x05, 0x70 -#define TM6010_REQ05_R71_OUT_MAXPS_HIGH9 0x05, 0x71 -#define TM6010_REQ05_R60_OUT_MAXPS_LOW10 0x05, 0x72 -#define TM6010_REQ05_R61_OUT_MAXPS_HIGH10 0x05, 0x73 -#define TM6010_REQ05_R60_OUT_MAXPS_LOW11 0x05, 0x74 -#define TM6010_REQ05_R61_OUT_MAXPS_HIGH11 0x05, 0x75 -#define TM6010_REQ05_R60_OUT_MAXPS_LOW12 0x05, 0x76 -#define TM6010_REQ05_R61_OUT_MAXPS_HIGH12 0x05, 0x77 -#define TM6010_REQ05_R60_OUT_MAXPS_LOW13 0x05, 0x78 -#define TM6010_REQ05_R61_OUT_MAXPS_HIGH13 0x05, 0x79 -#define TM6010_REQ05_R60_OUT_MAXPS_LOW14 0x05, 0x7a -#define TM6010_REQ05_R61_OUT_MAXPS_HIGH14 0x05, 0x7b -#define TM6010_REQ05_R60_OUT_MAXPS_LOW15 0x05, 0x7c -#define TM6010_REQ05_R61_OUT_MAXPS_HIGH15 0x05, 0x7d -#define TM6010_REQ05_R80_FIFO0 0x05, 0x80 -#define TM6010_REQ05_R81_FIFO1 0x05, 0x81 -#define TM6010_REQ05_R82_FIFO2 0x05, 0x82 -#define TM6010_REQ05_R83_FIFO3 0x05, 0x83 -#define TM6010_REQ05_R84_FIFO4 0x05, 0x84 -#define TM6010_REQ05_R85_FIFO5 0x05, 0x85 -#define TM6010_REQ05_R86_FIFO6 0x05, 0x86 -#define TM6010_REQ05_R87_FIFO7 0x05, 0x87 -#define TM6010_REQ05_R88_FIFO8 0x05, 0x88 -#define TM6010_REQ05_R89_FIFO9 0x05, 0x89 -#define TM6010_REQ05_R81_FIFO10 0x05, 0x8a -#define TM6010_REQ05_R81_FIFO11 0x05, 0x8b -#define TM6010_REQ05_R81_FIFO12 0x05, 0x8c -#define TM6010_REQ05_R81_FIFO13 0x05, 0x8d -#define TM6010_REQ05_R81_FIFO14 0x05, 0x8e -#define TM6010_REQ05_R81_FIFO15 0x05, 0x8f -#define TM6010_REQ05_R90_CFG_FIFO0 0x05, 0x90 -#define TM6010_REQ05_R91_CFG_FIFO1 0x05, 0x91 -#define TM6010_REQ05_R92_CFG_FIFO2 0x05, 0x92 -#define TM6010_REQ05_R93_CFG_FIFO3 0x05, 0x93 -#define TM6010_REQ05_R94_CFG_FIFO4 0x05, 0x94 -#define TM6010_REQ05_R95_CFG_FIFO5 0x05, 0x95 -#define TM6010_REQ05_R96_CFG_FIFO6 0x05, 0x96 -#define TM6010_REQ05_R97_CFG_FIFO7 0x05, 0x97 -#define TM6010_REQ05_R98_CFG_FIFO8 0x05, 0x98 -#define TM6010_REQ05_R99_CFG_FIFO9 0x05, 0x99 -#define TM6010_REQ05_R91_CFG_FIFO10 0x05, 0x9a -#define TM6010_REQ05_R91_CFG_FIFO11 0x05, 0x9b -#define TM6010_REQ05_R91_CFG_FIFO12 0x05, 0x9c -#define TM6010_REQ05_R91_CFG_FIFO13 0x05, 0x9d -#define TM6010_REQ05_R91_CFG_FIFO14 0x05, 0x9e -#define TM6010_REQ05_R91_CFG_FIFO15 0x05, 0x9f -#define TM6010_REQ05_RA0_CTL_FIFO0 0x05, 0xa0 -#define TM6010_REQ05_RA1_CTL_FIFO1 0x05, 0xa1 -#define TM6010_REQ05_RA2_CTL_FIFO2 0x05, 0xa2 -#define TM6010_REQ05_RA3_CTL_FIFO3 0x05, 0xa3 -#define TM6010_REQ05_RA4_CTL_FIFO4 0x05, 0xa4 -#define TM6010_REQ05_RA5_CTL_FIFO5 0x05, 0xa5 -#define TM6010_REQ05_RA6_CTL_FIFO6 0x05, 0xa6 -#define TM6010_REQ05_RA7_CTL_FIFO7 0x05, 0xa7 -#define TM6010_REQ05_RA8_CTL_FIFO8 0x05, 0xa8 -#define TM6010_REQ05_RA9_CTL_FIFO9 0x05, 0xa9 -#define TM6010_REQ05_RA1_CTL_FIFO10 0x05, 0xaa -#define TM6010_REQ05_RA1_CTL_FIFO11 0x05, 0xab -#define TM6010_REQ05_RA1_CTL_FIFO12 0x05, 0xac -#define TM6010_REQ05_RA1_CTL_FIFO13 0x05, 0xad -#define TM6010_REQ05_RA1_CTL_FIFO14 0x05, 0xae -#define TM6010_REQ05_RA1_CTL_FIFO15 0x05, 0xaf -#define TM6010_REQ05_RB0_BC_LOW_FIFO0 0x05, 0xb0 -#define TM6010_REQ05_RB1_BC_LOW_FIFO1 0x05, 0xb1 -#define TM6010_REQ05_RB2_BC_LOW_FIFO2 0x05, 0xb2 -#define TM6010_REQ05_RB3_BC_LOW_FIFO3 0x05, 0xb3 -#define TM6010_REQ05_RB4_BC_LOW_FIFO4 0x05, 0xb4 -#define TM6010_REQ05_RB5_BC_LOW_FIFO5 0x05, 0xb5 -#define TM6010_REQ05_RB6_BC_LOW_FIFO6 0x05, 0xb6 -#define TM6010_REQ05_RB7_BC_LOW_FIFO7 0x05, 0xb7 -#define TM6010_REQ05_RB8_BC_LOW_FIFO8 0x05, 0xb8 -#define TM6010_REQ05_RB9_BC_LOW_FIFO9 0x05, 0xb9 -#define TM6010_REQ05_RB1_BC_LOW_FIFO10 0x05, 0xba -#define TM6010_REQ05_RB1_BC_LOW_FIFO11 0x05, 0xbb -#define TM6010_REQ05_RB1_BC_LOW_FIFO12 0x05, 0xbc -#define TM6010_REQ05_RB1_BC_LOW_FIFO13 0x05, 0xbd -#define TM6010_REQ05_RB1_BC_LOW_FIFO14 0x05, 0xbe -#define TM6010_REQ05_RB1_BC_LOW_FIFO15 0x05, 0xbf -#define TM6010_REQ05_RC0_DATA_FIFO0 0x05, 0xc0 -#define TM6010_REQ05_RC4_DATA_FIFO1 0x05, 0xc4 -#define TM6010_REQ05_RC8_DATA_FIFO2 0x05, 0xc8 -#define TM6010_REQ05_RCC_DATA_FIFO3 0x05, 0xcc -#define TM6010_REQ05_RD0_DATA_FIFO4 0x05, 0xd0 -#define TM6010_REQ05_RD4_DATA_FIFO5 0x05, 0xd4 -#define TM6010_REQ05_RD8_DATA_FIFO6 0x05, 0xd8 -#define TM6010_REQ05_RDC_DATA_FIFO7 0x05, 0xdc -#define TM6010_REQ05_RE0_DATA_FIFO8 0x05, 0xe0 -#define TM6010_REQ05_RE4_DATA_FIFO9 0x05, 0xe4 -#define TM6010_REQ05_RC4_DATA_FIFO10 0x05, 0xe8 -#define TM6010_REQ05_RC4_DATA_FIFO11 0x05, 0xec -#define TM6010_REQ05_RC4_DATA_FIFO12 0x05, 0xf0 -#define TM6010_REQ05_RC4_DATA_FIFO13 0x05, 0xf4 -#define TM6010_REQ05_RC4_DATA_FIFO14 0x05, 0xf8 -#define TM6010_REQ05_RC4_DATA_FIFO15 0x05, 0xfc - -/* Define TM6010 Audio decoder registers */ -/* This core available only in TM6010 */ -#define TM6010_REQ08_R00_A_VERSION 0x08, 0x00 -#define TM6010_REQ08_R01_A_INIT 0x08, 0x01 -#define TM6010_REQ08_R02_A_FIX_GAIN_CTRL 0x08, 0x02 -#define TM6010_REQ08_R03_A_AUTO_GAIN_CTRL 0x08, 0x03 -#define TM6010_REQ08_R04_A_SIF_AMP_CTRL 0x08, 0x04 -#define TM6010_REQ08_R05_A_STANDARD_MOD 0x08, 0x05 -#define TM6010_REQ08_R06_A_SOUND_MOD 0x08, 0x06 -#define TM6010_REQ08_R07_A_LEFT_VOL 0x08, 0x07 -#define TM6010_REQ08_R08_A_RIGHT_VOL 0x08, 0x08 -#define TM6010_REQ08_R09_A_MAIN_VOL 0x08, 0x09 -#define TM6010_REQ08_R0A_A_I2S_MOD 0x08, 0x0a -#define TM6010_REQ08_R0B_A_ASD_THRES1 0x08, 0x0b -#define TM6010_REQ08_R0C_A_ASD_THRES2 0x08, 0x0c -#define TM6010_REQ08_R0D_A_AMD_THRES 0x08, 0x0d -#define TM6010_REQ08_R0E_A_MONO_THRES1 0x08, 0x0e -#define TM6010_REQ08_R0F_A_MONO_THRES2 0x08, 0x0f -#define TM6010_REQ08_R10_A_MUTE_THRES1 0x08, 0x10 -#define TM6010_REQ08_R11_A_MUTE_THRES2 0x08, 0x11 -#define TM6010_REQ08_R12_A_AGC_U 0x08, 0x12 -#define TM6010_REQ08_R13_A_AGC_ERR_T 0x08, 0x13 -#define TM6010_REQ08_R14_A_AGC_GAIN_INIT 0x08, 0x14 -#define TM6010_REQ08_R15_A_AGC_STEP_THR 0x08, 0x15 -#define TM6010_REQ08_R16_A_AGC_GAIN_MAX 0x08, 0x16 -#define TM6010_REQ08_R17_A_AGC_GAIN_MIN 0x08, 0x17 -#define TM6010_REQ08_R18_A_TR_CTRL 0x08, 0x18 -#define TM6010_REQ08_R19_A_FH_2FH_GAIN 0x08, 0x19 -#define TM6010_REQ08_R1A_A_NICAM_SER_MAX 0x08, 0x1a -#define TM6010_REQ08_R1B_A_NICAM_SER_MIN 0x08, 0x1b -#define TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT 0x08, 0x1e -#define TM6010_REQ08_R1F_A_TEST_INTF_SEL 0x08, 0x1f -#define TM6010_REQ08_R20_A_TEST_PIN_SEL 0x08, 0x20 -#define TM6010_REQ08_R21_A_AGC_ERR 0x08, 0x21 -#define TM6010_REQ08_R22_A_AGC_GAIN 0x08, 0x22 -#define TM6010_REQ08_R23_A_NICAM_INFO 0x08, 0x23 -#define TM6010_REQ08_R24_A_SER 0x08, 0x24 -#define TM6010_REQ08_R25_A_C1_AMP 0x08, 0x25 -#define TM6010_REQ08_R26_A_C2_AMP 0x08, 0x26 -#define TM6010_REQ08_R27_A_NOISE_AMP 0x08, 0x27 -#define TM6010_REQ08_R28_A_AUDIO_MODE_RES 0x08, 0x28 - -/* Define TM6010 Video ADC registers */ -#define TM6010_REQ08_RE0_ADC_REF 0x08, 0xe0 -#define TM6010_REQ08_RE1_DAC_CLMP 0x08, 0xe1 -#define TM6010_REQ08_RE2_POWER_DOWN_CTRL1 0x08, 0xe2 -#define TM6010_REQ08_RE3_ADC_IN1_SEL 0x08, 0xe3 -#define TM6010_REQ08_RE4_ADC_IN2_SEL 0x08, 0xe4 -#define TM6010_REQ08_RE5_GAIN_PARAM 0x08, 0xe5 -#define TM6010_REQ08_RE6_POWER_DOWN_CTRL2 0x08, 0xe6 -#define TM6010_REQ08_RE7_REG_GAIN_Y 0x08, 0xe7 -#define TM6010_REQ08_RE8_REG_GAIN_C 0x08, 0xe8 -#define TM6010_REQ08_RE9_BIAS_CTRL 0x08, 0xe9 -#define TM6010_REQ08_REA_BUFF_DRV_CTRL 0x08, 0xea -#define TM6010_REQ08_REB_SIF_GAIN_CTRL 0x08, 0xeb -#define TM6010_REQ08_REC_REVERSE_YC_CTRL 0x08, 0xec -#define TM6010_REQ08_RED_GAIN_SEL 0x08, 0xed - -/* Define TM6010 Audio ADC registers */ -#define TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG 0x08, 0xf0 -#define TM6010_REQ08_RF1_AADC_POWER_DOWN 0x08, 0xf1 -#define TM6010_REQ08_RF2_LEFT_CHANNEL_VOL 0x08, 0xf2 -#define TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL 0x08, 0xf3 diff --git a/drivers/media/video/tm6000/tm6000-stds.c b/drivers/media/video/tm6000/tm6000-stds.c deleted file mode 100644 index 5e28d6a2412f..000000000000 --- a/drivers/media/video/tm6000/tm6000-stds.c +++ /dev/null @@ -1,638 +0,0 @@ -/* - * tm6000-stds.c - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2007 Mauro Carvalho Chehab <mchehab@redhat.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include "tm6000.h" -#include "tm6000-regs.h" - -static unsigned int tm6010_a_mode; -module_param(tm6010_a_mode, int, 0644); -MODULE_PARM_DESC(tm6010_a_mode, "set tm6010 sif audio mode"); - -struct tm6000_reg_settings { - unsigned char req; - unsigned char reg; - unsigned char value; -}; - - -struct tm6000_std_settings { - v4l2_std_id id; - struct tm6000_reg_settings *common; -}; - -static struct tm6000_reg_settings composite_pal_m[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x04 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83 }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0 }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x20 }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f }, - { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_reg_settings composite_pal_nc[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x36 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91 }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f }, - { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_reg_settings composite_pal[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x32 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25 }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5 }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63 }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50 }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f }, - { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_reg_settings composite_secam[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x38 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24 }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92 }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8 }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18 }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xff }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_reg_settings composite_ntsc[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f }, - { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_std_settings composite_stds[] = { - { .id = V4L2_STD_PAL_M, .common = composite_pal_m, }, - { .id = V4L2_STD_PAL_Nc, .common = composite_pal_nc, }, - { .id = V4L2_STD_PAL, .common = composite_pal, }, - { .id = V4L2_STD_SECAM, .common = composite_secam, }, - { .id = V4L2_STD_NTSC, .common = composite_ntsc, }, -}; - -static struct tm6000_reg_settings svideo_pal_m[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x05 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83 }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0 }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f }, - { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_reg_settings svideo_pal_nc[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x37 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91 }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f }, - { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_reg_settings svideo_pal[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x33 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25 }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5 }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63 }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50 }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f }, - { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_reg_settings svideo_secam[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x39 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24 }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92 }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8 }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18 }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xff }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_reg_settings svideo_ntsc[] = { - { TM6010_REQ07_R3F_RESET, 0x01 }, - { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x01 }, - { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f }, - { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f }, - { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03 }, - { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30 }, - { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0x8b }, - { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e }, - { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b }, - { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 }, - { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 }, - { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c }, - { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc }, - { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc }, - { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd }, - { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 }, - { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 }, - { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 }, - { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c }, - { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c }, - { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 }, - { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f }, - { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd }, - { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 }, - { TM6010_REQ07_R3F_RESET, 0x00 }, - { 0, 0, 0 } -}; - -static struct tm6000_std_settings svideo_stds[] = { - { .id = V4L2_STD_PAL_M, .common = svideo_pal_m, }, - { .id = V4L2_STD_PAL_Nc, .common = svideo_pal_nc, }, - { .id = V4L2_STD_PAL, .common = svideo_pal, }, - { .id = V4L2_STD_SECAM, .common = svideo_secam, }, - { .id = V4L2_STD_NTSC, .common = svideo_ntsc, }, -}; - -static int tm6000_set_audio_std(struct tm6000_core *dev) -{ - uint8_t areg_02 = 0x04; /* GC1 Fixed gain 0dB */ - uint8_t areg_05 = 0x01; /* Auto 4.5 = M Japan, Auto 6.5 = DK */ - uint8_t areg_06 = 0x02; /* Auto de-emphasis, mannual channel mode */ - - if (dev->radio) { - tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, 0x04); - tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0x80); - tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, 0x0c); - /* set mono or stereo */ - if (dev->amode == V4L2_TUNER_MODE_MONO) - tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x00); - else if (dev->amode == V4L2_TUNER_MODE_STEREO) - tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x02); - tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x18); - tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x0a); - tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x40); - tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe); - tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13); - tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80); - tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0xff); - return 0; - } - - /* - * STD/MN shouldn't be affected by tm6010_a_mode, as there's just one - * audio standard for each V4L2_STD type. - */ - if ((dev->norm & V4L2_STD_NTSC) == V4L2_STD_NTSC_M_KR) { - areg_05 |= 0x04; - } else if ((dev->norm & V4L2_STD_NTSC) == V4L2_STD_NTSC_M_JP) { - areg_05 |= 0x43; - } else if (dev->norm & V4L2_STD_MN) { - areg_05 |= 0x22; - } else switch (tm6010_a_mode) { - /* auto */ - case 0: - if ((dev->norm & V4L2_STD_SECAM) == V4L2_STD_SECAM_L) - areg_05 |= 0x00; - else /* Other PAL/SECAM standards */ - areg_05 |= 0x10; - break; - /* A2 */ - case 1: - if (dev->norm & V4L2_STD_DK) - areg_05 = 0x09; - else - areg_05 = 0x05; - break; - /* NICAM */ - case 2: - if (dev->norm & V4L2_STD_DK) { - areg_05 = 0x06; - } else if (dev->norm & V4L2_STD_PAL_I) { - areg_05 = 0x08; - } else if (dev->norm & V4L2_STD_SECAM_L) { - areg_05 = 0x0a; - areg_02 = 0x02; - } else { - areg_05 = 0x07; - } - break; - /* other */ - case 3: - if (dev->norm & V4L2_STD_DK) { - areg_05 = 0x0b; - } else { - areg_05 = 0x02; - } - break; - } - - tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, areg_02); - tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0xa0); - tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, areg_05); - tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, areg_06); - tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x08); - tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, 0x91); - tm6000_set_reg(dev, TM6010_REQ08_R0B_A_ASD_THRES1, 0x20); - tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x12); - tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x20); - tm6000_set_reg(dev, TM6010_REQ08_R0E_A_MONO_THRES1, 0xf0); - tm6000_set_reg(dev, TM6010_REQ08_R0F_A_MONO_THRES2, 0x80); - tm6000_set_reg(dev, TM6010_REQ08_R10_A_MUTE_THRES1, 0xc0); - tm6000_set_reg(dev, TM6010_REQ08_R11_A_MUTE_THRES2, 0x80); - tm6000_set_reg(dev, TM6010_REQ08_R12_A_AGC_U, 0x12); - tm6000_set_reg(dev, TM6010_REQ08_R13_A_AGC_ERR_T, 0xfe); - tm6000_set_reg(dev, TM6010_REQ08_R14_A_AGC_GAIN_INIT, 0x20); - tm6000_set_reg(dev, TM6010_REQ08_R15_A_AGC_STEP_THR, 0x14); - tm6000_set_reg(dev, TM6010_REQ08_R16_A_AGC_GAIN_MAX, 0xfe); - tm6000_set_reg(dev, TM6010_REQ08_R17_A_AGC_GAIN_MIN, 0x01); - tm6000_set_reg(dev, TM6010_REQ08_R18_A_TR_CTRL, 0xa0); - tm6000_set_reg(dev, TM6010_REQ08_R19_A_FH_2FH_GAIN, 0x32); - tm6000_set_reg(dev, TM6010_REQ08_R1A_A_NICAM_SER_MAX, 0x64); - tm6000_set_reg(dev, TM6010_REQ08_R1B_A_NICAM_SER_MIN, 0x20); - tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1c, 0x00); - tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1d, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13); - tm6000_set_reg(dev, TM6010_REQ08_R1F_A_TEST_INTF_SEL, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R20_A_TEST_PIN_SEL, 0x00); - tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80); - - return 0; -} - -void tm6000_get_std_res(struct tm6000_core *dev) -{ - /* Currently, those are the only supported resoltions */ - if (dev->norm & V4L2_STD_525_60) - dev->height = 480; - else - dev->height = 576; - - dev->width = 720; -} - -static int tm6000_load_std(struct tm6000_core *dev, struct tm6000_reg_settings *set) -{ - int i, rc; - - /* Load board's initialization table */ - for (i = 0; set[i].req; i++) { - rc = tm6000_set_reg(dev, set[i].req, set[i].reg, set[i].value); - if (rc < 0) { - printk(KERN_ERR "Error %i while setting " - "req %d, reg %d to value %d\n", - rc, set[i].req, set[i].reg, set[i].value); - return rc; - } - } - - return 0; -} - -int tm6000_set_standard(struct tm6000_core *dev) -{ - struct tm6000_input *input; - int i, rc = 0; - u8 reg_07_fe = 0x8a; - u8 reg_08_f1 = 0xfc; - u8 reg_08_e2 = 0xf0; - u8 reg_08_e6 = 0x0f; - - tm6000_get_std_res(dev); - - if (!dev->radio) - input = &dev->vinput[dev->input]; - else - input = &dev->rinput; - - if (dev->dev_type == TM6010) { - switch (input->vmux) { - case TM6000_VMUX_VIDEO_A: - tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4); - tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1); - tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0); - tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2); - tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe8); - reg_07_fe |= 0x01; - break; - case TM6000_VMUX_VIDEO_B: - tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8); - tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1); - tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0); - tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2); - tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe8); - reg_07_fe |= 0x01; - break; - case TM6000_VMUX_VIDEO_AB: - tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc); - tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8); - reg_08_e6 = 0x00; - tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2); - tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0); - tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2); - tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe0); - break; - default: - break; - } - switch (input->amux) { - case TM6000_AMUX_ADC1: - tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, - 0x00, 0x0f); - /* Mux overflow workaround */ - tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL, - 0x10, 0xf0); - break; - case TM6000_AMUX_ADC2: - tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, - 0x08, 0x0f); - /* Mux overflow workaround */ - tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL, - 0x10, 0xf0); - break; - case TM6000_AMUX_SIF1: - reg_08_e2 |= 0x02; - reg_08_e6 = 0x08; - reg_07_fe |= 0x40; - reg_08_f1 |= 0x02; - tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3); - tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, - 0x02, 0x0f); - /* Mux overflow workaround */ - tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL, - 0x30, 0xf0); - break; - case TM6000_AMUX_SIF2: - reg_08_e2 |= 0x02; - reg_08_e6 = 0x08; - reg_07_fe |= 0x40; - reg_08_f1 |= 0x02; - tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf7); - tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, - 0x02, 0x0f); - /* Mux overflow workaround */ - tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL, - 0x30, 0xf0); - break; - default: - break; - } - tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, reg_08_e2); - tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, reg_08_e6); - tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, reg_08_f1); - tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, reg_07_fe); - } else { - switch (input->vmux) { - case TM6000_VMUX_VIDEO_A: - tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10); - tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00); - tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x0f); - tm6000_set_reg(dev, - REQ_03_SET_GET_MCU_PIN, input->v_gpio, 0); - break; - case TM6000_VMUX_VIDEO_B: - tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x00); - tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00); - tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x0f); - tm6000_set_reg(dev, - REQ_03_SET_GET_MCU_PIN, input->v_gpio, 0); - break; - case TM6000_VMUX_VIDEO_AB: - tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10); - tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x10); - tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00); - tm6000_set_reg(dev, - REQ_03_SET_GET_MCU_PIN, input->v_gpio, 1); - break; - default: - break; - } - switch (input->amux) { - case TM6000_AMUX_ADC1: - tm6000_set_reg_mask(dev, - TM6000_REQ07_REB_VADC_AADC_MODE, 0x00, 0x0f); - break; - case TM6000_AMUX_ADC2: - tm6000_set_reg_mask(dev, - TM6000_REQ07_REB_VADC_AADC_MODE, 0x04, 0x0f); - break; - default: - break; - } - } - if (input->type == TM6000_INPUT_SVIDEO) { - for (i = 0; i < ARRAY_SIZE(svideo_stds); i++) { - if (dev->norm & svideo_stds[i].id) { - rc = tm6000_load_std(dev, svideo_stds[i].common); - goto ret; - } - } - return -EINVAL; - } else { - for (i = 0; i < ARRAY_SIZE(composite_stds); i++) { - if (dev->norm & composite_stds[i].id) { - rc = tm6000_load_std(dev, composite_stds[i].common); - goto ret; - } - } - return -EINVAL; - } - -ret: - if (rc < 0) - return rc; - - if ((dev->dev_type == TM6010) && - ((input->amux == TM6000_AMUX_SIF1) || - (input->amux == TM6000_AMUX_SIF2))) - tm6000_set_audio_std(dev); - - msleep(40); - - return 0; -} diff --git a/drivers/media/video/tm6000/tm6000-usb-isoc.h b/drivers/media/video/tm6000/tm6000-usb-isoc.h deleted file mode 100644 index 99d15a55aa03..000000000000 --- a/drivers/media/video/tm6000/tm6000-usb-isoc.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * tm6000-buf.c - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/videodev2.h> - -#define TM6000_URB_MSG_LEN 180 - -struct usb_isoc_ctl { - /* max packet size of isoc transaction */ - int max_pkt_size; - - /* number of allocated urbs */ - int num_bufs; - - /* urb for isoc transfers */ - struct urb **urb; - - /* transfer buffers for isoc transfer */ - char **transfer_buffer; - - /* Last buffer command and region */ - u8 cmd; - int pos, size, pktsize; - - /* Last field: ODD or EVEN? */ - int vfield, field; - - /* Stores incomplete commands */ - u32 tmp_buf; - int tmp_buf_len; - - /* Stores already requested buffers */ - struct tm6000_buffer *buf; -}; diff --git a/drivers/media/video/tm6000/tm6000-video.c b/drivers/media/video/tm6000/tm6000-video.c deleted file mode 100644 index 45ed59cb2d04..000000000000 --- a/drivers/media/video/tm6000/tm6000-video.c +++ /dev/null @@ -1,1852 +0,0 @@ -/* - * tm6000-video.c - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> - * - * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com> - * - Fixed module load/unload - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/sched.h> -#include <linux/random.h> -#include <linux/usb.h> -#include <linux/videodev2.h> -#include <media/v4l2-ioctl.h> -#include <media/tuner.h> -#include <linux/interrupt.h> -#include <linux/kthread.h> -#include <linux/highmem.h> -#include <linux/freezer.h> - -#include "tm6000-regs.h" -#include "tm6000.h" - -#define BUFFER_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ - -/* Limits minimum and default number of buffers */ -#define TM6000_MIN_BUF 4 -#define TM6000_DEF_BUF 8 - -#define TM6000_MAX_ISO_PACKETS 46 /* Max number of ISO packets */ - -/* Declare static vars that will be used as parameters */ -static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ -static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ -static int radio_nr = -1; /* /dev/radioN, -1 for autodetect */ - -/* Debug level */ -int tm6000_debug; -EXPORT_SYMBOL_GPL(tm6000_debug); - -static const struct v4l2_queryctrl no_ctrl = { - .name = "42", - .flags = V4L2_CTRL_FLAG_DISABLED, -}; - -/* supported controls */ -static struct v4l2_queryctrl tm6000_qctrl[] = { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, - .maximum = 255, - .step = 1, - .default_value = 54, - .flags = 0, - }, { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0, - .maximum = 255, - .step = 0x1, - .default_value = 119, - .flags = 0, - }, { - .id = V4L2_CID_SATURATION, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Saturation", - .minimum = 0, - .maximum = 255, - .step = 0x1, - .default_value = 112, - .flags = 0, - }, { - .id = V4L2_CID_HUE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Hue", - .minimum = -128, - .maximum = 127, - .step = 0x1, - .default_value = 0, - .flags = 0, - }, - /* --- audio --- */ - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - }, { - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = -15, - .maximum = 15, - .step = 1, - .default_value = 0, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; - -static const unsigned int CTRLS = ARRAY_SIZE(tm6000_qctrl); -static int qctl_regs[ARRAY_SIZE(tm6000_qctrl)]; - -static struct tm6000_fmt format[] = { - { - .name = "4:2:2, packed, YVY2", - .fourcc = V4L2_PIX_FMT_YUYV, - .depth = 16, - }, { - .name = "4:2:2, packed, UYVY", - .fourcc = V4L2_PIX_FMT_UYVY, - .depth = 16, - }, { - .name = "A/V + VBI mux packet", - .fourcc = V4L2_PIX_FMT_TM6000, - .depth = 16, - } -}; - -static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id) -{ - unsigned int i; - - for (i = 0; i < CTRLS; i++) - if (tm6000_qctrl[i].id == id) - return tm6000_qctrl+i; - return NULL; -} - -/* ------------------------------------------------------------------ - * DMA and thread functions - * ------------------------------------------------------------------ - */ - -#define norm_maxw(a) 720 -#define norm_maxh(a) 576 - -#define norm_minw(a) norm_maxw(a) -#define norm_minh(a) norm_maxh(a) - -/* - * video-buf generic routine to get the next available buffer - */ -static inline void get_next_buf(struct tm6000_dmaqueue *dma_q, - struct tm6000_buffer **buf) -{ - struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq); - - if (list_empty(&dma_q->active)) { - dprintk(dev, V4L2_DEBUG_QUEUE, "No active queue to serve\n"); - *buf = NULL; - return; - } - - *buf = list_entry(dma_q->active.next, - struct tm6000_buffer, vb.queue); -} - -/* - * Announces that a buffer were filled and request the next - */ -static inline void buffer_filled(struct tm6000_core *dev, - struct tm6000_dmaqueue *dma_q, - struct tm6000_buffer *buf) -{ - /* Advice that buffer was filled */ - dprintk(dev, V4L2_DEBUG_ISOC, "[%p/%d] wakeup\n", buf, buf->vb.i); - buf->vb.state = VIDEOBUF_DONE; - buf->vb.field_count++; - do_gettimeofday(&buf->vb.ts); - - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); -} - -/* - * Identify the tm5600/6000 buffer header type and properly handles - */ -static int copy_streams(u8 *data, unsigned long len, - struct urb *urb) -{ - struct tm6000_dmaqueue *dma_q = urb->context; - struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq); - u8 *ptr = data, *endp = data+len; - unsigned long header = 0; - int rc = 0; - unsigned int cmd, cpysize, pktsize, size, field, block, line, pos = 0; - struct tm6000_buffer *vbuf = NULL; - char *voutp = NULL; - unsigned int linewidth; - - if (!dev->radio) { - /* get video buffer */ - get_next_buf(dma_q, &vbuf); - - if (!vbuf) - return rc; - voutp = videobuf_to_vmalloc(&vbuf->vb); - - if (!voutp) - return 0; - } - - for (ptr = data; ptr < endp;) { - if (!dev->isoc_ctl.cmd) { - /* Header */ - if (dev->isoc_ctl.tmp_buf_len > 0) { - /* from last urb or packet */ - header = dev->isoc_ctl.tmp_buf; - if (4 - dev->isoc_ctl.tmp_buf_len > 0) { - memcpy((u8 *)&header + - dev->isoc_ctl.tmp_buf_len, - ptr, - 4 - dev->isoc_ctl.tmp_buf_len); - ptr += 4 - dev->isoc_ctl.tmp_buf_len; - } - dev->isoc_ctl.tmp_buf_len = 0; - } else { - if (ptr + 3 >= endp) { - /* have incomplete header */ - dev->isoc_ctl.tmp_buf_len = endp - ptr; - memcpy(&dev->isoc_ctl.tmp_buf, ptr, - dev->isoc_ctl.tmp_buf_len); - return rc; - } - /* Seek for sync */ - for (; ptr < endp - 3; ptr++) { - if (*(ptr + 3) == 0x47) - break; - } - /* Get message header */ - header = *(unsigned long *)ptr; - ptr += 4; - } - - /* split the header fields */ - size = ((header & 0x7e) << 1); - if (size > 0) - size -= 4; - block = (header >> 7) & 0xf; - field = (header >> 11) & 0x1; - line = (header >> 12) & 0x1ff; - cmd = (header >> 21) & 0x7; - /* Validates haeder fields */ - if (size > TM6000_URB_MSG_LEN) - size = TM6000_URB_MSG_LEN; - pktsize = TM6000_URB_MSG_LEN; - /* - * calculate position in buffer and change the buffer - */ - switch (cmd) { - case TM6000_URB_MSG_VIDEO: - if (!dev->radio) { - if ((dev->isoc_ctl.vfield != field) && - (field == 1)) { - /* - * Announces that a new buffer - * were filled - */ - buffer_filled(dev, dma_q, vbuf); - dprintk(dev, V4L2_DEBUG_ISOC, - "new buffer filled\n"); - get_next_buf(dma_q, &vbuf); - if (!vbuf) - return rc; - voutp = videobuf_to_vmalloc(&vbuf->vb); - if (!voutp) - return rc; - memset(voutp, 0, vbuf->vb.size); - } - linewidth = vbuf->vb.width << 1; - pos = ((line << 1) - field - 1) * - linewidth + block * TM6000_URB_MSG_LEN; - /* Don't allow to write out of the buffer */ - if (pos + size > vbuf->vb.size) - cmd = TM6000_URB_MSG_ERR; - dev->isoc_ctl.vfield = field; - } - break; - case TM6000_URB_MSG_VBI: - break; - case TM6000_URB_MSG_AUDIO: - case TM6000_URB_MSG_PTS: - size = pktsize; /* Size is always 180 bytes */ - break; - } - } else { - /* Continue the last copy */ - cmd = dev->isoc_ctl.cmd; - size = dev->isoc_ctl.size; - pos = dev->isoc_ctl.pos; - pktsize = dev->isoc_ctl.pktsize; - field = dev->isoc_ctl.field; - } - cpysize = (endp - ptr > size) ? size : endp - ptr; - if (cpysize) { - /* copy data in different buffers */ - switch (cmd) { - case TM6000_URB_MSG_VIDEO: - /* Fills video buffer */ - if (vbuf) - memcpy(&voutp[pos], ptr, cpysize); - break; - case TM6000_URB_MSG_AUDIO: { - int i; - for (i = 0; i < cpysize; i += 2) - swab16s((u16 *)(ptr + i)); - - tm6000_call_fillbuf(dev, TM6000_AUDIO, ptr, cpysize); - break; - } - case TM6000_URB_MSG_VBI: - /* Need some code to copy vbi buffer */ - break; - case TM6000_URB_MSG_PTS: { - /* Need some code to copy pts */ - u32 pts; - pts = *(u32 *)ptr; - dprintk(dev, V4L2_DEBUG_ISOC, "field %d, PTS %x", - field, pts); - break; - } - } - } - if (ptr + pktsize > endp) { - /* - * End of URB packet, but cmd processing is not - * complete. Preserve the state for a next packet - */ - dev->isoc_ctl.pos = pos + cpysize; - dev->isoc_ctl.size = size - cpysize; - dev->isoc_ctl.cmd = cmd; - dev->isoc_ctl.field = field; - dev->isoc_ctl.pktsize = pktsize - (endp - ptr); - ptr += endp - ptr; - } else { - dev->isoc_ctl.cmd = 0; - ptr += pktsize; - } - } - return 0; -} - -/* - * Identify the tm5600/6000 buffer header type and properly handles - */ -static int copy_multiplexed(u8 *ptr, unsigned long len, - struct urb *urb) -{ - struct tm6000_dmaqueue *dma_q = urb->context; - struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq); - unsigned int pos = dev->isoc_ctl.pos, cpysize; - int rc = 1; - struct tm6000_buffer *buf; - char *outp = NULL; - - get_next_buf(dma_q, &buf); - if (buf) - outp = videobuf_to_vmalloc(&buf->vb); - - if (!outp) - return 0; - - while (len > 0) { - cpysize = min(len, buf->vb.size-pos); - memcpy(&outp[pos], ptr, cpysize); - pos += cpysize; - ptr += cpysize; - len -= cpysize; - if (pos >= buf->vb.size) { - pos = 0; - /* Announces that a new buffer were filled */ - buffer_filled(dev, dma_q, buf); - dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n"); - get_next_buf(dma_q, &buf); - if (!buf) - break; - outp = videobuf_to_vmalloc(&(buf->vb)); - if (!outp) - return rc; - pos = 0; - } - } - - dev->isoc_ctl.pos = pos; - return rc; -} - -static inline void print_err_status(struct tm6000_core *dev, - int packet, int status) -{ - char *errmsg = "Unknown"; - - switch (status) { - case -ENOENT: - errmsg = "unlinked synchronuously"; - break; - case -ECONNRESET: - errmsg = "unlinked asynchronuously"; - break; - case -ENOSR: - errmsg = "Buffer error (overrun)"; - break; - case -EPIPE: - errmsg = "Stalled (device not responding)"; - break; - case -EOVERFLOW: - errmsg = "Babble (bad cable?)"; - break; - case -EPROTO: - errmsg = "Bit-stuff error (bad cable?)"; - break; - case -EILSEQ: - errmsg = "CRC/Timeout (could be anything)"; - break; - case -ETIME: - errmsg = "Device does not respond"; - break; - } - if (packet < 0) { - dprintk(dev, V4L2_DEBUG_QUEUE, "URB status %d [%s].\n", - status, errmsg); - } else { - dprintk(dev, V4L2_DEBUG_QUEUE, "URB packet %d, status %d [%s].\n", - packet, status, errmsg); - } -} - - -/* - * Controls the isoc copy of each urb packet - */ -static inline int tm6000_isoc_copy(struct urb *urb) -{ - struct tm6000_dmaqueue *dma_q = urb->context; - struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq); - int i, len = 0, rc = 1, status; - char *p; - - if (urb->status < 0) { - print_err_status(dev, -1, urb->status); - return 0; - } - - for (i = 0; i < urb->number_of_packets; i++) { - status = urb->iso_frame_desc[i].status; - - if (status < 0) { - print_err_status(dev, i, status); - continue; - } - - len = urb->iso_frame_desc[i].actual_length; - - if (len > 0) { - p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - if (!urb->iso_frame_desc[i].status) { - if ((dev->fourcc) == V4L2_PIX_FMT_TM6000) { - rc = copy_multiplexed(p, len, urb); - if (rc <= 0) - return rc; - } else { - copy_streams(p, len, urb); - } - } - } - } - return rc; -} - -/* ------------------------------------------------------------------ - * URB control - * ------------------------------------------------------------------ - */ - -/* - * IRQ callback, called by URB callback - */ -static void tm6000_irq_callback(struct urb *urb) -{ - struct tm6000_dmaqueue *dma_q = urb->context; - struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq); - int i; - - switch (urb->status) { - case 0: - case -ETIMEDOUT: - break; - - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - return; - - default: - tm6000_err("urb completion error %d.\n", urb->status); - break; - } - - spin_lock(&dev->slock); - tm6000_isoc_copy(urb); - spin_unlock(&dev->slock); - - /* Reset urb buffers */ - for (i = 0; i < urb->number_of_packets; i++) { - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = 0; - } - - urb->status = usb_submit_urb(urb, GFP_ATOMIC); - if (urb->status) - tm6000_err("urb resubmit failed (error=%i)\n", - urb->status); -} - -/* - * Stop and Deallocate URBs - */ -static void tm6000_uninit_isoc(struct tm6000_core *dev) -{ - struct urb *urb; - int i; - - dev->isoc_ctl.buf = NULL; - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - urb = dev->isoc_ctl.urb[i]; - if (urb) { - usb_kill_urb(urb); - usb_unlink_urb(urb); - if (dev->isoc_ctl.transfer_buffer[i]) { - usb_free_coherent(dev->udev, - urb->transfer_buffer_length, - dev->isoc_ctl.transfer_buffer[i], - urb->transfer_dma); - } - usb_free_urb(urb); - dev->isoc_ctl.urb[i] = NULL; - } - dev->isoc_ctl.transfer_buffer[i] = NULL; - } - - kfree(dev->isoc_ctl.urb); - kfree(dev->isoc_ctl.transfer_buffer); - - dev->isoc_ctl.urb = NULL; - dev->isoc_ctl.transfer_buffer = NULL; - dev->isoc_ctl.num_bufs = 0; -} - -/* - * Allocate URBs and start IRQ - */ -static int tm6000_prepare_isoc(struct tm6000_core *dev) -{ - struct tm6000_dmaqueue *dma_q = &dev->vidq; - int i, j, sb_size, pipe, size, max_packets, num_bufs = 8; - struct urb *urb; - - /* De-allocates all pending stuff */ - tm6000_uninit_isoc(dev); - /* Stop interrupt USB pipe */ - tm6000_ir_int_stop(dev); - - usb_set_interface(dev->udev, - dev->isoc_in.bInterfaceNumber, - dev->isoc_in.bAlternateSetting); - - /* Start interrupt USB pipe */ - tm6000_ir_int_start(dev); - - pipe = usb_rcvisocpipe(dev->udev, - dev->isoc_in.endp->desc.bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK); - - size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); - - if (size > dev->isoc_in.maxsize) - size = dev->isoc_in.maxsize; - - dev->isoc_ctl.max_pkt_size = size; - - max_packets = TM6000_MAX_ISO_PACKETS; - sb_size = max_packets * size; - - dev->isoc_ctl.num_bufs = num_bufs; - - dev->isoc_ctl.urb = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL); - if (!dev->isoc_ctl.urb) { - tm6000_err("cannot alloc memory for usb buffers\n"); - return -ENOMEM; - } - - dev->isoc_ctl.transfer_buffer = kmalloc(sizeof(void *)*num_bufs, - GFP_KERNEL); - if (!dev->isoc_ctl.transfer_buffer) { - tm6000_err("cannot allocate memory for usbtransfer\n"); - kfree(dev->isoc_ctl.urb); - return -ENOMEM; - } - - dprintk(dev, V4L2_DEBUG_QUEUE, "Allocating %d x %d packets" - " (%d bytes) of %d bytes each to handle %u size\n", - max_packets, num_bufs, sb_size, - dev->isoc_in.maxsize, size); - - /* allocate urbs and transfer buffers */ - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - urb = usb_alloc_urb(max_packets, GFP_KERNEL); - if (!urb) { - tm6000_err("cannot alloc isoc_ctl.urb %i\n", i); - tm6000_uninit_isoc(dev); - usb_free_urb(urb); - return -ENOMEM; - } - dev->isoc_ctl.urb[i] = urb; - - dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev, - sb_size, GFP_KERNEL, &urb->transfer_dma); - if (!dev->isoc_ctl.transfer_buffer[i]) { - tm6000_err("unable to allocate %i bytes for transfer" - " buffer %i%s\n", - sb_size, i, - in_interrupt() ? " while in int" : ""); - tm6000_uninit_isoc(dev); - return -ENOMEM; - } - memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); - - usb_fill_bulk_urb(urb, dev->udev, pipe, - dev->isoc_ctl.transfer_buffer[i], sb_size, - tm6000_irq_callback, dma_q); - urb->interval = dev->isoc_in.endp->desc.bInterval; - urb->number_of_packets = max_packets; - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - - for (j = 0; j < max_packets; j++) { - urb->iso_frame_desc[j].offset = size * j; - urb->iso_frame_desc[j].length = size; - } - } - - return 0; -} - -static int tm6000_start_thread(struct tm6000_core *dev) -{ - struct tm6000_dmaqueue *dma_q = &dev->vidq; - int i; - - dma_q->frame = 0; - dma_q->ini_jiffies = jiffies; - - init_waitqueue_head(&dma_q->wq); - - /* submit urbs and enables IRQ */ - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { - int rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); - if (rc) { - tm6000_err("submit of urb %i failed (error=%i)\n", i, - rc); - tm6000_uninit_isoc(dev); - return rc; - } - } - - return 0; -} - -/* ------------------------------------------------------------------ - * Videobuf operations - * ------------------------------------------------------------------ - */ - -static int -buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) -{ - struct tm6000_fh *fh = vq->priv_data; - - *size = fh->fmt->depth * fh->width * fh->height >> 3; - if (0 == *count) - *count = TM6000_DEF_BUF; - - if (*count < TM6000_MIN_BUF) - *count = TM6000_MIN_BUF; - - while (*size * *count > vid_limit * 1024 * 1024) - (*count)--; - - return 0; -} - -static void free_buffer(struct videobuf_queue *vq, struct tm6000_buffer *buf) -{ - struct tm6000_fh *fh = vq->priv_data; - struct tm6000_core *dev = fh->dev; - unsigned long flags; - - if (in_interrupt()) - BUG(); - - /* We used to wait for the buffer to finish here, but this didn't work - because, as we were keeping the state as VIDEOBUF_QUEUED, - videobuf_queue_cancel marked it as finished for us. - (Also, it could wedge forever if the hardware was misconfigured.) - - This should be safe; by the time we get here, the buffer isn't - queued anymore. If we ever start marking the buffers as - VIDEOBUF_ACTIVE, it won't be, though. - */ - spin_lock_irqsave(&dev->slock, flags); - if (dev->isoc_ctl.buf == buf) - dev->isoc_ctl.buf = NULL; - spin_unlock_irqrestore(&dev->slock, flags); - - videobuf_vmalloc_free(&buf->vb); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int -buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct tm6000_fh *fh = vq->priv_data; - struct tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb); - struct tm6000_core *dev = fh->dev; - int rc = 0; - - BUG_ON(NULL == fh->fmt); - - - /* FIXME: It assumes depth=2 */ - /* The only currently supported format is 16 bits/pixel */ - buf->vb.size = fh->fmt->depth*fh->width*fh->height >> 3; - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - if (buf->fmt != fh->fmt || - buf->vb.width != fh->width || - buf->vb.height != fh->height || - buf->vb.field != field) { - buf->fmt = fh->fmt; - buf->vb.width = fh->width; - buf->vb.height = fh->height; - buf->vb.field = field; - buf->vb.state = VIDEOBUF_NEEDS_INIT; - } - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - rc = videobuf_iolock(vq, &buf->vb, NULL); - if (rc != 0) - goto fail; - } - - if (!dev->isoc_ctl.num_bufs) { - rc = tm6000_prepare_isoc(dev); - if (rc < 0) - goto fail; - - rc = tm6000_start_thread(dev); - if (rc < 0) - goto fail; - - } - - buf->vb.state = VIDEOBUF_PREPARED; - return 0; - -fail: - free_buffer(vq, buf); - return rc; -} - -static void -buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb); - struct tm6000_fh *fh = vq->priv_data; - struct tm6000_core *dev = fh->dev; - struct tm6000_dmaqueue *vidq = &dev->vidq; - - buf->vb.state = VIDEOBUF_QUEUED; - list_add_tail(&buf->vb.queue, &vidq->active); -} - -static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb); - - free_buffer(vq, buf); -} - -static struct videobuf_queue_ops tm6000_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, -}; - -/* ------------------------------------------------------------------ - * IOCTL handling - * ------------------------------------------------------------------ - */ - -static bool is_res_read(struct tm6000_core *dev, struct tm6000_fh *fh) -{ - /* Is the current fh handling it? if so, that's OK */ - if (dev->resources == fh && dev->is_res_read) - return true; - - return false; -} - -static bool is_res_streaming(struct tm6000_core *dev, struct tm6000_fh *fh) -{ - /* Is the current fh handling it? if so, that's OK */ - if (dev->resources == fh) - return true; - - return false; -} - -static bool res_get(struct tm6000_core *dev, struct tm6000_fh *fh, - bool is_res_read) -{ - /* Is the current fh handling it? if so, that's OK */ - if (dev->resources == fh && dev->is_res_read == is_res_read) - return true; - - /* is it free? */ - if (dev->resources) - return false; - - /* grab it */ - dev->resources = fh; - dev->is_res_read = is_res_read; - dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: get\n"); - return true; -} - -static void res_free(struct tm6000_core *dev, struct tm6000_fh *fh) -{ - /* Is the current fh handling it? if so, that's OK */ - if (dev->resources != fh) - return; - - dev->resources = NULL; - dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: put\n"); -} - -/* ------------------------------------------------------------------ - * IOCTL vidioc handling - * ------------------------------------------------------------------ - */ -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev; - - strlcpy(cap->driver, "tm6000", sizeof(cap->driver)); - strlcpy(cap->card, "Trident TVMaster TM5600/6000/6010", sizeof(cap->card)); - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_STREAMING | - V4L2_CAP_AUDIO | - V4L2_CAP_READWRITE; - - if (dev->tuner_type != TUNER_ABSENT) - cap->capabilities |= V4L2_CAP_TUNER; - - return 0; -} - -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - if (unlikely(f->index >= ARRAY_SIZE(format))) - return -EINVAL; - - strlcpy(f->description, format[f->index].name, sizeof(f->description)); - f->pixelformat = format[f->index].fourcc; - return 0; -} - -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct tm6000_fh *fh = priv; - - f->fmt.pix.width = fh->width; - f->fmt.pix.height = fh->height; - f->fmt.pix.field = fh->vb_vidq.field; - f->fmt.pix.pixelformat = fh->fmt->fourcc; - f->fmt.pix.bytesperline = - (f->fmt.pix.width * fh->fmt->depth) >> 3; - f->fmt.pix.sizeimage = - f->fmt.pix.height * f->fmt.pix.bytesperline; - - return 0; -} - -static struct tm6000_fmt *format_by_fourcc(unsigned int fourcc) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(format); i++) - if (format[i].fourcc == fourcc) - return format+i; - return NULL; -} - -static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev; - struct tm6000_fmt *fmt; - enum v4l2_field field; - - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - if (NULL == fmt) { - dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Fourcc format (0x%08x)" - " invalid.\n", f->fmt.pix.pixelformat); - return -EINVAL; - } - - field = f->fmt.pix.field; - - if (field == V4L2_FIELD_ANY) - field = V4L2_FIELD_SEQ_TB; - else if (V4L2_FIELD_INTERLACED != field) { - dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Field type invalid.\n"); - return -EINVAL; - } - - tm6000_get_std_res(dev); - - f->fmt.pix.width = dev->width; - f->fmt.pix.height = dev->height; - - f->fmt.pix.width &= ~0x01; - - f->fmt.pix.field = field; - - f->fmt.pix.bytesperline = - (f->fmt.pix.width * fmt->depth) >> 3; - f->fmt.pix.sizeimage = - f->fmt.pix.height * f->fmt.pix.bytesperline; - - return 0; -} - -/*FIXME: This seems to be generic enough to be at videodev2 */ -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - int ret = vidioc_try_fmt_vid_cap(file, fh, f); - if (ret < 0) - return ret; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - fh->vb_vidq.field = f->fmt.pix.field; - fh->type = f->type; - - dev->fourcc = f->fmt.pix.pixelformat; - - tm6000_set_fourcc_format(dev); - - return 0; -} - -static int vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *p) -{ - struct tm6000_fh *fh = priv; - - return videobuf_reqbufs(&fh->vb_vidq, p); -} - -static int vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *p) -{ - struct tm6000_fh *fh = priv; - - return videobuf_querybuf(&fh->vb_vidq, p); -} - -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct tm6000_fh *fh = priv; - - return videobuf_qbuf(&fh->vb_vidq, p); -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct tm6000_fh *fh = priv; - - return videobuf_dqbuf(&fh->vb_vidq, p, - file->f_flags & O_NONBLOCK); -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - if (!res_get(dev, fh, false)) - return -EBUSY; - return videobuf_streamon(&fh->vb_vidq); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (i != fh->type) - return -EINVAL; - - videobuf_streamoff(&fh->vb_vidq); - res_free(dev, fh); - - return 0; -} - -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) -{ - int rc = 0; - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - dev->norm = *norm; - rc = tm6000_init_analog_mode(dev); - - fh->width = dev->width; - fh->height = dev->height; - - if (rc < 0) - return rc; - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); - - return 0; -} - -static const char *iname[] = { - [TM6000_INPUT_TV] = "Television", - [TM6000_INPUT_COMPOSITE1] = "Composite 1", - [TM6000_INPUT_COMPOSITE2] = "Composite 2", - [TM6000_INPUT_SVIDEO] = "S-Video", -}; - -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *i) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - unsigned int n; - - n = i->index; - if (n >= 3) - return -EINVAL; - - if (!dev->vinput[n].type) - return -EINVAL; - - i->index = n; - - if (dev->vinput[n].type == TM6000_INPUT_TV) - i->type = V4L2_INPUT_TYPE_TUNER; - else - i->type = V4L2_INPUT_TYPE_CAMERA; - - strcpy(i->name, iname[dev->vinput[n].type]); - - i->std = TM6000_STD; - - return 0; -} - -static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - *i = dev->input; - - return 0; -} - -static int vidioc_s_input(struct file *file, void *priv, unsigned int i) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - int rc = 0; - - if (i >= 3) - return -EINVAL; - if (!dev->vinput[i].type) - return -EINVAL; - - dev->input = i; - - rc = vidioc_s_std(file, priv, &dev->vfd->current_norm); - - return rc; -} - -/* --- controls ---------------------------------------------- */ -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++) - if (qc->id && qc->id == tm6000_qctrl[i].id) { - memcpy(qc, &(tm6000_qctrl[i]), - sizeof(*qc)); - return 0; - } - - return -EINVAL; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - int val; - - /* FIXME: Probably, those won't work! Maybe we need shadow regs */ - switch (ctrl->id) { - case V4L2_CID_CONTRAST: - val = tm6000_get_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0); - break; - case V4L2_CID_BRIGHTNESS: - val = tm6000_get_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0); - return 0; - case V4L2_CID_SATURATION: - val = tm6000_get_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0); - return 0; - case V4L2_CID_HUE: - val = tm6000_get_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, 0); - return 0; - case V4L2_CID_AUDIO_MUTE: - val = dev->ctl_mute; - return 0; - case V4L2_CID_AUDIO_VOLUME: - val = dev->ctl_volume; - return 0; - default: - return -EINVAL; - } - - if (val < 0) - return val; - - ctrl->value = val; - - return 0; -} -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - u8 val = ctrl->value; - - switch (ctrl->id) { - case V4L2_CID_CONTRAST: - tm6000_set_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, val); - return 0; - case V4L2_CID_BRIGHTNESS: - tm6000_set_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, val); - return 0; - case V4L2_CID_SATURATION: - tm6000_set_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, val); - return 0; - case V4L2_CID_HUE: - tm6000_set_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, val); - return 0; - case V4L2_CID_AUDIO_MUTE: - dev->ctl_mute = val; - tm6000_tvaudio_set_mute(dev, val); - return 0; - case V4L2_CID_AUDIO_VOLUME: - dev->ctl_volume = val; - tm6000_set_volume(dev, val); - return 0; - } - return -EINVAL; -} - -static int vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (unlikely(UNSET == dev->tuner_type)) - return -EINVAL; - if (0 != t->index) - return -EINVAL; - - strcpy(t->name, "Television"); - t->type = V4L2_TUNER_ANALOG_TV; - t->capability = V4L2_TUNER_CAP_NORM; - t->rangehigh = 0xffffffffUL; - t->rxsubchans = V4L2_TUNER_SUB_STEREO; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); - - t->audmode = dev->amode; - - return 0; -} - -static int vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (UNSET == dev->tuner_type) - return -EINVAL; - if (0 != t->index) - return -EINVAL; - - dev->amode = t->audmode; - dprintk(dev, 3, "audio mode: %x\n", t->audmode); - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); - - return 0; -} - -static int vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (unlikely(UNSET == dev->tuner_type)) - return -EINVAL; - - f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - f->frequency = dev->freq; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, f); - - return 0; -} - -static int vidioc_s_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (unlikely(UNSET == dev->tuner_type)) - return -EINVAL; - if (unlikely(f->tuner != 0)) - return -EINVAL; - if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type) - return -EINVAL; - if (1 == fh->radio && V4L2_TUNER_RADIO != f->type) - return -EINVAL; - - dev->freq = f->frequency; - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f); - - return 0; -} - -static int radio_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct tm6000_fh *fh = file->private_data; - struct tm6000_core *dev = fh->dev; - - strcpy(cap->driver, "tm6000"); - strlcpy(cap->card, dev->name, sizeof(dev->name)); - sprintf(cap->bus_info, "USB%04x:%04x", - le16_to_cpu(dev->udev->descriptor.idVendor), - le16_to_cpu(dev->udev->descriptor.idProduct)); - cap->version = dev->dev_type; - cap->capabilities = V4L2_CAP_TUNER | - V4L2_CAP_AUDIO | - V4L2_CAP_RADIO | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - - return 0; -} - -static int radio_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct tm6000_fh *fh = file->private_data; - struct tm6000_core *dev = fh->dev; - - if (0 != t->index) - return -EINVAL; - - memset(t, 0, sizeof(*t)); - strcpy(t->name, "Radio"); - t->type = V4L2_TUNER_RADIO; - t->rxsubchans = V4L2_TUNER_SUB_STEREO; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); - - return 0; -} - -static int radio_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct tm6000_fh *fh = file->private_data; - struct tm6000_core *dev = fh->dev; - - if (0 != t->index) - return -EINVAL; - - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); - - return 0; -} - -static int radio_enum_input(struct file *file, void *priv, - struct v4l2_input *i) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (i->index != 0) - return -EINVAL; - - if (!dev->rinput.type) - return -EINVAL; - - strcpy(i->name, "Radio"); - i->type = V4L2_INPUT_TYPE_TUNER; - - return 0; -} - -static int radio_g_input(struct file *filp, void *priv, unsigned int *i) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (dev->input != 5) - return -EINVAL; - - *i = dev->input - 5; - - return 0; -} - -static int radio_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - memset(a, 0, sizeof(*a)); - strcpy(a->name, "Radio"); - return 0; -} - -static int radio_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - return 0; -} - -static int radio_s_input(struct file *filp, void *priv, unsigned int i) -{ - struct tm6000_fh *fh = priv; - struct tm6000_core *dev = fh->dev; - - if (i) - return -EINVAL; - - if (!dev->rinput.type) - return -EINVAL; - - dev->input = i + 5; - - return 0; -} - -static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm) -{ - return 0; -} - -static int radio_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *c) -{ - const struct v4l2_queryctrl *ctrl; - - if (c->id < V4L2_CID_BASE || - c->id >= V4L2_CID_LASTP1) - return -EINVAL; - if (c->id == V4L2_CID_AUDIO_MUTE) { - ctrl = ctrl_by_id(c->id); - *c = *ctrl; - } else - *c = no_ctrl; - - return 0; -} - -/* ------------------------------------------------------------------ - File operations for the device - ------------------------------------------------------------------*/ - -static int __tm6000_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct tm6000_core *dev = video_drvdata(file); - struct tm6000_fh *fh; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - int i, rc; - int radio = 0; - - dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: open called (dev=%s)\n", - video_device_node_name(vdev)); - - switch (vdev->vfl_type) { - case VFL_TYPE_GRABBER: - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - break; - case VFL_TYPE_VBI: - type = V4L2_BUF_TYPE_VBI_CAPTURE; - break; - case VFL_TYPE_RADIO: - radio = 1; - break; - } - - /* If more than one user, mutex should be added */ - dev->users++; - - dprintk(dev, V4L2_DEBUG_OPEN, "open dev=%s type=%s users=%d\n", - video_device_node_name(vdev), v4l2_type_names[type], - dev->users); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - dev->users--; - return -ENOMEM; - } - - file->private_data = fh; - fh->dev = dev; - fh->radio = radio; - dev->radio = radio; - fh->type = type; - dev->fourcc = format[0].fourcc; - - fh->fmt = format_by_fourcc(dev->fourcc); - - tm6000_get_std_res(dev); - - fh->width = dev->width; - fh->height = dev->height; - - dprintk(dev, V4L2_DEBUG_OPEN, "Open: fh=0x%08lx, dev=0x%08lx, " - "dev->vidq=0x%08lx\n", - (unsigned long)fh, (unsigned long)dev, - (unsigned long)&dev->vidq); - dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty " - "queued=%d\n", list_empty(&dev->vidq.queued)); - dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty " - "active=%d\n", list_empty(&dev->vidq.active)); - - /* initialize hardware on analog mode */ - rc = tm6000_init_analog_mode(dev); - if (rc < 0) - return rc; - - if (dev->mode != TM6000_MODE_ANALOG) { - /* Put all controls at a sane state */ - for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++) - qctl_regs[i] = tm6000_qctrl[i].default_value; - - dev->mode = TM6000_MODE_ANALOG; - } - - if (!fh->radio) { - videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops, - NULL, &dev->slock, - fh->type, - V4L2_FIELD_INTERLACED, - sizeof(struct tm6000_buffer), fh, &dev->lock); - } else { - dprintk(dev, V4L2_DEBUG_OPEN, "video_open: setting radio device\n"); - dev->input = 5; - tm6000_set_audio_rinput(dev); - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio); - tm6000_prepare_isoc(dev); - tm6000_start_thread(dev); - } - - return 0; -} - -static int tm6000_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - int res; - - mutex_lock(vdev->lock); - res = __tm6000_open(file); - mutex_unlock(vdev->lock); - return res; -} - -static ssize_t -tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos) -{ - struct tm6000_fh *fh = file->private_data; - struct tm6000_core *dev = fh->dev; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - int res; - - if (!res_get(fh->dev, fh, true)) - return -EBUSY; - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - res = videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0, - file->f_flags & O_NONBLOCK); - mutex_unlock(&dev->lock); - return res; - } - return 0; -} - -static unsigned int -__tm6000_poll(struct file *file, struct poll_table_struct *wait) -{ - struct tm6000_fh *fh = file->private_data; - struct tm6000_buffer *buf; - - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) - return POLLERR; - - if (!!is_res_streaming(fh->dev, fh)) - return POLLERR; - - if (!is_res_read(fh->dev, fh)) { - /* streaming capture */ - if (list_empty(&fh->vb_vidq.stream)) - return POLLERR; - buf = list_entry(fh->vb_vidq.stream.next, struct tm6000_buffer, vb.stream); - } else { - /* read() capture */ - return videobuf_poll_stream(file, &fh->vb_vidq, wait); - } - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || - buf->vb.state == VIDEOBUF_ERROR) - return POLLIN | POLLRDNORM; - return 0; -} - -static unsigned int tm6000_poll(struct file *file, struct poll_table_struct *wait) -{ - struct tm6000_fh *fh = file->private_data; - struct tm6000_core *dev = fh->dev; - unsigned int res; - - mutex_lock(&dev->lock); - res = __tm6000_poll(file, wait); - mutex_unlock(&dev->lock); - return res; -} - -static int tm6000_release(struct file *file) -{ - struct tm6000_fh *fh = file->private_data; - struct tm6000_core *dev = fh->dev; - struct video_device *vdev = video_devdata(file); - - dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: close called (dev=%s, users=%d)\n", - video_device_node_name(vdev), dev->users); - - mutex_lock(&dev->lock); - dev->users--; - - res_free(dev, fh); - - if (!dev->users) { - tm6000_uninit_isoc(dev); - - /* Stop interrupt USB pipe */ - tm6000_ir_int_stop(dev); - - usb_reset_configuration(dev->udev); - - if (dev->int_in.endp) - usb_set_interface(dev->udev, - dev->isoc_in.bInterfaceNumber, 2); - else - usb_set_interface(dev->udev, - dev->isoc_in.bInterfaceNumber, 0); - - /* Start interrupt USB pipe */ - tm6000_ir_int_start(dev); - - if (!fh->radio) - videobuf_mmap_free(&fh->vb_vidq); - } - - kfree(fh); - mutex_unlock(&dev->lock); - - return 0; -} - -static int tm6000_mmap(struct file *file, struct vm_area_struct * vma) -{ - struct tm6000_fh *fh = file->private_data; - struct tm6000_core *dev = fh->dev; - int res; - - if (mutex_lock_interruptible(&dev->lock)) - return -ERESTARTSYS; - res = videobuf_mmap_mapper(&fh->vb_vidq, vma); - mutex_unlock(&dev->lock); - return res; -} - -static struct v4l2_file_operations tm6000_fops = { - .owner = THIS_MODULE, - .open = tm6000_open, - .release = tm6000_release, - .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ - .read = tm6000_read, - .poll = tm6000_poll, - .mmap = tm6000_mmap, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .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_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, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, -}; - -static struct video_device tm6000_template = { - .name = "tm6000", - .fops = &tm6000_fops, - .ioctl_ops = &video_ioctl_ops, - .release = video_device_release, - .tvnorms = TM6000_STD, - .current_norm = V4L2_STD_NTSC_M, -}; - -static const struct v4l2_file_operations radio_fops = { - .owner = THIS_MODULE, - .open = tm6000_open, - .release = tm6000_release, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops radio_ioctl_ops = { - .vidioc_querycap = radio_querycap, - .vidioc_g_tuner = radio_g_tuner, - .vidioc_enum_input = radio_enum_input, - .vidioc_g_audio = radio_g_audio, - .vidioc_s_tuner = radio_s_tuner, - .vidioc_s_audio = radio_s_audio, - .vidioc_s_input = radio_s_input, - .vidioc_s_std = radio_s_std, - .vidioc_queryctrl = radio_queryctrl, - .vidioc_g_input = radio_g_input, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, -}; - -static struct video_device tm6000_radio_template = { - .name = "tm6000", - .fops = &radio_fops, - .ioctl_ops = &radio_ioctl_ops, -}; - -/* ----------------------------------------------------------------- - * Initialization and module stuff - * ------------------------------------------------------------------ - */ - -static struct video_device *vdev_init(struct tm6000_core *dev, - const struct video_device - *template, const char *type_name) -{ - struct video_device *vfd; - - vfd = video_device_alloc(); - if (NULL == vfd) - return NULL; - - *vfd = *template; - vfd->v4l2_dev = &dev->v4l2_dev; - vfd->release = video_device_release; - vfd->debug = tm6000_debug; - vfd->lock = &dev->lock; - - snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); - - video_set_drvdata(vfd, dev); - return vfd; -} - -int tm6000_v4l2_register(struct tm6000_core *dev) -{ - int ret = -1; - - dev->vfd = vdev_init(dev, &tm6000_template, "video"); - - if (!dev->vfd) { - printk(KERN_INFO "%s: can't register video device\n", - dev->name); - return -ENOMEM; - } - - /* init video dma queues */ - INIT_LIST_HEAD(&dev->vidq.active); - INIT_LIST_HEAD(&dev->vidq.queued); - - ret = video_register_device(dev->vfd, VFL_TYPE_GRABBER, video_nr); - - if (ret < 0) { - printk(KERN_INFO "%s: can't register video device\n", - dev->name); - return ret; - } - - printk(KERN_INFO "%s: registered device %s\n", - dev->name, video_device_node_name(dev->vfd)); - - if (dev->caps.has_radio) { - dev->radio_dev = vdev_init(dev, &tm6000_radio_template, - "radio"); - if (!dev->radio_dev) { - printk(KERN_INFO "%s: can't register radio device\n", - dev->name); - return ret; /* FIXME release resource */ - } - - ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, - radio_nr); - if (ret < 0) { - printk(KERN_INFO "%s: can't register radio device\n", - dev->name); - return ret; /* FIXME release resource */ - } - - printk(KERN_INFO "%s: registered device %s\n", - dev->name, video_device_node_name(dev->radio_dev)); - } - - printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret); - return ret; -} - -int tm6000_v4l2_unregister(struct tm6000_core *dev) -{ - video_unregister_device(dev->vfd); - - if (dev->radio_dev) { - if (video_is_registered(dev->radio_dev)) - video_unregister_device(dev->radio_dev); - else - video_device_release(dev->radio_dev); - dev->radio_dev = NULL; - } - - return 0; -} - -int tm6000_v4l2_exit(void) -{ - return 0; -} - -module_param(video_nr, int, 0); -MODULE_PARM_DESC(video_nr, "Allow changing video device number"); - -module_param_named(debug, tm6000_debug, int, 0444); -MODULE_PARM_DESC(debug, "activates debug info"); - -module_param(vid_limit, int, 0644); -MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); - diff --git a/drivers/media/video/tm6000/tm6000.h b/drivers/media/video/tm6000/tm6000.h deleted file mode 100644 index 6df418658c9c..000000000000 --- a/drivers/media/video/tm6000/tm6000.h +++ /dev/null @@ -1,399 +0,0 @@ -/* - * tm6000.h - driver for TM5600/TM6000/TM6010 USB video capture devices - * - * Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org> - * - * Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com> - * - DVB-T support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/videodev2.h> -#include <media/v4l2-common.h> -#include <media/videobuf-vmalloc.h> -#include "tm6000-usb-isoc.h" -#include <linux/i2c.h> -#include <linux/mutex.h> -#include <media/v4l2-device.h> - -#include <linux/dvb/frontend.h> -#include "dvb_demux.h" -#include "dvb_frontend.h" -#include "dmxdev.h" - -/* Inputs */ -enum tm6000_itype { - TM6000_INPUT_TV = 1, - TM6000_INPUT_COMPOSITE1, - TM6000_INPUT_COMPOSITE2, - TM6000_INPUT_SVIDEO, - TM6000_INPUT_DVB, - TM6000_INPUT_RADIO, -}; - -enum tm6000_mux { - TM6000_VMUX_VIDEO_A = 1, - TM6000_VMUX_VIDEO_B, - TM6000_VMUX_VIDEO_AB, - TM6000_AMUX_ADC1, - TM6000_AMUX_ADC2, - TM6000_AMUX_SIF1, - TM6000_AMUX_SIF2, - TM6000_AMUX_I2S, -}; - -enum tm6000_devtype { - TM6000 = 0, - TM5600, - TM6010, -}; - -struct tm6000_input { - enum tm6000_itype type; - enum tm6000_mux vmux; - enum tm6000_mux amux; - unsigned int v_gpio; - unsigned int a_gpio; -}; - -/* ------------------------------------------------------------------ - * Basic structures - * ------------------------------------------------------------------ - */ - -struct tm6000_fmt { - char *name; - u32 fourcc; /* v4l2 format id */ - int depth; -}; - -/* buffer for one video frame */ -struct tm6000_buffer { - /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - - struct tm6000_fmt *fmt; -}; - -struct tm6000_dmaqueue { - struct list_head active; - struct list_head queued; - - /* thread for generating video stream*/ - struct task_struct *kthread; - wait_queue_head_t wq; - /* Counters to control fps rate */ - int frame; - int ini_jiffies; -}; - -/* device states */ -enum tm6000_core_state { - DEV_INITIALIZED = 0x01, - DEV_DISCONNECTED = 0x02, - DEV_MISCONFIGURED = 0x04, -}; - -/* io methods */ -enum tm6000_io_method { - IO_NONE, - IO_READ, - IO_MMAP, -}; - -enum tm6000_mode { - TM6000_MODE_UNKNOWN = 0, - TM6000_MODE_ANALOG, - TM6000_MODE_DIGITAL, -}; - -struct tm6000_gpio { - int tuner_reset; - int tuner_on; - int demod_reset; - int demod_on; - int power_led; - int dvb_led; - int ir; -}; - -struct tm6000_capabilities { - unsigned int has_tuner:1; - unsigned int has_tda9874:1; - unsigned int has_dvb:1; - unsigned int has_zl10353:1; - unsigned int has_eeprom:1; - unsigned int has_remote:1; - unsigned int has_radio:1; -}; - -struct tm6000_dvb { - struct dvb_adapter adapter; - struct dvb_demux demux; - struct dvb_frontend *frontend; - struct dmxdev dmxdev; - unsigned int streams; - struct urb *bulk_urb; - struct mutex mutex; -}; - -struct snd_tm6000_card { - struct snd_card *card; - spinlock_t reg_lock; - struct tm6000_core *core; - struct snd_pcm_substream *substream; - - /* temporary data for buffer fill processing */ - unsigned buf_pos; - unsigned period_pos; -}; - -struct tm6000_endpoint { - struct usb_host_endpoint *endp; - __u8 bInterfaceNumber; - __u8 bAlternateSetting; - unsigned maxsize; -}; - -#define TM6000_QUIRK_NO_USB_DELAY (1 << 0) - -struct tm6000_core { - /* generic device properties */ - char name[30]; /* name (including minor) of the device */ - int model; /* index in the device_data struct */ - int devno; /* marks the number of this device */ - enum tm6000_devtype dev_type; /* type of device */ - unsigned char eedata[256]; /* Eeprom data */ - unsigned eedata_size; /* Size of the eeprom info */ - - v4l2_std_id norm; /* Current norm */ - int width, height; /* Selected resolution */ - - enum tm6000_core_state state; - - /* Device Capabilities*/ - struct tm6000_capabilities caps; - - /* Used to load alsa/dvb */ - struct work_struct request_module_wk; - - /* Tuner configuration */ - int tuner_type; /* type of the tuner */ - int tuner_addr; /* tuner address */ - - struct tm6000_gpio gpio; - - char *ir_codes; - - __u8 radio; - - /* Demodulator configuration */ - int demod_addr; /* demodulator address */ - - int audio_bitrate; - /* i2c i/o */ - struct i2c_adapter i2c_adap; - struct i2c_client i2c_client; - - - /* extension */ - struct list_head devlist; - - /* video for linux */ - int users; - - /* various device info */ - struct tm6000_fh *resources; /* Points to fh that is streaming */ - bool is_res_read; - - struct video_device *vfd; - struct video_device *radio_dev; - struct tm6000_dmaqueue vidq; - struct v4l2_device v4l2_dev; - - int input; - struct tm6000_input vinput[3]; /* video input */ - struct tm6000_input rinput; /* radio input */ - - int freq; - unsigned int fourcc; - - enum tm6000_mode mode; - - int ctl_mute; /* audio */ - int ctl_volume; - int amode; - - /* DVB-T support */ - struct tm6000_dvb *dvb; - - /* audio support */ - struct snd_tm6000_card *adev; - struct work_struct wq_trigger; /* Trigger to start/stop audio for alsa module */ - atomic_t stream_started; /* stream should be running if true */ - - struct tm6000_IR *ir; - - /* locks */ - struct mutex lock; - struct mutex usb_lock; - - /* usb transfer */ - struct usb_device *udev; /* the usb device */ - - struct tm6000_endpoint bulk_in, bulk_out, isoc_in, isoc_out; - struct tm6000_endpoint int_in, int_out; - - /* scaler!=0 if scaler is active*/ - int scaler; - - /* Isoc control struct */ - struct usb_isoc_ctl isoc_ctl; - - spinlock_t slock; - - unsigned long quirks; -}; - -enum tm6000_ops_type { - TM6000_AUDIO = 0x10, - TM6000_DVB = 0x20, -}; - -struct tm6000_ops { - struct list_head next; - char *name; - enum tm6000_ops_type type; - int (*init)(struct tm6000_core *); - int (*fini)(struct tm6000_core *); - int (*fillbuf)(struct tm6000_core *, char *buf, int size); -}; - -struct tm6000_fh { - struct tm6000_core *dev; - unsigned int radio; - - /* video capture */ - struct tm6000_fmt *fmt; - unsigned int width, height; - struct videobuf_queue vb_vidq; - - enum v4l2_buf_type type; -}; - -#define TM6000_STD (V4L2_STD_PAL|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc| \ - V4L2_STD_PAL_M|V4L2_STD_PAL_60|V4L2_STD_NTSC_M| \ - V4L2_STD_NTSC_M_JP|V4L2_STD_SECAM) - -/* In tm6000-cards.c */ - -int tm6000_tuner_callback(void *ptr, int component, int command, int arg); -int tm6000_xc5000_callback(void *ptr, int component, int command, int arg); -int tm6000_cards_setup(struct tm6000_core *dev); -void tm6000_flash_led(struct tm6000_core *dev, u8 state); - -/* In tm6000-core.c */ - -int tm6000_read_write_usb(struct tm6000_core *dev, u8 reqtype, u8 req, - u16 value, u16 index, u8 *buf, u16 len); -int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index); -int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index); -int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index); -int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index); -int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value, - u16 index, u16 mask); -int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep); -int tm6000_init(struct tm6000_core *dev); -int tm6000_reset(struct tm6000_core *dev); - -int tm6000_init_analog_mode(struct tm6000_core *dev); -int tm6000_init_digital_mode(struct tm6000_core *dev); -int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate); -int tm6000_set_audio_rinput(struct tm6000_core *dev); -int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute); -void tm6000_set_volume(struct tm6000_core *dev, int vol); - -int tm6000_v4l2_register(struct tm6000_core *dev); -int tm6000_v4l2_unregister(struct tm6000_core *dev); -int tm6000_v4l2_exit(void); -void tm6000_set_fourcc_format(struct tm6000_core *dev); - -void tm6000_remove_from_devlist(struct tm6000_core *dev); -void tm6000_add_into_devlist(struct tm6000_core *dev); -int tm6000_register_extension(struct tm6000_ops *ops); -void tm6000_unregister_extension(struct tm6000_ops *ops); -void tm6000_init_extension(struct tm6000_core *dev); -void tm6000_close_extension(struct tm6000_core *dev); -int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type, - char *buf, int size); - - -/* In tm6000-stds.c */ -void tm6000_get_std_res(struct tm6000_core *dev); -int tm6000_set_standard(struct tm6000_core *dev); - -/* In tm6000-i2c.c */ -int tm6000_i2c_register(struct tm6000_core *dev); -int tm6000_i2c_unregister(struct tm6000_core *dev); - -/* In tm6000-queue.c */ - -int tm6000_v4l2_mmap(struct file *filp, struct vm_area_struct *vma); - -int tm6000_vidioc_streamon(struct file *file, void *priv, - enum v4l2_buf_type i); -int tm6000_vidioc_streamoff(struct file *file, void *priv, - enum v4l2_buf_type i); -int tm6000_vidioc_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *rb); -int tm6000_vidioc_querybuf(struct file *file, void *priv, - struct v4l2_buffer *b); -int tm6000_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b); -int tm6000_vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b); -ssize_t tm6000_v4l2_read(struct file *filp, char __user * buf, size_t count, - loff_t *f_pos); -unsigned int tm6000_v4l2_poll(struct file *file, - struct poll_table_struct *wait); -int tm6000_queue_init(struct tm6000_core *dev); - -/* In tm6000-alsa.c */ -/*int tm6000_audio_init(struct tm6000_core *dev, int idx);*/ - -/* In tm6000-input.c */ -int tm6000_ir_init(struct tm6000_core *dev); -int tm6000_ir_fini(struct tm6000_core *dev); -void tm6000_ir_wait(struct tm6000_core *dev, u8 state); -int tm6000_ir_int_start(struct tm6000_core *dev); -void tm6000_ir_int_stop(struct tm6000_core *dev); - -/* Debug stuff */ - -extern int tm6000_debug; - -#define dprintk(dev, level, fmt, arg...) do {\ - if (tm6000_debug & level) \ - printk(KERN_INFO "(%lu) %s %s :"fmt, jiffies, \ - dev->name, __func__ , ##arg); } while (0) - -#define V4L2_DEBUG_REG 0x0004 -#define V4L2_DEBUG_I2C 0x0008 -#define V4L2_DEBUG_QUEUE 0x0010 -#define V4L2_DEBUG_ISOC 0x0020 -#define V4L2_DEBUG_RES_LOCK 0x0040 /* Resource locking */ -#define V4L2_DEBUG_OPEN 0x0080 /* video open/close debug */ - -#define tm6000_err(fmt, arg...) do {\ - printk(KERN_ERR "tm6000 %s :"fmt, \ - __func__ , ##arg); } while (0) diff --git a/drivers/media/video/usbvision/Kconfig b/drivers/media/video/usbvision/Kconfig deleted file mode 100644 index fc24ef05b3f3..000000000000 --- a/drivers/media/video/usbvision/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -config VIDEO_USBVISION - tristate "USB video devices based on Nogatech NT1003/1004/1005" - depends on I2C && VIDEO_V4L2 - select VIDEO_TUNER - select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO - ---help--- - There are more than 50 different USB video devices based on - NT1003/1004/1005 USB Bridges. This driver enables using those - devices. - - To compile this driver as a module, choose M here: the - module will be called usbvision. diff --git a/drivers/media/video/usbvision/Makefile b/drivers/media/video/usbvision/Makefile deleted file mode 100644 index d55c6bd97a35..000000000000 --- a/drivers/media/video/usbvision/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -usbvision-objs := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-cards.o - -obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o - -ccflags-y += -Idrivers/media/video -ccflags-y += -Idrivers/media/tuners diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c deleted file mode 100644 index 3103d0d020e8..000000000000 --- a/drivers/media/video/usbvision/usbvision-cards.c +++ /dev/null @@ -1,1133 +0,0 @@ -/* - * usbvision-cards.c - * usbvision cards definition file - * - * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> - * - * This module is part of usbvision driver project. - * Updates to driver completed by Dwaine P. Garden - * - * 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 <linux/list.h> -#include <linux/module.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[] = { - [XANBOO] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 4, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = -1, - .y_offset = -1, - .model_string = "Xanboo", - }, - [BELKIN_VIDEOBUS_II] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 2, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Belkin USB VideoBus II Adapter", - }, - [BELKIN_VIDEOBUS] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 2, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = -1, - .y_offset = -1, - .model_string = "Belkin Components USB VideoBus", - }, - [BELKIN_USB_VIDEOBUS_II] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 2, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Belkin USB VideoBus II", - }, - [ECHOFX_INTERVIEW_LITE] = { - .interface = 0, - .codec = CODEC_SAA7111, - .video_channels = 2, - .video_norm = V4L2_STD_PAL, - .audio_channels = 0, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = -1, - .y_offset = -1, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "echoFX InterView Lite", - }, - [USBGEAR_USBG_V1] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 2, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = -1, - .y_offset = -1, - .model_string = "USBGear USBG-V1 resp. HAMA USB", - }, - [D_LINK_V100] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 4, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 0, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "D-Link V100", - }, - [X10_USB_CAMERA] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 2, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = -1, - .y_offset = -1, - .model_string = "X10 USB Camera", - }, - [HPG_WINTV_LIVE_PAL_BG] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 2, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = -1, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Live (PAL B/G)", - }, - [HPG_WINTV_LIVE_PRO_NTSC_MN] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 2, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 0, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Live Pro (NTSC M/N)", - }, - [ZORAN_PMD_NOGATECH] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 2, - .video_norm = V4L2_STD_PAL, - .audio_channels = 2, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Zoran Co. PMD (Nogatech) AV-grabber Manhattan", - }, - [NOGATECH_USB_TV_NTSC_FM] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_NTSC_M, - .x_offset = -1, - .y_offset = 20, - .model_string = "Nogatech USB-TV (NTSC) FM", - }, - [PNY_USB_TV_NTSC_FM] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_NTSC_M, - .x_offset = -1, - .y_offset = 20, - .model_string = "PNY USB-TV (NTSC) FM", - }, - [PV_PLAYTV_USB_PRO_PAL_FM] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "PixelView PlayTv-USB PRO (PAL) FM", - }, - [ZT_721] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "ZTV ZT-721 2.4GHz USB A/V Receiver", - }, - [HPG_WINTV_NTSC_MN] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_NTSC_M, - .x_offset = -1, - .y_offset = 20, - .model_string = "Hauppauge WinTV USB (NTSC M/N)", - }, - [HPG_WINTV_PAL_BG] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .x_offset = -1, - .y_offset = -1, - .model_string = "Hauppauge WinTV USB (PAL B/G)", - }, - [HPG_WINTV_PAL_I] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .x_offset = -1, - .y_offset = -1, - .model_string = "Hauppauge WinTV USB (PAL I)", - }, - [HPG_WINTV_PAL_SECAM_L] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_SECAM, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_SECAM, - .x_offset = 0x80, - .y_offset = 0x16, - .model_string = "Hauppauge WinTV USB (PAL/SECAM L)", - }, - [HPG_WINTV_PAL_D_K] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .x_offset = -1, - .y_offset = -1, - .model_string = "Hauppauge WinTV USB (PAL D/K)", - }, - [HPG_WINTV_NTSC_FM] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_NTSC_M, - .x_offset = -1, - .y_offset = -1, - .model_string = "Hauppauge WinTV USB (NTSC FM)", - }, - [HPG_WINTV_PAL_BG_FM] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .x_offset = -1, - .y_offset = -1, - .model_string = "Hauppauge WinTV USB (PAL B/G FM)", - }, - [HPG_WINTV_PAL_I_FM] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .x_offset = -1, - .y_offset = -1, - .model_string = "Hauppauge WinTV USB (PAL I FM)", - }, - [HPG_WINTV_PAL_D_K_FM] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .x_offset = -1, - .y_offset = -1, - .model_string = "Hauppauge WinTV USB (PAL D/K FM)", - }, - [HPG_WINTV_PRO_NTSC_MN] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_MICROTUNE_4049FM5, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (NTSC M/N)", - }, - [HPG_WINTV_PRO_NTSC_MN_V2] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_MICROTUNE_4049FM5, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (NTSC M/N) V2", - }, - [HPG_WINTV_PRO_PAL] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L)", - }, - [HPG_WINTV_PRO_NTSC_MN_V3] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_NTSC_M, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (NTSC M/N) V3", - }, - [HPG_WINTV_PRO_PAL_BG] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (PAL B/G)", - }, - [HPG_WINTV_PRO_PAL_I] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (PAL I)", - }, - [HPG_WINTV_PRO_PAL_SECAM_L] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_SECAM, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_SECAM, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (PAL/SECAM L)", - }, - [HPG_WINTV_PRO_PAL_D_K] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (PAL D/K)", - }, - [HPG_WINTV_PRO_PAL_SECAM] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_SECAM, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_SECAM, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L)", - }, - [HPG_WINTV_PRO_PAL_SECAM_V2] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_SECAM, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_SECAM, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L) V2", - }, - [HPG_WINTV_PRO_PAL_BG_V2] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_ALPS_TSBE1_PAL, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (PAL B/G) V2", - }, - [HPG_WINTV_PRO_PAL_BG_D_K] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_ALPS_TSBE1_PAL, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (PAL B/G,D/K)", - }, - [HPG_WINTV_PRO_PAL_I_D_K] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (PAL I,D/K)", - }, - [HPG_WINTV_PRO_NTSC_MN_FM] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_NTSC_M, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (NTSC M/N FM)", - }, - [HPG_WINTV_PRO_PAL_BG_FM] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (PAL B/G FM)", - }, - [HPG_WINTV_PRO_PAL_I_FM] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (PAL I FM)", - }, - [HPG_WINTV_PRO_PAL_D_K_FM] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (PAL D/K FM)", - }, - [HPG_WINTV_PRO_TEMIC_PAL_FM] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_MICROTUNE_4049FM5, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (Temic PAL/SECAM B/G/I/D/K/L FM)", - }, - [HPG_WINTV_PRO_TEMIC_PAL_BG_FM] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_MICROTUNE_4049FM5, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (Temic PAL B/G FM)", - }, - [HPG_WINTV_PRO_PAL_FM] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L FM)", - }, - [HPG_WINTV_PRO_NTSC_MN_FM_V2] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_NTSC_M, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Hauppauge WinTV USB Pro (NTSC M/N FM) V2", - }, - [CAMTEL_TVB330] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_NTSC_M, - .x_offset = 5, - .y_offset = 5, - .model_string = "Camtel Technology USB TV Genie Pro FM Model TVB330", - }, - [DIGITAL_VIDEO_CREATOR_I] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 2, - .video_norm = V4L2_STD_PAL, - .audio_channels = 0, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Digital Video Creator I", - }, - [GLOBAL_VILLAGE_GV_007_NTSC] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 2, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 0, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = 82, - .y_offset = 20, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Global Village GV-007 (NTSC)", - }, - [DAZZLE_DVC_50_REV_1_NTSC] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 2, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 0, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)", - }, - [DAZZLE_DVC_80_REV_1_PAL] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 2, - .video_norm = V4L2_STD_PAL, - .audio_channels = 0, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Dazzle Fusion Model DVC-80 Rev 1 (PAL)", - }, - [DAZZLE_DVC_90_REV_1_SECAM] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 2, - .video_norm = V4L2_STD_SECAM, - .audio_channels = 0, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)", - }, - [ESKAPE_LABS_MYTV2GO] = { - .interface = 0, - .codec = CODEC_SAA7113, - .video_channels = 2, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Eskape Labs MyTV2Go", - }, - [PINNA_PCTV_USB_PAL] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 0, - .vbi = 0, - .tuner = 1, - .tuner_type = TUNER_TEMIC_4066FY5_PAL_I, - .x_offset = -1, - .y_offset = -1, - .model_string = "Pinnacle Studio PCTV USB (PAL)", - }, - [PINNA_PCTV_USB_SECAM] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_SECAM, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_SECAM, - .x_offset = -1, - .y_offset = -1, - .model_string = "Pinnacle Studio PCTV USB (SECAM)", - }, - [PINNA_PCTV_USB_PAL_FM] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .x_offset = 128, - .y_offset = 23, - .model_string = "Pinnacle Studio PCTV USB (PAL) FM", - }, - [MIRO_PCTV_USB] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_PAL, - .x_offset = -1, - .y_offset = -1, - .model_string = "Miro PCTV USB", - }, - [PINNA_PCTV_USB_NTSC_FM] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_NTSC_M, - .x_offset = -1, - .y_offset = -1, - .model_string = "Pinnacle Studio PCTV USB (NTSC) FM", - }, - [PINNA_PCTV_USB_NTSC_FM_V3] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_NTSC_M, - .x_offset = -1, - .y_offset = -1, - .model_string = "Pinnacle Studio PCTV USB (NTSC) FM V3", - }, - [PINNA_PCTV_USB_PAL_FM_V2] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_TEMIC_4009FR5_PAL, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Pinnacle Studio PCTV USB (PAL) FM V2", - }, - [PINNA_PCTV_USB_NTSC_FM_V2] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_TEMIC_4039FR5_NTSC, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Pinnacle Studio PCTV USB (NTSC) FM V2", - }, - [PINNA_PCTV_USB_PAL_FM_V3] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_TEMIC_4009FR5_PAL, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Pinnacle Studio PCTV USB (PAL) FM V3", - }, - [PINNA_LINX_VD_IN_CAB_NTSC] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 2, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Pinnacle Studio Linx Video input cable (NTSC)", - }, - [PINNA_LINX_VD_IN_CAB_PAL] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 2, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 0, - .tuner_type = 0, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Pinnacle Studio Linx Video input cable (PAL)", - }, - [PINNA_PCTV_BUNGEE_PAL_FM] = { - .interface = -1, - .codec = CODEC_SAA7113, - .video_channels = 3, - .video_norm = V4L2_STD_PAL, - .audio_channels = 1, - .radio = 1, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_TEMIC_4009FR5_PAL, - .x_offset = 0, - .y_offset = 3, - .dvi_yuv_override = 1, - .dvi_yuv = 7, - .model_string = "Pinnacle PCTV Bungee USB (PAL) FM", - }, - [HPG_WINTV] = { - .interface = -1, - .codec = CODEC_SAA7111, - .video_channels = 3, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 1, - .radio = 0, - .vbi = 1, - .tuner = 1, - .tuner_type = TUNER_PHILIPS_NTSC_M, - .x_offset = -1, - .y_offset = -1, - .model_string = "Hauppauge WinTv-USB", - }, - [MICROCAM_NTSC] = { - .interface = -1, - .codec = CODEC_WEBCAM, - .video_channels = 1, - .video_norm = V4L2_STD_NTSC, - .audio_channels = 0, - .radio = 0, - .vbi = 0, - .tuner = 0, - .tuner_type = 0, - .x_offset = 71, - .y_offset = 15, - .model_string = "Nogatech USB MicroCam NTSC (NV3000N)", - }, - [MICROCAM_PAL] = { - .interface = -1, - .codec = CODEC_WEBCAM, - .video_channels = 1, - .video_norm = V4L2_STD_PAL, - .audio_channels = 0, - .radio = 0, - .vbi = 0, - .tuner = 0, - .tuner_type = 0, - .x_offset = 71, - .y_offset = 18, - .model_string = "Nogatech USB MicroCam PAL (NV3001P)", - }, -}; -const int usbvision_device_data_size = ARRAY_SIZE(usbvision_device_data); - -/* Supported Devices */ - -struct usb_device_id usbvision_table[] = { - { USB_DEVICE(0x0a6f, 0x0400), .driver_info = XANBOO }, - { USB_DEVICE(0x050d, 0x0106), .driver_info = BELKIN_VIDEOBUS_II }, - { USB_DEVICE(0x050d, 0x0207), .driver_info = BELKIN_VIDEOBUS }, - { USB_DEVICE(0x050d, 0x0208), .driver_info = BELKIN_USB_VIDEOBUS_II }, - { USB_DEVICE(0x0571, 0x0002), .driver_info = ECHOFX_INTERVIEW_LITE }, - { USB_DEVICE(0x0573, 0x0003), .driver_info = USBGEAR_USBG_V1 }, - { USB_DEVICE(0x0573, 0x0400), .driver_info = D_LINK_V100 }, - { USB_DEVICE(0x0573, 0x2000), .driver_info = X10_USB_CAMERA }, - { USB_DEVICE(0x0573, 0x2d00), .driver_info = HPG_WINTV_LIVE_PAL_BG }, - { USB_DEVICE(0x0573, 0x2d01), .driver_info = HPG_WINTV_LIVE_PRO_NTSC_MN }, - { USB_DEVICE(0x0573, 0x2101), .driver_info = ZORAN_PMD_NOGATECH }, - { USB_DEVICE(0x0573, 0x3000), .driver_info = MICROCAM_NTSC }, - { USB_DEVICE(0x0573, 0x3001), .driver_info = MICROCAM_PAL }, - { 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, 0x0113), .driver_info = PINNA_PCTV_USB_NTSC_FM_V3 }, - { USB_DEVICE(0x2304, 0x0210), .driver_info = PINNA_PCTV_USB_PAL_FM_V2 }, - { USB_DEVICE(0x2304, 0x0212), .driver_info = PINNA_PCTV_USB_NTSC_FM_V2 }, - { USB_DEVICE(0x2304, 0x0214), .driver_info = PINNA_PCTV_USB_PAL_FM_V3 }, - { USB_DEVICE(0x2304, 0x0300), .driver_info = PINNA_LINX_VD_IN_CAB_NTSC }, - { USB_DEVICE(0x2304, 0x0301), .driver_info = PINNA_LINX_VD_IN_CAB_PAL }, - { USB_DEVICE(0x2304, 0x0419), .driver_info = PINNA_PCTV_BUNGEE_PAL_FM }, - { USB_DEVICE(0x2400, 0x4200), .driver_info = HPG_WINTV }, - { }, /* terminate list */ -}; - -MODULE_DEVICE_TABLE(usb, usbvision_table); diff --git a/drivers/media/video/usbvision/usbvision-cards.h b/drivers/media/video/usbvision/usbvision-cards.h deleted file mode 100644 index a51cc1185cce..000000000000 --- a/drivers/media/video/usbvision/usbvision-cards.h +++ /dev/null @@ -1,69 +0,0 @@ -#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 -#define PINNA_PCTV_USB_NTSC_FM_V3 64 -#define MICROCAM_NTSC 65 -#define MICROCAM_PAL 66 - -extern const int usbvision_device_data_size; diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c deleted file mode 100644 index c9b2042f8bdf..000000000000 --- a/drivers/media/video/usbvision/usbvision-core.c +++ /dev/null @@ -1,2518 +0,0 @@ -/* - * usbvision-core.c - driver for NT100x USB video capture devices - * - * - * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> - * Dwaine Garden <dwainegarden@rogers.com> - * - * This module is part of usbvision driver project. - * Updates to driver completed by Dwaine P. Garden - * - * 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 <linux/kernel.h> -#include <linux/list.h> -#include <linux/timer.h> -#include <linux/gfp.h> -#include <linux/mm.h> -#include <linux/highmem.h> -#include <linux/vmalloc.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/io.h> -#include <linux/videodev2.h> -#include <linux/i2c.h> - -#include <media/saa7115.h> -#include <media/v4l2-common.h> -#include <media/tuner.h> - -#include <linux/workqueue.h> - -#include "usbvision.h" - -static unsigned int core_debug; -module_param(core_debug, int, 0644); -MODULE_PARM_DESC(core_debug, "enable debug messages [core]"); - -static int adjust_compression = 1; /* Set the compression to be adaptive */ -module_param(adjust_compression, int, 0444); -MODULE_PARM_DESC(adjust_compression, " Set the ADPCM compression for the device. Default: 1 (On)"); - -/* To help people with Black and White output with using s-video input. - * Some cables and input device are wired differently. */ -static int switch_svideo_input; -module_param(switch_svideo_input, int, 0444); -MODULE_PARM_DESC(switch_svideo_input, " Set the S-Video input. Some cables and input device are wired differently. Default: 0 (Off)"); - -static unsigned int adjust_x_offset = -1; -module_param(adjust_x_offset, int, 0644); -MODULE_PARM_DESC(adjust_x_offset, "adjust X offset display [core]"); - -static unsigned int adjust_y_offset = -1; -module_param(adjust_y_offset, int, 0644); -MODULE_PARM_DESC(adjust_y_offset, "adjust Y offset display [core]"); - - -#define ENABLE_HEXDUMP 0 /* Enable if you need it */ - - -#ifdef USBVISION_DEBUG - #define PDEBUG(level, fmt, args...) { \ - if (core_debug & (level)) \ - printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \ - __func__, __LINE__ , ## args); \ - } -#else - #define PDEBUG(level, fmt, args...) do {} while (0) -#endif - -#define DBG_HEADER (1 << 0) -#define DBG_IRQ (1 << 1) -#define DBG_ISOC (1 << 2) -#define DBG_PARSE (1 << 3) -#define DBG_SCRATCH (1 << 4) -#define DBG_FUNC (1 << 5) - -static const int max_imgwidth = MAX_FRAME_WIDTH; -static const int max_imgheight = MAX_FRAME_HEIGHT; -static const int min_imgwidth = MIN_FRAME_WIDTH; -static const int min_imgheight = MIN_FRAME_HEIGHT; - -/* The value of 'scratch_buf_size' affects quality of the picture - * in many ways. Shorter buffers may cause loss of data when client - * is too slow. Larger buffers are memory-consuming and take longer - * to work with. This setting can be adjusted, but the default value - * should be OK for most desktop users. - */ -#define DEFAULT_SCRATCH_BUF_SIZE (0x20000) /* 128kB memory scratch buffer */ -static const int scratch_buf_size = DEFAULT_SCRATCH_BUF_SIZE; - -/* Function prototypes */ -static int usbvision_request_intra(struct usb_usbvision *usbvision); -static int usbvision_unrequest_intra(struct usb_usbvision *usbvision); -static int usbvision_adjust_compression(struct usb_usbvision *usbvision); -static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision); - -/*******************************/ -/* Memory management functions */ -/*******************************/ - -/* - * Here we want the physical address of the memory. - * This is used when initializing the contents of the area. - */ - -static void *usbvision_rvmalloc(unsigned long size) -{ - void *mem; - unsigned long adr; - - size = PAGE_ALIGN(size); - mem = vmalloc_32(size); - if (!mem) - return NULL; - - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr = (unsigned long) mem; - while (size > 0) { - SetPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return mem; -} - -static void usbvision_rvfree(void *mem, unsigned long size) -{ - unsigned long adr; - - if (!mem) - return; - - size = PAGE_ALIGN(size); - - adr = (unsigned long) mem; - while ((long) size > 0) { - ClearPageReserved(vmalloc_to_page((void *)adr)); - adr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - vfree(mem); -} - - -#if ENABLE_HEXDUMP -static void usbvision_hexdump(const unsigned char *data, int len) -{ - char tmp[80]; - int i, k; - - for (i = k = 0; len > 0; i++, len--) { - if (i > 0 && (i % 16 == 0)) { - printk("%s\n", tmp); - k = 0; - } - k += sprintf(&tmp[k], "%02x ", data[i]); - } - if (k > 0) - printk(KERN_CONT "%s\n", tmp); -} -#endif - -/******************************** - * scratch ring buffer handling - ********************************/ -static int scratch_len(struct usb_usbvision *usbvision) /* This returns the amount of data actually in the buffer */ -{ - int len = usbvision->scratch_write_ptr - usbvision->scratch_read_ptr; - - if (len < 0) - len += scratch_buf_size; - PDEBUG(DBG_SCRATCH, "scratch_len() = %d\n", len); - - return len; -} - - -/* This returns the free space left in the buffer */ -static int scratch_free(struct usb_usbvision *usbvision) -{ - int free = usbvision->scratch_read_ptr - usbvision->scratch_write_ptr; - if (free <= 0) - free += scratch_buf_size; - if (free) { - free -= 1; /* at least one byte in the buffer must */ - /* left blank, otherwise there is no chance to differ between full and empty */ - } - PDEBUG(DBG_SCRATCH, "return %d\n", free); - - return free; -} - - -/* This puts data into the buffer */ -static int scratch_put(struct usb_usbvision *usbvision, unsigned char *data, - int len) -{ - int len_part; - - if (usbvision->scratch_write_ptr + len < scratch_buf_size) { - memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len); - usbvision->scratch_write_ptr += len; - } else { - len_part = scratch_buf_size - usbvision->scratch_write_ptr; - memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len_part); - if (len == len_part) { - usbvision->scratch_write_ptr = 0; /* just set write_ptr to zero */ - } else { - memcpy(usbvision->scratch, data + len_part, len - len_part); - usbvision->scratch_write_ptr = len - len_part; - } - } - - PDEBUG(DBG_SCRATCH, "len=%d, new write_ptr=%d\n", len, usbvision->scratch_write_ptr); - - return len; -} - -/* This marks the write_ptr as position of new frame header */ -static void scratch_mark_header(struct usb_usbvision *usbvision) -{ - PDEBUG(DBG_SCRATCH, "header at write_ptr=%d\n", usbvision->scratch_headermarker_write_ptr); - - usbvision->scratch_headermarker[usbvision->scratch_headermarker_write_ptr] = - usbvision->scratch_write_ptr; - usbvision->scratch_headermarker_write_ptr += 1; - usbvision->scratch_headermarker_write_ptr %= USBVISION_NUM_HEADERMARKER; -} - -/* This gets data from the buffer at the given "ptr" position */ -static int scratch_get_extra(struct usb_usbvision *usbvision, - unsigned char *data, int *ptr, int len) -{ - int len_part; - - if (*ptr + len < scratch_buf_size) { - memcpy(data, usbvision->scratch + *ptr, len); - *ptr += len; - } else { - len_part = scratch_buf_size - *ptr; - memcpy(data, usbvision->scratch + *ptr, len_part); - if (len == len_part) { - *ptr = 0; /* just set the y_ptr to zero */ - } else { - memcpy(data + len_part, usbvision->scratch, len - len_part); - *ptr = len - len_part; - } - } - - PDEBUG(DBG_SCRATCH, "len=%d, new ptr=%d\n", len, *ptr); - - return len; -} - - -/* This sets the scratch extra read pointer */ -static void scratch_set_extra_ptr(struct usb_usbvision *usbvision, int *ptr, - int len) -{ - *ptr = (usbvision->scratch_read_ptr + len) % scratch_buf_size; - - PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr); -} - - -/* This increments the scratch extra read pointer */ -static void scratch_inc_extra_ptr(int *ptr, int len) -{ - *ptr = (*ptr + len) % scratch_buf_size; - - PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr); -} - - -/* This gets data from the buffer */ -static int scratch_get(struct usb_usbvision *usbvision, unsigned char *data, - int len) -{ - int len_part; - - if (usbvision->scratch_read_ptr + len < scratch_buf_size) { - memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len); - usbvision->scratch_read_ptr += len; - } else { - len_part = scratch_buf_size - usbvision->scratch_read_ptr; - memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len_part); - if (len == len_part) { - usbvision->scratch_read_ptr = 0; /* just set the read_ptr to zero */ - } else { - memcpy(data + len_part, usbvision->scratch, len - len_part); - usbvision->scratch_read_ptr = len - len_part; - } - } - - PDEBUG(DBG_SCRATCH, "len=%d, new read_ptr=%d\n", len, usbvision->scratch_read_ptr); - - return len; -} - - -/* This sets read pointer to next header and returns it */ -static int scratch_get_header(struct usb_usbvision *usbvision, - struct usbvision_frame_header *header) -{ - int err_code = 0; - - PDEBUG(DBG_SCRATCH, "from read_ptr=%d", usbvision->scratch_headermarker_read_ptr); - - while (usbvision->scratch_headermarker_write_ptr - - usbvision->scratch_headermarker_read_ptr != 0) { - usbvision->scratch_read_ptr = - usbvision->scratch_headermarker[usbvision->scratch_headermarker_read_ptr]; - usbvision->scratch_headermarker_read_ptr += 1; - usbvision->scratch_headermarker_read_ptr %= USBVISION_NUM_HEADERMARKER; - scratch_get(usbvision, (unsigned char *)header, USBVISION_HEADER_LENGTH); - if ((header->magic_1 == USBVISION_MAGIC_1) - && (header->magic_2 == USBVISION_MAGIC_2) - && (header->header_length == USBVISION_HEADER_LENGTH)) { - err_code = USBVISION_HEADER_LENGTH; - header->frame_width = header->frame_width_lo + (header->frame_width_hi << 8); - header->frame_height = header->frame_height_lo + (header->frame_height_hi << 8); - break; - } - } - - return err_code; -} - - -/* This removes len bytes of old data from the buffer */ -static void scratch_rm_old(struct usb_usbvision *usbvision, int len) -{ - usbvision->scratch_read_ptr += len; - usbvision->scratch_read_ptr %= scratch_buf_size; - PDEBUG(DBG_SCRATCH, "read_ptr is now %d\n", usbvision->scratch_read_ptr); -} - - -/* This resets the buffer - kills all data in it too */ -static void scratch_reset(struct usb_usbvision *usbvision) -{ - PDEBUG(DBG_SCRATCH, "\n"); - - usbvision->scratch_read_ptr = 0; - usbvision->scratch_write_ptr = 0; - usbvision->scratch_headermarker_read_ptr = 0; - usbvision->scratch_headermarker_write_ptr = 0; - usbvision->isocstate = isoc_state_no_frame; -} - -int usbvision_scratch_alloc(struct usb_usbvision *usbvision) -{ - usbvision->scratch = vmalloc_32(scratch_buf_size); - scratch_reset(usbvision); - if (usbvision->scratch == NULL) { - dev_err(&usbvision->dev->dev, - "%s: unable to allocate %d bytes for scratch\n", - __func__, scratch_buf_size); - return -ENOMEM; - } - return 0; -} - -void usbvision_scratch_free(struct usb_usbvision *usbvision) -{ - vfree(usbvision->scratch); - usbvision->scratch = NULL; -} - -/* - * usbvision_decompress_alloc() - * - * allocates intermediate buffer for decompression - */ -int usbvision_decompress_alloc(struct usb_usbvision *usbvision) -{ - int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2; - - usbvision->intra_frame_buffer = vmalloc_32(IFB_size); - if (usbvision->intra_frame_buffer == NULL) { - dev_err(&usbvision->dev->dev, - "%s: unable to allocate %d for compr. frame buffer\n", - __func__, IFB_size); - return -ENOMEM; - } - return 0; -} - -/* - * usbvision_decompress_free() - * - * frees intermediate buffer for decompression - */ -void usbvision_decompress_free(struct usb_usbvision *usbvision) -{ - vfree(usbvision->intra_frame_buffer); - usbvision->intra_frame_buffer = NULL; - -} - -/************************************************************ - * Here comes the data parsing stuff that is run as interrupt - ************************************************************/ -/* - * usbvision_find_header() - * - * Locate one of supported header markers in the scratch buffer. - */ -static enum parse_state usbvision_find_header(struct usb_usbvision *usbvision) -{ - struct usbvision_frame *frame; - int found_header = 0; - - frame = usbvision->cur_frame; - - while (scratch_get_header(usbvision, &frame->isoc_header) == USBVISION_HEADER_LENGTH) { - /* found header in scratch */ - PDEBUG(DBG_HEADER, "found header: 0x%02x%02x %d %d %d %d %#x 0x%02x %u %u", - frame->isoc_header.magic_2, - frame->isoc_header.magic_1, - frame->isoc_header.header_length, - frame->isoc_header.frame_num, - frame->isoc_header.frame_phase, - frame->isoc_header.frame_latency, - frame->isoc_header.data_format, - frame->isoc_header.format_param, - frame->isoc_header.frame_width, - frame->isoc_header.frame_height); - - if (usbvision->request_intra) { - if (frame->isoc_header.format_param & 0x80) { - found_header = 1; - usbvision->last_isoc_frame_num = -1; /* do not check for lost frames this time */ - usbvision_unrequest_intra(usbvision); - break; - } - } else { - found_header = 1; - break; - } - } - - if (found_header) { - frame->frmwidth = frame->isoc_header.frame_width * usbvision->stretch_width; - frame->frmheight = frame->isoc_header.frame_height * usbvision->stretch_height; - frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth) >> 3; - } else { /* no header found */ - PDEBUG(DBG_HEADER, "skipping scratch data, no header"); - scratch_reset(usbvision); - return parse_state_end_parse; - } - - /* found header */ - if (frame->isoc_header.data_format == ISOC_MODE_COMPRESS) { - /* check isoc_header.frame_num for lost frames */ - if (usbvision->last_isoc_frame_num >= 0) { - if (((usbvision->last_isoc_frame_num + 1) % 32) != frame->isoc_header.frame_num) { - /* unexpected frame drop: need to request new intra frame */ - PDEBUG(DBG_HEADER, "Lost frame before %d on USB", frame->isoc_header.frame_num); - usbvision_request_intra(usbvision); - return parse_state_next_frame; - } - } - usbvision->last_isoc_frame_num = frame->isoc_header.frame_num; - } - usbvision->header_count++; - frame->scanstate = scan_state_lines; - frame->curline = 0; - - return parse_state_continue; -} - -static enum parse_state usbvision_parse_lines_422(struct usb_usbvision *usbvision, - long *pcopylen) -{ - volatile struct usbvision_frame *frame; - unsigned char *f; - int len; - int i; - unsigned char yuyv[4] = { 180, 128, 10, 128 }; /* YUV components */ - unsigned char rv, gv, bv; /* RGB components */ - int clipmask_index, bytes_per_pixel; - int stretch_bytes, clipmask_add; - - frame = usbvision->cur_frame; - f = frame->data + (frame->v4l2_linesize * frame->curline); - - /* Make sure there's enough data for the entire line */ - len = (frame->isoc_header.frame_width * 2) + 5; - if (scratch_len(usbvision) < len) { - PDEBUG(DBG_PARSE, "out of data in line %d, need %u.\n", frame->curline, len); - return parse_state_out; - } - - if ((frame->curline + 1) >= frame->frmheight) - return parse_state_next_frame; - - bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; - stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel; - clipmask_index = frame->curline * MAX_FRAME_WIDTH; - clipmask_add = usbvision->stretch_width; - - for (i = 0; i < frame->frmwidth; i += (2 * usbvision->stretch_width)) { - scratch_get(usbvision, &yuyv[0], 4); - - if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f++ = yuyv[0]; /* Y */ - *f++ = yuyv[3]; /* U */ - } else { - YUV_TO_RGB_BY_THE_BOOK(yuyv[0], yuyv[1], yuyv[3], rv, gv, bv); - switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - *f++ = (0x1F & rv) | - (0xE0 & (gv << 5)); - *f++ = (0x07 & (gv >> 3)) | - (0xF8 & bv); - break; - case V4L2_PIX_FMT_RGB24: - *f++ = rv; - *f++ = gv; - *f++ = bv; - break; - case V4L2_PIX_FMT_RGB32: - *f++ = rv; - *f++ = gv; - *f++ = bv; - f++; - break; - case V4L2_PIX_FMT_RGB555: - *f++ = (0x1F & rv) | - (0xE0 & (gv << 5)); - *f++ = (0x03 & (gv >> 3)) | - (0x7C & (bv << 2)); - break; - } - } - clipmask_index += clipmask_add; - f += stretch_bytes; - - if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f++ = yuyv[2]; /* Y */ - *f++ = yuyv[1]; /* V */ - } else { - YUV_TO_RGB_BY_THE_BOOK(yuyv[2], yuyv[1], yuyv[3], rv, gv, bv); - switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - *f++ = (0x1F & rv) | - (0xE0 & (gv << 5)); - *f++ = (0x07 & (gv >> 3)) | - (0xF8 & bv); - break; - case V4L2_PIX_FMT_RGB24: - *f++ = rv; - *f++ = gv; - *f++ = bv; - break; - case V4L2_PIX_FMT_RGB32: - *f++ = rv; - *f++ = gv; - *f++ = bv; - f++; - break; - case V4L2_PIX_FMT_RGB555: - *f++ = (0x1F & rv) | - (0xE0 & (gv << 5)); - *f++ = (0x03 & (gv >> 3)) | - (0x7C & (bv << 2)); - break; - } - } - clipmask_index += clipmask_add; - f += stretch_bytes; - } - - frame->curline += usbvision->stretch_height; - *pcopylen += frame->v4l2_linesize * usbvision->stretch_height; - - if (frame->curline >= frame->frmheight) - return parse_state_next_frame; - return parse_state_continue; -} - -/* The decompression routine */ -static int usbvision_decompress(struct usb_usbvision *usbvision, unsigned char *compressed, - unsigned char *decompressed, int *start_pos, - int *block_typestart_pos, int len) -{ - int rest_pixel, idx, pos, extra_pos, block_len, block_type_pos, block_type_len; - unsigned char block_byte, block_code, block_type, block_type_byte, integrator; - - integrator = 0; - pos = *start_pos; - block_type_pos = *block_typestart_pos; - extra_pos = pos; - block_len = 0; - block_byte = 0; - block_code = 0; - block_type = 0; - block_type_byte = 0; - block_type_len = 0; - rest_pixel = len; - - for (idx = 0; idx < len; idx++) { - if (block_len == 0) { - if (block_type_len == 0) { - block_type_byte = compressed[block_type_pos]; - block_type_pos++; - block_type_len = 4; - } - block_type = (block_type_byte & 0xC0) >> 6; - - /* statistic: */ - usbvision->compr_block_types[block_type]++; - - pos = extra_pos; - if (block_type == 0) { - if (rest_pixel >= 24) { - idx += 23; - rest_pixel -= 24; - integrator = decompressed[idx]; - } else { - idx += rest_pixel - 1; - rest_pixel = 0; - } - } else { - block_code = compressed[pos]; - pos++; - if (rest_pixel >= 24) - block_len = 24; - else - block_len = rest_pixel; - rest_pixel -= block_len; - extra_pos = pos + (block_len / 4); - } - block_type_byte <<= 2; - block_type_len -= 1; - } - if (block_len > 0) { - if ((block_len % 4) == 0) { - block_byte = compressed[pos]; - pos++; - } - if (block_type == 1) /* inter Block */ - integrator = decompressed[idx]; - switch (block_byte & 0xC0) { - case 0x03 << 6: - integrator += compressed[extra_pos]; - extra_pos++; - break; - case 0x02 << 6: - integrator += block_code; - break; - case 0x00: - integrator -= block_code; - break; - } - decompressed[idx] = integrator; - block_byte <<= 2; - block_len -= 1; - } - } - *start_pos = extra_pos; - *block_typestart_pos = block_type_pos; - return idx; -} - - -/* - * usbvision_parse_compress() - * - * Parse compressed frame from the scratch buffer, put - * decoded RGB value into the current frame buffer and add the written - * number of bytes (RGB) to the *pcopylen. - * - */ -static enum parse_state usbvision_parse_compress(struct usb_usbvision *usbvision, - long *pcopylen) -{ -#define USBVISION_STRIP_MAGIC 0x5A -#define USBVISION_STRIP_LEN_MAX 400 -#define USBVISION_STRIP_HEADER_LEN 3 - - struct usbvision_frame *frame; - unsigned char *f, *u = NULL, *v = NULL; - unsigned char strip_data[USBVISION_STRIP_LEN_MAX]; - unsigned char strip_header[USBVISION_STRIP_HEADER_LEN]; - int idx, idx_end, strip_len, strip_ptr, startblock_pos, block_pos, block_type_pos; - int clipmask_index; - int image_size; - unsigned char rv, gv, bv; - static unsigned char *Y, *U, *V; - - frame = usbvision->cur_frame; - image_size = frame->frmwidth * frame->frmheight; - if ((frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) || - (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420)) { /* this is a planar format */ - /* ... v4l2_linesize not used here. */ - f = frame->data + (frame->width * frame->curline); - } else - f = frame->data + (frame->v4l2_linesize * frame->curline); - - if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { /* initialise u and v pointers */ - /* get base of u and b planes add halfoffset */ - u = frame->data - + image_size - + (frame->frmwidth >> 1) * frame->curline; - v = u + (image_size >> 1); - } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) { - v = frame->data + image_size + ((frame->curline * (frame->width)) >> 2); - u = v + (image_size >> 2); - } - - if (frame->curline == 0) - usbvision_adjust_compression(usbvision); - - if (scratch_len(usbvision) < USBVISION_STRIP_HEADER_LEN) - return parse_state_out; - - /* get strip header without changing the scratch_read_ptr */ - scratch_set_extra_ptr(usbvision, &strip_ptr, 0); - scratch_get_extra(usbvision, &strip_header[0], &strip_ptr, - USBVISION_STRIP_HEADER_LEN); - - if (strip_header[0] != USBVISION_STRIP_MAGIC) { - /* wrong strip magic */ - usbvision->strip_magic_errors++; - return parse_state_next_frame; - } - - if (frame->curline != (int)strip_header[2]) { - /* line number mismatch error */ - usbvision->strip_line_number_errors++; - } - - strip_len = 2 * (unsigned int)strip_header[1]; - if (strip_len > USBVISION_STRIP_LEN_MAX) { - /* strip overrun */ - /* I think this never happens */ - usbvision_request_intra(usbvision); - } - - if (scratch_len(usbvision) < strip_len) { - /* there is not enough data for the strip */ - return parse_state_out; - } - - if (usbvision->intra_frame_buffer) { - Y = usbvision->intra_frame_buffer + frame->frmwidth * frame->curline; - U = usbvision->intra_frame_buffer + image_size + (frame->frmwidth / 2) * (frame->curline / 2); - V = usbvision->intra_frame_buffer + image_size / 4 * 5 + (frame->frmwidth / 2) * (frame->curline / 2); - } else { - return parse_state_next_frame; - } - - clipmask_index = frame->curline * MAX_FRAME_WIDTH; - - scratch_get(usbvision, strip_data, strip_len); - - idx_end = frame->frmwidth; - block_type_pos = USBVISION_STRIP_HEADER_LEN; - startblock_pos = block_type_pos + (idx_end - 1) / 96 + (idx_end / 2 - 1) / 96 + 2; - block_pos = startblock_pos; - - usbvision->block_pos = block_pos; - - usbvision_decompress(usbvision, strip_data, Y, &block_pos, &block_type_pos, idx_end); - if (strip_len > usbvision->max_strip_len) - usbvision->max_strip_len = strip_len; - - if (frame->curline % 2) - usbvision_decompress(usbvision, strip_data, V, &block_pos, &block_type_pos, idx_end / 2); - else - usbvision_decompress(usbvision, strip_data, U, &block_pos, &block_type_pos, idx_end / 2); - - if (block_pos > usbvision->comprblock_pos) - usbvision->comprblock_pos = block_pos; - if (block_pos > strip_len) - usbvision->strip_len_errors++; - - for (idx = 0; idx < idx_end; idx++) { - if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f++ = Y[idx]; - *f++ = idx & 0x01 ? U[idx / 2] : V[idx / 2]; - } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) { - *f++ = Y[idx]; - if (idx & 0x01) - *u++ = U[idx >> 1]; - else - *v++ = V[idx >> 1]; - } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) { - *f++ = Y[idx]; - if (!((idx & 0x01) | (frame->curline & 0x01))) { - /* only need do this for 1 in 4 pixels */ - /* intraframe buffer is YUV420 format */ - *u++ = U[idx >> 1]; - *v++ = V[idx >> 1]; - } - } else { - YUV_TO_RGB_BY_THE_BOOK(Y[idx], U[idx / 2], V[idx / 2], rv, gv, bv); - switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_GREY: - *f++ = Y[idx]; - break; - case V4L2_PIX_FMT_RGB555: - *f++ = (0x1F & rv) | - (0xE0 & (gv << 5)); - *f++ = (0x03 & (gv >> 3)) | - (0x7C & (bv << 2)); - break; - case V4L2_PIX_FMT_RGB565: - *f++ = (0x1F & rv) | - (0xE0 & (gv << 5)); - *f++ = (0x07 & (gv >> 3)) | - (0xF8 & bv); - break; - case V4L2_PIX_FMT_RGB24: - *f++ = rv; - *f++ = gv; - *f++ = bv; - break; - case V4L2_PIX_FMT_RGB32: - *f++ = rv; - *f++ = gv; - *f++ = bv; - f++; - break; - } - } - clipmask_index++; - } - /* Deal with non-integer no. of bytes for YUV420P */ - if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420) - *pcopylen += frame->v4l2_linesize; - else - *pcopylen += frame->curline & 0x01 ? frame->v4l2_linesize : frame->v4l2_linesize << 1; - - frame->curline += 1; - - if (frame->curline >= frame->frmheight) - return parse_state_next_frame; - return parse_state_continue; - -} - - -/* - * usbvision_parse_lines_420() - * - * Parse two lines from the scratch buffer, put - * decoded RGB value into the current frame buffer and add the written - * number of bytes (RGB) to the *pcopylen. - * - */ -static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvision, - long *pcopylen) -{ - struct usbvision_frame *frame; - unsigned char *f_even = NULL, *f_odd = NULL; - unsigned int pixel_per_line, block; - int pixel, block_split; - int y_ptr, u_ptr, v_ptr, y_odd_offset; - const int y_block_size = 128; - const int uv_block_size = 64; - const int sub_block_size = 32; - const int y_step[] = { 0, 0, 0, 2 }, y_step_size = 4; - const int uv_step[] = { 0, 0, 0, 4 }, uv_step_size = 4; - unsigned char y[2], u, v; /* YUV components */ - int y_, u_, v_, vb, uvg, ur; - int r_, g_, b_; /* RGB components */ - unsigned char g; - int clipmask_even_index, clipmask_odd_index, bytes_per_pixel; - int clipmask_add, stretch_bytes; - - frame = usbvision->cur_frame; - f_even = frame->data + (frame->v4l2_linesize * frame->curline); - f_odd = f_even + frame->v4l2_linesize * usbvision->stretch_height; - - /* Make sure there's enough data for the entire line */ - /* In this mode usbvision transfer 3 bytes for every 2 pixels */ - /* I need two lines to decode the color */ - bytes_per_pixel = frame->v4l2_format.bytes_per_pixel; - stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel; - clipmask_even_index = frame->curline * MAX_FRAME_WIDTH; - clipmask_odd_index = clipmask_even_index + MAX_FRAME_WIDTH; - clipmask_add = usbvision->stretch_width; - pixel_per_line = frame->isoc_header.frame_width; - - if (scratch_len(usbvision) < (int)pixel_per_line * 3) { - /* printk(KERN_DEBUG "out of data, need %d\n", len); */ - return parse_state_out; - } - - if ((frame->curline + 1) >= frame->frmheight) - return parse_state_next_frame; - - block_split = (pixel_per_line%y_block_size) ? 1 : 0; /* are some blocks splitted into different lines? */ - - y_odd_offset = (pixel_per_line / y_block_size) * (y_block_size + uv_block_size) - + block_split * uv_block_size; - - scratch_set_extra_ptr(usbvision, &y_ptr, y_odd_offset); - scratch_set_extra_ptr(usbvision, &u_ptr, y_block_size); - scratch_set_extra_ptr(usbvision, &v_ptr, y_odd_offset - + (4 - block_split) * sub_block_size); - - for (block = 0; block < (pixel_per_line / sub_block_size); block++) { - for (pixel = 0; pixel < sub_block_size; pixel += 2) { - scratch_get(usbvision, &y[0], 2); - scratch_get_extra(usbvision, &u, &u_ptr, 1); - scratch_get_extra(usbvision, &v, &v_ptr, 1); - - /* I don't use the YUV_TO_RGB macro for better performance */ - v_ = v - 128; - u_ = u - 128; - vb = 132252 * v_; - uvg = -53281 * u_ - 25625 * v_; - ur = 104595 * u_; - - if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f_even++ = y[0]; - *f_even++ = v; - } else { - y_ = 76284 * (y[0] - 16); - - b_ = (y_ + vb) >> 16; - g_ = (y_ + uvg) >> 16; - r_ = (y_ + ur) >> 16; - - switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - g = LIMIT_RGB(g_); - *f_even++ = - (0x1F & LIMIT_RGB(r_)) | - (0xE0 & (g << 5)); - *f_even++ = - (0x07 & (g >> 3)) | - (0xF8 & LIMIT_RGB(b_)); - break; - case V4L2_PIX_FMT_RGB24: - *f_even++ = LIMIT_RGB(r_); - *f_even++ = LIMIT_RGB(g_); - *f_even++ = LIMIT_RGB(b_); - break; - case V4L2_PIX_FMT_RGB32: - *f_even++ = LIMIT_RGB(r_); - *f_even++ = LIMIT_RGB(g_); - *f_even++ = LIMIT_RGB(b_); - f_even++; - break; - case V4L2_PIX_FMT_RGB555: - g = LIMIT_RGB(g_); - *f_even++ = (0x1F & LIMIT_RGB(r_)) | - (0xE0 & (g << 5)); - *f_even++ = (0x03 & (g >> 3)) | - (0x7C & (LIMIT_RGB(b_) << 2)); - break; - } - } - clipmask_even_index += clipmask_add; - f_even += stretch_bytes; - - if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f_even++ = y[1]; - *f_even++ = u; - } else { - y_ = 76284 * (y[1] - 16); - - b_ = (y_ + vb) >> 16; - g_ = (y_ + uvg) >> 16; - r_ = (y_ + ur) >> 16; - - switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - g = LIMIT_RGB(g_); - *f_even++ = - (0x1F & LIMIT_RGB(r_)) | - (0xE0 & (g << 5)); - *f_even++ = - (0x07 & (g >> 3)) | - (0xF8 & LIMIT_RGB(b_)); - break; - case V4L2_PIX_FMT_RGB24: - *f_even++ = LIMIT_RGB(r_); - *f_even++ = LIMIT_RGB(g_); - *f_even++ = LIMIT_RGB(b_); - break; - case V4L2_PIX_FMT_RGB32: - *f_even++ = LIMIT_RGB(r_); - *f_even++ = LIMIT_RGB(g_); - *f_even++ = LIMIT_RGB(b_); - f_even++; - break; - case V4L2_PIX_FMT_RGB555: - g = LIMIT_RGB(g_); - *f_even++ = (0x1F & LIMIT_RGB(r_)) | - (0xE0 & (g << 5)); - *f_even++ = (0x03 & (g >> 3)) | - (0x7C & (LIMIT_RGB(b_) << 2)); - break; - } - } - clipmask_even_index += clipmask_add; - f_even += stretch_bytes; - - scratch_get_extra(usbvision, &y[0], &y_ptr, 2); - - if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f_odd++ = y[0]; - *f_odd++ = v; - } else { - y_ = 76284 * (y[0] - 16); - - b_ = (y_ + vb) >> 16; - g_ = (y_ + uvg) >> 16; - r_ = (y_ + ur) >> 16; - - switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - g = LIMIT_RGB(g_); - *f_odd++ = - (0x1F & LIMIT_RGB(r_)) | - (0xE0 & (g << 5)); - *f_odd++ = - (0x07 & (g >> 3)) | - (0xF8 & LIMIT_RGB(b_)); - break; - case V4L2_PIX_FMT_RGB24: - *f_odd++ = LIMIT_RGB(r_); - *f_odd++ = LIMIT_RGB(g_); - *f_odd++ = LIMIT_RGB(b_); - break; - case V4L2_PIX_FMT_RGB32: - *f_odd++ = LIMIT_RGB(r_); - *f_odd++ = LIMIT_RGB(g_); - *f_odd++ = LIMIT_RGB(b_); - f_odd++; - break; - case V4L2_PIX_FMT_RGB555: - g = LIMIT_RGB(g_); - *f_odd++ = (0x1F & LIMIT_RGB(r_)) | - (0xE0 & (g << 5)); - *f_odd++ = (0x03 & (g >> 3)) | - (0x7C & (LIMIT_RGB(b_) << 2)); - break; - } - } - clipmask_odd_index += clipmask_add; - f_odd += stretch_bytes; - - if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { - *f_odd++ = y[1]; - *f_odd++ = u; - } else { - y_ = 76284 * (y[1] - 16); - - b_ = (y_ + vb) >> 16; - g_ = (y_ + uvg) >> 16; - r_ = (y_ + ur) >> 16; - - switch (frame->v4l2_format.format) { - case V4L2_PIX_FMT_RGB565: - g = LIMIT_RGB(g_); - *f_odd++ = - (0x1F & LIMIT_RGB(r_)) | - (0xE0 & (g << 5)); - *f_odd++ = - (0x07 & (g >> 3)) | - (0xF8 & LIMIT_RGB(b_)); - break; - case V4L2_PIX_FMT_RGB24: - *f_odd++ = LIMIT_RGB(r_); - *f_odd++ = LIMIT_RGB(g_); - *f_odd++ = LIMIT_RGB(b_); - break; - case V4L2_PIX_FMT_RGB32: - *f_odd++ = LIMIT_RGB(r_); - *f_odd++ = LIMIT_RGB(g_); - *f_odd++ = LIMIT_RGB(b_); - f_odd++; - break; - case V4L2_PIX_FMT_RGB555: - g = LIMIT_RGB(g_); - *f_odd++ = (0x1F & LIMIT_RGB(r_)) | - (0xE0 & (g << 5)); - *f_odd++ = (0x03 & (g >> 3)) | - (0x7C & (LIMIT_RGB(b_) << 2)); - break; - } - } - clipmask_odd_index += clipmask_add; - f_odd += stretch_bytes; - } - - scratch_rm_old(usbvision, y_step[block % y_step_size] * sub_block_size); - scratch_inc_extra_ptr(&y_ptr, y_step[(block + 2 * block_split) % y_step_size] - * sub_block_size); - scratch_inc_extra_ptr(&u_ptr, uv_step[block % uv_step_size] - * sub_block_size); - scratch_inc_extra_ptr(&v_ptr, uv_step[(block + 2 * block_split) % uv_step_size] - * sub_block_size); - } - - scratch_rm_old(usbvision, pixel_per_line * 3 / 2 - + block_split * sub_block_size); - - frame->curline += 2 * usbvision->stretch_height; - *pcopylen += frame->v4l2_linesize * 2 * usbvision->stretch_height; - - if (frame->curline >= frame->frmheight) - return parse_state_next_frame; - return parse_state_continue; -} - -/* - * usbvision_parse_data() - * - * Generic routine to parse the scratch buffer. It employs either - * usbvision_find_header() or usbvision_parse_lines() to do most - * of work. - * - */ -static void usbvision_parse_data(struct usb_usbvision *usbvision) -{ - struct usbvision_frame *frame; - enum parse_state newstate; - long copylen = 0; - unsigned long lock_flags; - - frame = usbvision->cur_frame; - - PDEBUG(DBG_PARSE, "parsing len=%d\n", scratch_len(usbvision)); - - while (1) { - newstate = parse_state_out; - if (scratch_len(usbvision)) { - if (frame->scanstate == scan_state_scanning) { - newstate = usbvision_find_header(usbvision); - } else if (frame->scanstate == scan_state_lines) { - if (usbvision->isoc_mode == ISOC_MODE_YUV420) - newstate = usbvision_parse_lines_420(usbvision, ©len); - else if (usbvision->isoc_mode == ISOC_MODE_YUV422) - newstate = usbvision_parse_lines_422(usbvision, ©len); - else if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) - newstate = usbvision_parse_compress(usbvision, ©len); - } - } - if (newstate == parse_state_continue) - continue; - if ((newstate == parse_state_next_frame) || (newstate == parse_state_out)) - break; - return; /* parse_state_end_parse */ - } - - if (newstate == parse_state_next_frame) { - frame->grabstate = frame_state_done; - do_gettimeofday(&(frame->timestamp)); - frame->sequence = usbvision->frame_num; - - spin_lock_irqsave(&usbvision->queue_lock, lock_flags); - list_move_tail(&(frame->frame), &usbvision->outqueue); - usbvision->cur_frame = NULL; - spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); - - usbvision->frame_num++; - - /* This will cause the process to request another frame. */ - if (waitqueue_active(&usbvision->wait_frame)) { - PDEBUG(DBG_PARSE, "Wake up !"); - wake_up_interruptible(&usbvision->wait_frame); - } - } else { - frame->grabstate = frame_state_grabbing; - } - - /* Update the frame's uncompressed length. */ - frame->scanlength += copylen; -} - - -/* - * Make all of the blocks of data contiguous - */ -static int usbvision_compress_isochronous(struct usb_usbvision *usbvision, - struct urb *urb) -{ - unsigned char *packet_data; - int i, totlen = 0; - - for (i = 0; i < urb->number_of_packets; i++) { - int packet_len = urb->iso_frame_desc[i].actual_length; - int packet_stat = urb->iso_frame_desc[i].status; - - packet_data = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - - /* Detect and ignore errored packets */ - if (packet_stat) { /* packet_stat != 0 ????????????? */ - PDEBUG(DBG_ISOC, "data error: [%d] len=%d, status=%X", i, packet_len, packet_stat); - usbvision->isoc_err_count++; - continue; - } - - /* Detect and ignore empty packets */ - if (packet_len < 0) { - PDEBUG(DBG_ISOC, "error packet [%d]", i); - usbvision->isoc_skip_count++; - continue; - } else if (packet_len == 0) { /* Frame end ????? */ - PDEBUG(DBG_ISOC, "null packet [%d]", i); - usbvision->isocstate = isoc_state_no_frame; - usbvision->isoc_skip_count++; - continue; - } else if (packet_len > usbvision->isoc_packet_size) { - PDEBUG(DBG_ISOC, "packet[%d] > isoc_packet_size", i); - usbvision->isoc_skip_count++; - continue; - } - - PDEBUG(DBG_ISOC, "packet ok [%d] len=%d", i, packet_len); - - if (usbvision->isocstate == isoc_state_no_frame) { /* new frame begins */ - usbvision->isocstate = isoc_state_in_frame; - scratch_mark_header(usbvision); - usbvision_measure_bandwidth(usbvision); - PDEBUG(DBG_ISOC, "packet with header"); - } - - /* - * If usbvision continues to feed us with data but there is no - * consumption (if, for example, V4L client fell asleep) we - * may overflow the buffer. We have to move old data over to - * free room for new data. This is bad for old data. If we - * just drop new data then it's bad for new data... choose - * your favorite evil here. - */ - if (scratch_free(usbvision) < packet_len) { - usbvision->scratch_ovf_count++; - PDEBUG(DBG_ISOC, "scratch buf overflow! scr_len: %d, n: %d", - scratch_len(usbvision), packet_len); - scratch_rm_old(usbvision, packet_len - scratch_free(usbvision)); - } - - /* Now we know that there is enough room in scratch buffer */ - scratch_put(usbvision, packet_data, packet_len); - totlen += packet_len; - usbvision->isoc_data_count += packet_len; - usbvision->isoc_packet_count++; - } -#if ENABLE_HEXDUMP - if (totlen > 0) { - static int foo; - - if (foo < 1) { - printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen); - usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen); - ++foo; - } - } -#endif - return totlen; -} - -static void usbvision_isoc_irq(struct urb *urb) -{ - int err_code = 0; - int len; - struct usb_usbvision *usbvision = urb->context; - int i; - unsigned long start_time = jiffies; - struct usbvision_frame **f; - - /* We don't want to do anything if we are about to be removed! */ - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return; - - /* any urb with wrong status is ignored without acknowledgement */ - if (urb->status == -ENOENT) - return; - - f = &usbvision->cur_frame; - - /* Manage streaming interruption */ - if (usbvision->streaming == stream_interrupt) { - usbvision->streaming = stream_idle; - if ((*f)) { - (*f)->grabstate = frame_state_ready; - (*f)->scanstate = scan_state_scanning; - } - PDEBUG(DBG_IRQ, "stream interrupted"); - wake_up_interruptible(&usbvision->wait_stream); - } - - /* Copy the data received into our scratch buffer */ - len = usbvision_compress_isochronous(usbvision, urb); - - usbvision->isoc_urb_count++; - usbvision->urb_length = len; - - if (usbvision->streaming == stream_on) { - /* If we collected enough data let's parse! */ - if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH && - !list_empty(&(usbvision->inqueue))) { - if (!(*f)) { - (*f) = list_entry(usbvision->inqueue.next, - struct usbvision_frame, - frame); - } - usbvision_parse_data(usbvision); - } else { - /* If we don't have a frame - we're current working on, complain */ - PDEBUG(DBG_IRQ, - "received data, but no one needs it"); - scratch_reset(usbvision); - } - } else { - PDEBUG(DBG_IRQ, "received data, but no one needs it"); - scratch_reset(usbvision); - } - - usbvision->time_in_irq += jiffies - start_time; - - for (i = 0; i < USBVISION_URB_FRAMES; i++) { - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = 0; - } - - urb->status = 0; - urb->dev = usbvision->dev; - err_code = usb_submit_urb(urb, GFP_ATOMIC); - - if (err_code) { - dev_err(&usbvision->dev->dev, - "%s: usb_submit_urb failed: error %d\n", - __func__, err_code); - } - - return; -} - -/*************************************/ -/* Low level usbvision access functions */ -/*************************************/ - -/* - * usbvision_read_reg() - * - * return < 0 -> Error - * >= 0 -> Data - */ - -int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg) -{ - int err_code = 0; - unsigned char buffer[1]; - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return -1; - - err_code = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, - 0, (__u16) reg, buffer, 1, HZ); - - if (err_code < 0) { - dev_err(&usbvision->dev->dev, - "%s: failed: error %d\n", __func__, err_code); - return err_code; - } - return buffer[0]; -} - -/* - * usbvision_write_reg() - * - * return 1 -> Reg written - * 0 -> usbvision is not yet ready - * -1 -> Something went wrong - */ - -int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, - unsigned char value) -{ - int err_code = 0; - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return 0; - - err_code = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ); - - if (err_code < 0) { - dev_err(&usbvision->dev->dev, - "%s: failed: error %d\n", __func__, err_code); - } - return err_code; -} - - -static void usbvision_ctrl_urb_complete(struct urb *urb) -{ - struct usb_usbvision *usbvision = (struct usb_usbvision *)urb->context; - - PDEBUG(DBG_IRQ, ""); - usbvision->ctrl_urb_busy = 0; - if (waitqueue_active(&usbvision->ctrl_urb_wq)) - wake_up_interruptible(&usbvision->ctrl_urb_wq); -} - - -static int usbvision_write_reg_irq(struct usb_usbvision *usbvision, int address, - unsigned char *data, int len) -{ - int err_code = 0; - - PDEBUG(DBG_IRQ, ""); - if (len > 8) - return -EFAULT; - if (usbvision->ctrl_urb_busy) - return -EBUSY; - usbvision->ctrl_urb_busy = 1; - - usbvision->ctrl_urb_setup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; - usbvision->ctrl_urb_setup.bRequest = USBVISION_OP_CODE; - usbvision->ctrl_urb_setup.wValue = 0; - usbvision->ctrl_urb_setup.wIndex = cpu_to_le16(address); - usbvision->ctrl_urb_setup.wLength = cpu_to_le16(len); - usb_fill_control_urb(usbvision->ctrl_urb, usbvision->dev, - usb_sndctrlpipe(usbvision->dev, 1), - (unsigned char *)&usbvision->ctrl_urb_setup, - (void *)usbvision->ctrl_urb_buffer, len, - usbvision_ctrl_urb_complete, - (void *)usbvision); - - memcpy(usbvision->ctrl_urb_buffer, data, len); - - err_code = usb_submit_urb(usbvision->ctrl_urb, GFP_ATOMIC); - if (err_code < 0) { - /* error in usb_submit_urb() */ - usbvision->ctrl_urb_busy = 0; - } - PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, err_code); - return err_code; -} - - -static int usbvision_init_compression(struct usb_usbvision *usbvision) -{ - int err_code = 0; - - usbvision->last_isoc_frame_num = -1; - usbvision->isoc_data_count = 0; - usbvision->isoc_packet_count = 0; - usbvision->isoc_skip_count = 0; - usbvision->compr_level = 50; - usbvision->last_compr_level = -1; - usbvision->isoc_urb_count = 0; - usbvision->request_intra = 1; - usbvision->isoc_measure_bandwidth_count = 0; - - return err_code; -} - -/* this function measures the used bandwidth since last call - * return: 0 : no error - * sets used_bandwidth to 1-100 : 1-100% of full bandwidth resp. to isoc_packet_size - */ -static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision) -{ - int err_code = 0; - - if (usbvision->isoc_measure_bandwidth_count < 2) { /* this gives an average bandwidth of 3 frames */ - usbvision->isoc_measure_bandwidth_count++; - return err_code; - } - if ((usbvision->isoc_packet_size > 0) && (usbvision->isoc_packet_count > 0)) { - usbvision->used_bandwidth = usbvision->isoc_data_count / - (usbvision->isoc_packet_count + usbvision->isoc_skip_count) * - 100 / usbvision->isoc_packet_size; - } - usbvision->isoc_measure_bandwidth_count = 0; - usbvision->isoc_data_count = 0; - usbvision->isoc_packet_count = 0; - usbvision->isoc_skip_count = 0; - return err_code; -} - -static int usbvision_adjust_compression(struct usb_usbvision *usbvision) -{ - int err_code = 0; - unsigned char buffer[6]; - - PDEBUG(DBG_IRQ, ""); - if ((adjust_compression) && (usbvision->used_bandwidth > 0)) { - usbvision->compr_level += (usbvision->used_bandwidth - 90) / 2; - RESTRICT_TO_RANGE(usbvision->compr_level, 0, 100); - if (usbvision->compr_level != usbvision->last_compr_level) { - int distortion; - - if (usbvision->bridge_type == BRIDGE_NT1004 || usbvision->bridge_type == BRIDGE_NT1005) { - buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100); /* PCM Threshold 1 */ - buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100); /* PCM Threshold 2 */ - distortion = 7 + 248 * usbvision->compr_level / 100; - buffer[2] = (unsigned char)(distortion & 0xFF); /* Average distortion Threshold (inter) */ - buffer[3] = (unsigned char)(distortion & 0xFF); /* Average distortion Threshold (intra) */ - distortion = 1 + 42 * usbvision->compr_level / 100; - buffer[4] = (unsigned char)(distortion & 0xFF); /* Maximum distortion Threshold (inter) */ - buffer[5] = (unsigned char)(distortion & 0xFF); /* Maximum distortion Threshold (intra) */ - } else { /* BRIDGE_NT1003 */ - buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100); /* PCM threshold 1 */ - buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100); /* PCM threshold 2 */ - distortion = 2 + 253 * usbvision->compr_level / 100; - buffer[2] = (unsigned char)(distortion & 0xFF); /* distortion threshold bit0-7 */ - buffer[3] = 0; /* (unsigned char)((distortion >> 8) & 0x0F); distortion threshold bit 8-11 */ - distortion = 0 + 43 * usbvision->compr_level / 100; - buffer[4] = (unsigned char)(distortion & 0xFF); /* maximum distortion bit0-7 */ - buffer[5] = 0; /* (unsigned char)((distortion >> 8) & 0x01); maximum distortion bit 8 */ - } - err_code = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6); - if (err_code == 0) { - PDEBUG(DBG_IRQ, "new compr params %#02x %#02x %#02x %#02x %#02x %#02x", buffer[0], - buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); - usbvision->last_compr_level = usbvision->compr_level; - } - } - } - return err_code; -} - -static int usbvision_request_intra(struct usb_usbvision *usbvision) -{ - int err_code = 0; - unsigned char buffer[1]; - - PDEBUG(DBG_IRQ, ""); - usbvision->request_intra = 1; - buffer[0] = 1; - usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); - return err_code; -} - -static int usbvision_unrequest_intra(struct usb_usbvision *usbvision) -{ - int err_code = 0; - unsigned char buffer[1]; - - PDEBUG(DBG_IRQ, ""); - usbvision->request_intra = 0; - buffer[0] = 0; - usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); - return err_code; -} - -/******************************* - * usbvision utility functions - *******************************/ - -int usbvision_power_off(struct usb_usbvision *usbvision) -{ - int err_code = 0; - - PDEBUG(DBG_FUNC, ""); - - err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); - if (err_code == 1) - usbvision->power = 0; - PDEBUG(DBG_FUNC, "%s: err_code %d", (err_code != 1) ? "ERROR" : "power is off", err_code); - return err_code; -} - -/* configure webcam image sensor using the serial port */ -static int usbvision_init_webcam(struct usb_usbvision *usbvision) -{ - int rc; - int i; - static char init_values[38][3] = { - { 0x04, 0x12, 0x08 }, { 0x05, 0xff, 0xc8 }, { 0x06, 0x18, 0x07 }, { 0x07, 0x90, 0x00 }, - { 0x09, 0x00, 0x00 }, { 0x0a, 0x00, 0x00 }, { 0x0b, 0x08, 0x00 }, { 0x0d, 0xcc, 0xcc }, - { 0x0e, 0x13, 0x14 }, { 0x10, 0x9b, 0x83 }, { 0x11, 0x5a, 0x3f }, { 0x12, 0xe4, 0x73 }, - { 0x13, 0x88, 0x84 }, { 0x14, 0x89, 0x80 }, { 0x15, 0x00, 0x20 }, { 0x16, 0x00, 0x00 }, - { 0x17, 0xff, 0xa0 }, { 0x18, 0x6b, 0x20 }, { 0x19, 0x22, 0x40 }, { 0x1a, 0x10, 0x07 }, - { 0x1b, 0x00, 0x47 }, { 0x1c, 0x03, 0xe0 }, { 0x1d, 0x00, 0x00 }, { 0x1e, 0x00, 0x00 }, - { 0x1f, 0x00, 0x00 }, { 0x20, 0x00, 0x00 }, { 0x21, 0x00, 0x00 }, { 0x22, 0x00, 0x00 }, - { 0x23, 0x00, 0x00 }, { 0x24, 0x00, 0x00 }, { 0x25, 0x00, 0x00 }, { 0x26, 0x00, 0x00 }, - { 0x27, 0x00, 0x00 }, { 0x28, 0x00, 0x00 }, { 0x29, 0x00, 0x00 }, { 0x08, 0x80, 0x60 }, - { 0x0f, 0x2d, 0x24 }, { 0x0c, 0x80, 0x80 } - }; - char value[3]; - - /* the only difference between PAL and NTSC init_values */ - if (usbvision_device_data[usbvision->dev_model].video_norm == V4L2_STD_NTSC) - init_values[4][1] = 0x34; - - for (i = 0; i < sizeof(init_values) / 3; i++) { - usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT); - memcpy(value, init_values[i], 3); - rc = usb_control_msg(usbvision->dev, - usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_ENDPOINT, 0, - (__u16) USBVISION_SER_DAT1, value, - 3, HZ); - if (rc < 0) - return rc; - usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SIO); - /* write 3 bytes to the serial port using SIO mode */ - usbvision_write_reg(usbvision, USBVISION_SER_CONT, 3 | 0x10); - usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, 0); - usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT); - usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_IO_2); - usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_CLK_OUT); - usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_DAT_IO); - usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_CLK_OUT | USBVISION_DAT_IO); - } - - return 0; -} - -/* - * usbvision_set_video_format() - * - */ -static int usbvision_set_video_format(struct usb_usbvision *usbvision, int format) -{ - static const char proc[] = "usbvision_set_video_format"; - int rc; - unsigned char value[2]; - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return 0; - - PDEBUG(DBG_FUNC, "isoc_mode %#02x", format); - - if ((format != ISOC_MODE_YUV422) - && (format != ISOC_MODE_YUV420) - && (format != ISOC_MODE_COMPRESS)) { - printk(KERN_ERR "usbvision: unknown video format %02x, using default YUV420", - format); - format = ISOC_MODE_YUV420; - } - value[0] = 0x0A; /* TODO: See the effect of the filter */ - value[1] = format; /* Sets the VO_MODE register which follows FILT_CONT */ - rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_ENDPOINT, 0, - (__u16) USBVISION_FILT_CONT, value, 2, HZ); - - if (rc < 0) { - printk(KERN_ERR "%s: ERROR=%d. USBVISION stopped - " - "reconnect or reload driver.\n", proc, rc); - } - usbvision->isoc_mode = format; - return rc; -} - -/* - * usbvision_set_output() - * - */ - -int usbvision_set_output(struct usb_usbvision *usbvision, int width, - int height) -{ - int err_code = 0; - int usb_width, usb_height; - unsigned int frame_rate = 0, frame_drop = 0; - unsigned char value[4]; - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return 0; - - if (width > MAX_USB_WIDTH) { - usb_width = width / 2; - usbvision->stretch_width = 2; - } else { - usb_width = width; - usbvision->stretch_width = 1; - } - - if (height > MAX_USB_HEIGHT) { - usb_height = height / 2; - usbvision->stretch_height = 2; - } else { - usb_height = height; - usbvision->stretch_height = 1; - } - - RESTRICT_TO_RANGE(usb_width, MIN_FRAME_WIDTH, MAX_USB_WIDTH); - usb_width &= ~(MIN_FRAME_WIDTH-1); - RESTRICT_TO_RANGE(usb_height, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT); - usb_height &= ~(1); - - PDEBUG(DBG_FUNC, "usb %dx%d; screen %dx%d; stretch %dx%d", - usb_width, usb_height, width, height, - usbvision->stretch_width, usbvision->stretch_height); - - /* I'll not rewrite the same values */ - if ((usb_width != usbvision->curwidth) || (usb_height != usbvision->curheight)) { - value[0] = usb_width & 0xff; /* LSB */ - value[1] = (usb_width >> 8) & 0x03; /* MSB */ - value[2] = usb_height & 0xff; /* LSB */ - value[3] = (usb_height >> 8) & 0x03; /* MSB */ - - err_code = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, - 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ); - - if (err_code < 0) { - dev_err(&usbvision->dev->dev, - "%s failed: error %d\n", __func__, err_code); - return err_code; - } - usbvision->curwidth = usbvision->stretch_width * usb_width; - usbvision->curheight = usbvision->stretch_height * usb_height; - } - - if (usbvision->isoc_mode == ISOC_MODE_YUV422) - frame_rate = (usbvision->isoc_packet_size * 1000) / (usb_width * usb_height * 2); - else if (usbvision->isoc_mode == ISOC_MODE_YUV420) - frame_rate = (usbvision->isoc_packet_size * 1000) / ((usb_width * usb_height * 12) / 8); - else - frame_rate = FRAMERATE_MAX; - - if (usbvision->tvnorm_id & V4L2_STD_625_50) - frame_drop = frame_rate * 32 / 25 - 1; - else if (usbvision->tvnorm_id & V4L2_STD_525_60) - frame_drop = frame_rate * 32 / 30 - 1; - - RESTRICT_TO_RANGE(frame_drop, FRAMERATE_MIN, FRAMERATE_MAX); - - PDEBUG(DBG_FUNC, "frame_rate %d fps, frame_drop %d", frame_rate, frame_drop); - - frame_drop = FRAMERATE_MAX; /* We can allow the maximum here, because dropping is controlled */ - - if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) { - if (usbvision_device_data[usbvision->dev_model].video_norm == V4L2_STD_PAL) - frame_drop = 25; - else - frame_drop = 30; - } - - /* frame_drop = 7; => frame_phase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... - => frame_skip = 4; - => frame_rate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25; - - frame_drop = 9; => frame_phase = 1, 5, 8, 11, 14, 17, 21, 24, 27, 1, 4, 8, ... - => frame_skip = 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, ... - => frame_rate = (9 + 1) * 25 / 32 = 250 / 32 = 7.8125; - */ - err_code = usbvision_write_reg(usbvision, USBVISION_FRM_RATE, frame_drop); - return err_code; -} - - -/* - * usbvision_frames_alloc - * allocate the required frames - */ -int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames) -{ - int i; - - /* needs to be page aligned cause the buffers can be mapped individually! */ - usbvision->max_frame_size = PAGE_ALIGN(usbvision->curwidth * - usbvision->curheight * - usbvision->palette.bytes_per_pixel); - - /* Try to do my best to allocate the frames the user want in the remaining memory */ - usbvision->num_frames = number_of_frames; - while (usbvision->num_frames > 0) { - usbvision->fbuf_size = usbvision->num_frames * usbvision->max_frame_size; - usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size); - if (usbvision->fbuf) - break; - usbvision->num_frames--; - } - - spin_lock_init(&usbvision->queue_lock); - init_waitqueue_head(&usbvision->wait_frame); - init_waitqueue_head(&usbvision->wait_stream); - - /* Allocate all buffers */ - for (i = 0; i < usbvision->num_frames; i++) { - usbvision->frame[i].index = i; - usbvision->frame[i].grabstate = frame_state_unused; - usbvision->frame[i].data = usbvision->fbuf + - i * usbvision->max_frame_size; - /* - * Set default sizes for read operation. - */ - usbvision->stretch_width = 1; - usbvision->stretch_height = 1; - usbvision->frame[i].width = usbvision->curwidth; - usbvision->frame[i].height = usbvision->curheight; - usbvision->frame[i].bytes_read = 0; - } - PDEBUG(DBG_FUNC, "allocated %d frames (%d bytes per frame)", - usbvision->num_frames, usbvision->max_frame_size); - return usbvision->num_frames; -} - -/* - * usbvision_frames_free - * frees memory allocated for the frames - */ -void usbvision_frames_free(struct usb_usbvision *usbvision) -{ - /* Have to free all that memory */ - PDEBUG(DBG_FUNC, "free %d frames", usbvision->num_frames); - - if (usbvision->fbuf != NULL) { - usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size); - usbvision->fbuf = NULL; - - usbvision->num_frames = 0; - } -} -/* - * usbvision_empty_framequeues() - * prepare queues for incoming and outgoing frames - */ -void usbvision_empty_framequeues(struct usb_usbvision *usbvision) -{ - u32 i; - - INIT_LIST_HEAD(&(usbvision->inqueue)); - INIT_LIST_HEAD(&(usbvision->outqueue)); - - for (i = 0; i < USBVISION_NUMFRAMES; i++) { - usbvision->frame[i].grabstate = frame_state_unused; - usbvision->frame[i].bytes_read = 0; - } -} - -/* - * usbvision_stream_interrupt() - * stops streaming - */ -int usbvision_stream_interrupt(struct usb_usbvision *usbvision) -{ - int ret = 0; - - /* stop reading from the device */ - - usbvision->streaming = stream_interrupt; - ret = wait_event_timeout(usbvision->wait_stream, - (usbvision->streaming == stream_idle), - msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES)); - return ret; -} - -/* - * usbvision_set_compress_params() - * - */ - -static int usbvision_set_compress_params(struct usb_usbvision *usbvision) -{ - static const char proc[] = "usbvision_set_compresion_params: "; - int rc; - unsigned char value[6]; - - value[0] = 0x0F; /* Intra-Compression cycle */ - value[1] = 0x01; /* Reg.45 one line per strip */ - value[2] = 0x00; /* Reg.46 Force intra mode on all new frames */ - value[3] = 0x00; /* Reg.47 FORCE_UP <- 0 normal operation (not force) */ - value[4] = 0xA2; /* Reg.48 BUF_THR I'm not sure if this does something in not compressed mode. */ - value[5] = 0x00; /* Reg.49 DVI_YUV This has nothing to do with compression */ - - /* catched values for NT1004 */ - /* value[0] = 0xFF; Never apply intra mode automatically */ - /* value[1] = 0xF1; Use full frame height for virtual strip width; One line per strip */ - /* value[2] = 0x01; Force intra mode on all new frames */ - /* value[3] = 0x00; Strip size 400 Bytes; do not force up */ - /* value[4] = 0xA2; */ - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return 0; - - rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_ENDPOINT, 0, - (__u16) USBVISION_INTRA_CYC, value, 5, HZ); - - if (rc < 0) { - printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " - "reconnect or reload driver.\n", proc, rc); - return rc; - } - - if (usbvision->bridge_type == BRIDGE_NT1004) { - value[0] = 20; /* PCM Threshold 1 */ - value[1] = 12; /* PCM Threshold 2 */ - value[2] = 255; /* Distortion Threshold inter */ - value[3] = 255; /* Distortion Threshold intra */ - value[4] = 43; /* Max Distortion inter */ - value[5] = 43; /* Max Distortion intra */ - } else { - value[0] = 20; /* PCM Threshold 1 */ - value[1] = 12; /* PCM Threshold 2 */ - value[2] = 255; /* Distortion Threshold d7-d0 */ - value[3] = 0; /* Distortion Threshold d11-d8 */ - value[4] = 43; /* Max Distortion d7-d0 */ - value[5] = 0; /* Max Distortion d8 */ - } - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return 0; - - rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_ENDPOINT, 0, - (__u16) USBVISION_PCM_THR1, value, 6, HZ); - - if (rc < 0) { - printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " - "reconnect or reload driver.\n", proc, rc); - } - return rc; -} - - -/* - * usbvision_set_input() - * - * Set the input (saa711x, ...) size x y and other misc input params - * I've no idea if this parameters are right - * - */ -int usbvision_set_input(struct usb_usbvision *usbvision) -{ - static const char proc[] = "usbvision_set_input: "; - int rc; - unsigned char value[8]; - unsigned char dvi_yuv_value; - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return 0; - - /* Set input format expected from decoder*/ - if (usbvision_device_data[usbvision->dev_model].vin_reg1_override) { - value[0] = usbvision_device_data[usbvision->dev_model].vin_reg1; - } else if (usbvision_device_data[usbvision->dev_model].codec == CODEC_SAA7113) { - /* SAA7113 uses 8 bit output */ - value[0] = USBVISION_8_422_SYNC; - } else { - /* I'm sure only about d2-d0 [010] 16 bit 4:2:2 usin sync pulses - * as that is how saa7111 is configured */ - value[0] = USBVISION_16_422_SYNC; - /* | USBVISION_VSNC_POL | USBVISION_VCLK_POL);*/ - } - - rc = usbvision_write_reg(usbvision, USBVISION_VIN_REG1, value[0]); - if (rc < 0) { - printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " - "reconnect or reload driver.\n", proc, rc); - return rc; - } - - - if (usbvision->tvnorm_id & V4L2_STD_PAL) { - value[0] = 0xC0; - value[1] = 0x02; /* 0x02C0 -> 704 Input video line length */ - value[2] = 0x20; - value[3] = 0x01; /* 0x0120 -> 288 Input video n. of lines */ - value[4] = 0x60; - 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) { - value[0] = 0xC0; - value[1] = 0x02; /* 0x02C0 -> 704 Input video line length */ - value[2] = 0x20; - value[3] = 0x01; /* 0x0120 -> 288 Input video n. of lines */ - value[4] = 0x01; - value[5] = 0x00; /* 0x0001 -> 01 Input video h offset */ - value[6] = 0x01; - value[7] = 0x00; /* 0x0001 -> 01 Input video v offset */ - } else { /* V4L2_STD_NTSC */ - value[0] = 0xD0; - value[1] = 0x02; /* 0x02D0 -> 720 Input video line length */ - value[2] = 0xF0; - value[3] = 0x00; /* 0x00F0 -> 240 Input video number of lines */ - value[4] = 0x50; - value[5] = 0x00; /* 0x0050 -> 80 Input video h offset */ - value[6] = 0x10; - value[7] = 0x00; /* 0x0010 -> 16 Input video v offset */ - } - - /* webcam is only 480 pixels wide, both PAL and NTSC version */ - if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) { - value[0] = 0xe0; - value[1] = 0x01; /* 0x01E0 -> 480 Input video line length */ - } - - if (usbvision_device_data[usbvision->dev_model].x_offset >= 0) { - value[4] = usbvision_device_data[usbvision->dev_model].x_offset & 0xff; - value[5] = (usbvision_device_data[usbvision->dev_model].x_offset & 0x0300) >> 8; - } - - if (adjust_x_offset != -1) { - value[4] = adjust_x_offset & 0xff; - value[5] = (adjust_x_offset & 0x0300) >> 8; - } - - if (usbvision_device_data[usbvision->dev_model].y_offset >= 0) { - value[6] = usbvision_device_data[usbvision->dev_model].y_offset & 0xff; - value[7] = (usbvision_device_data[usbvision->dev_model].y_offset & 0x0300) >> 8; - } - - if (adjust_y_offset != -1) { - value[6] = adjust_y_offset & 0xff; - value[7] = (adjust_y_offset & 0x0300) >> 8; - } - - rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, /* USBVISION specific code */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, - (__u16) USBVISION_LXSIZE_I, value, 8, HZ); - if (rc < 0) { - printk(KERN_ERR "%sERROR=%d. USBVISION stopped - " - "reconnect or reload driver.\n", proc, rc); - return rc; - } - - - dvi_yuv_value = 0x00; /* U comes after V, Ya comes after U/V, Yb comes after Yb */ - - if (usbvision_device_data[usbvision->dev_model].dvi_yuv_override) { - dvi_yuv_value = usbvision_device_data[usbvision->dev_model].dvi_yuv; - } else if (usbvision_device_data[usbvision->dev_model].codec == CODEC_SAA7113) { - /* This changes as the fine sync control changes. Further investigation necessary */ - dvi_yuv_value = 0x06; - } - - return usbvision_write_reg(usbvision, USBVISION_DVI_YUV, dvi_yuv_value); -} - - -/* - * usbvision_set_dram_settings() - * - * Set the buffer address needed by the usbvision dram to operate - * This values has been taken with usbsnoop. - * - */ - -static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) -{ - int rc; - unsigned char value[8]; - - if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) { - value[0] = 0x42; - value[1] = 0x71; - value[2] = 0xff; - value[3] = 0x00; - value[4] = 0x98; - value[5] = 0xe0; - value[6] = 0x71; - value[7] = 0xff; - /* UR: 0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte) */ - /* FDL: 0x00000-0x0E099 = 57498 Words */ - /* VDW: 0x0E3FF-0x3FFFF */ - } else { - value[0] = 0x42; - value[1] = 0x00; - value[2] = 0xff; - value[3] = 0x00; - value[4] = 0x00; - value[5] = 0x00; - value[6] = 0x00; - value[7] = 0xff; - } - /* These are the values of the address of the video buffer, - * they have to be loaded into the USBVISION_DRM_PRM1-8 - * - * Start address of video output buffer for read: drm_prm1-2 -> 0x00000 - * End address of video output buffer for read: drm_prm1-3 -> 0x1ffff - * Start address of video frame delay buffer: drm_prm1-4 -> 0x20000 - * Only used in compressed mode - * End address of video frame delay buffer: drm_prm1-5-6 -> 0x3ffff - * Only used in compressed mode - * Start address of video output buffer for write: drm_prm1-7 -> 0x00000 - * End address of video output buffer for write: drm_prm1-8 -> 0x1ffff - */ - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return 0; - - rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, /* USBVISION specific code */ - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_ENDPOINT, 0, - (__u16) USBVISION_DRM_PRM1, value, 8, HZ); - - if (rc < 0) { - dev_err(&usbvision->dev->dev, "%s: ERROR=%d\n", __func__, rc); - return rc; - } - - /* Restart the video buffer logic */ - rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, USBVISION_RES_UR | - USBVISION_RES_FDL | USBVISION_RES_VDW); - if (rc < 0) - return rc; - rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, 0x00); - - return rc; -} - -/* - * () - * - * Power on the device, enables suspend-resume logic - * & reset the isoc End-Point - * - */ - -int usbvision_power_on(struct usb_usbvision *usbvision) -{ - int err_code = 0; - - PDEBUG(DBG_FUNC, ""); - - usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); - usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_RES2); - - if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) { - usbvision_write_reg(usbvision, USBVISION_VIN_REG1, - USBVISION_16_422_SYNC | USBVISION_HVALID_PO); - usbvision_write_reg(usbvision, USBVISION_VIN_REG2, - USBVISION_NOHVALID | USBVISION_KEEP_BLANK); - } - usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_PWR_VID); - mdelay(10); - err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2); - if (err_code == 1) - usbvision->power = 1; - PDEBUG(DBG_FUNC, "%s: err_code %d", (err_code < 0) ? "ERROR" : "power is on", err_code); - return err_code; -} - - -/* - * usbvision timer stuff - */ - -/* to call usbvision_power_off from task queue */ -static void call_usbvision_power_off(struct work_struct *work) -{ - struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, power_off_work); - - PDEBUG(DBG_FUNC, ""); - if (mutex_lock_interruptible(&usbvision->v4l2_lock)) - return; - - if (usbvision->user == 0) { - usbvision_i2c_unregister(usbvision); - - usbvision_power_off(usbvision); - usbvision->initialized = 0; - } - mutex_unlock(&usbvision->v4l2_lock); -} - -static void usbvision_power_off_timer(unsigned long data) -{ - struct usb_usbvision *usbvision = (void *)data; - - PDEBUG(DBG_FUNC, ""); - del_timer(&usbvision->power_off_timer); - INIT_WORK(&usbvision->power_off_work, call_usbvision_power_off); - (void) schedule_work(&usbvision->power_off_work); -} - -void usbvision_init_power_off_timer(struct usb_usbvision *usbvision) -{ - init_timer(&usbvision->power_off_timer); - usbvision->power_off_timer.data = (long)usbvision; - usbvision->power_off_timer.function = usbvision_power_off_timer; -} - -void usbvision_set_power_off_timer(struct usb_usbvision *usbvision) -{ - mod_timer(&usbvision->power_off_timer, jiffies + USBVISION_POWEROFF_TIME); -} - -void usbvision_reset_power_off_timer(struct usb_usbvision *usbvision) -{ - if (timer_pending(&usbvision->power_off_timer)) - del_timer(&usbvision->power_off_timer); -} - -/* - * usbvision_begin_streaming() - * Sure you have to put bit 7 to 0, if not incoming frames are droped, but no - * idea about the rest - */ -int usbvision_begin_streaming(struct usb_usbvision *usbvision) -{ - if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) - usbvision_init_compression(usbvision); - return usbvision_write_reg(usbvision, USBVISION_VIN_REG2, - USBVISION_NOHVALID | usbvision->vin_reg2_preset); -} - -/* - * usbvision_restart_isoc() - * Not sure yet if touching here PWR_REG make loose the config - */ - -int usbvision_restart_isoc(struct usb_usbvision *usbvision) -{ - int ret; - - ret = usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_PWR_VID); - if (ret < 0) - return ret; - ret = usbvision_write_reg(usbvision, USBVISION_PWR_REG, - USBVISION_SSPND_EN | USBVISION_PWR_VID | - USBVISION_RES2); - if (ret < 0) - return ret; - ret = usbvision_write_reg(usbvision, USBVISION_VIN_REG2, - USBVISION_KEEP_BLANK | USBVISION_NOHVALID | - usbvision->vin_reg2_preset); - if (ret < 0) - return ret; - - /* TODO: schedule timeout */ - while ((usbvision_read_reg(usbvision, USBVISION_STATUS_REG) & 0x01) != 1) - ; - - return 0; -} - -int usbvision_audio_off(struct usb_usbvision *usbvision) -{ - if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_AUDIO_MUTE) < 0) { - printk(KERN_ERR "usbvision_audio_off: can't write reg\n"); - return -1; - } - usbvision->audio_mute = 0; - usbvision->audio_channel = USBVISION_AUDIO_MUTE; - return 0; -} - -int usbvision_set_audio(struct usb_usbvision *usbvision, int audio_channel) -{ - if (!usbvision->audio_mute) { - if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, audio_channel) < 0) { - printk(KERN_ERR "usbvision_set_audio: can't write iopin register for audio switching\n"); - return -1; - } - } - usbvision->audio_channel = audio_channel; - return 0; -} - -int usbvision_setup(struct usb_usbvision *usbvision, int format) -{ - if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) - usbvision_init_webcam(usbvision); - usbvision_set_video_format(usbvision, format); - usbvision_set_dram_settings(usbvision); - usbvision_set_compress_params(usbvision); - usbvision_set_input(usbvision); - usbvision_set_output(usbvision, MAX_USB_WIDTH, MAX_USB_HEIGHT); - usbvision_restart_isoc(usbvision); - - /* cosas del PCM */ - return USBVISION_IS_OPERATIONAL(usbvision); -} - -int usbvision_set_alternate(struct usb_usbvision *dev) -{ - int err_code, prev_alt = dev->iface_alt; - int i; - - dev->iface_alt = 0; - for (i = 0; i < dev->num_alt; i++) - if (dev->alt_max_pkt_size[i] > dev->alt_max_pkt_size[dev->iface_alt]) - dev->iface_alt = i; - - if (dev->iface_alt != prev_alt) { - dev->isoc_packet_size = dev->alt_max_pkt_size[dev->iface_alt]; - PDEBUG(DBG_FUNC, "setting alternate %d with max_packet_size=%u", - dev->iface_alt, dev->isoc_packet_size); - err_code = usb_set_interface(dev->dev, dev->iface, dev->iface_alt); - if (err_code < 0) { - dev_err(&dev->dev->dev, - "cannot change alternate number to %d (error=%i)\n", - dev->iface_alt, err_code); - return err_code; - } - } - - PDEBUG(DBG_ISOC, "ISO Packet Length:%d", dev->isoc_packet_size); - - return 0; -} - -/* - * usbvision_init_isoc() - * - */ -int usbvision_init_isoc(struct usb_usbvision *usbvision) -{ - struct usb_device *dev = usbvision->dev; - int buf_idx, err_code, reg_value; - int sb_size; - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return -EFAULT; - - usbvision->cur_frame = NULL; - scratch_reset(usbvision); - - /* Alternate interface 1 is is the biggest frame size */ - err_code = usbvision_set_alternate(usbvision); - if (err_code < 0) { - usbvision->last_error = err_code; - return -EBUSY; - } - sb_size = USBVISION_URB_FRAMES * usbvision->isoc_packet_size; - - reg_value = (16 - usbvision_read_reg(usbvision, - USBVISION_ALTER_REG)) & 0x0F; - - usbvision->usb_bandwidth = reg_value >> 1; - PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", - usbvision->usb_bandwidth); - - - - /* We double buffer the Iso lists */ - - for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) { - int j, k; - struct urb *urb; - - urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); - if (urb == NULL) { - dev_err(&usbvision->dev->dev, - "%s: usb_alloc_urb() failed\n", __func__); - return -ENOMEM; - } - usbvision->sbuf[buf_idx].urb = urb; - usbvision->sbuf[buf_idx].data = - usb_alloc_coherent(usbvision->dev, - sb_size, - GFP_KERNEL, - &urb->transfer_dma); - urb->dev = dev; - urb->context = usbvision; - urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp); - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - urb->interval = 1; - urb->transfer_buffer = usbvision->sbuf[buf_idx].data; - urb->complete = usbvision_isoc_irq; - urb->number_of_packets = USBVISION_URB_FRAMES; - urb->transfer_buffer_length = - usbvision->isoc_packet_size * USBVISION_URB_FRAMES; - for (j = k = 0; j < USBVISION_URB_FRAMES; j++, - k += usbvision->isoc_packet_size) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = - usbvision->isoc_packet_size; - } - } - - /* Submit all URBs */ - for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) { - err_code = usb_submit_urb(usbvision->sbuf[buf_idx].urb, - GFP_KERNEL); - if (err_code) { - dev_err(&usbvision->dev->dev, - "%s: usb_submit_urb(%d) failed: error %d\n", - __func__, buf_idx, err_code); - } - } - - usbvision->streaming = stream_idle; - PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", - __func__, - usbvision->video_endp); - return 0; -} - -/* - * usbvision_stop_isoc() - * - * This procedure stops streaming and deallocates URBs. Then it - * activates zero-bandwidth alt. setting of the video interface. - * - */ -void usbvision_stop_isoc(struct usb_usbvision *usbvision) -{ - int buf_idx, err_code, reg_value; - int sb_size = USBVISION_URB_FRAMES * usbvision->isoc_packet_size; - - if ((usbvision->streaming == stream_off) || (usbvision->dev == NULL)) - return; - - /* Unschedule all of the iso td's */ - for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) { - usb_kill_urb(usbvision->sbuf[buf_idx].urb); - if (usbvision->sbuf[buf_idx].data) { - usb_free_coherent(usbvision->dev, - sb_size, - usbvision->sbuf[buf_idx].data, - usbvision->sbuf[buf_idx].urb->transfer_dma); - } - usb_free_urb(usbvision->sbuf[buf_idx].urb); - usbvision->sbuf[buf_idx].urb = NULL; - } - - PDEBUG(DBG_ISOC, "%s: streaming=stream_off\n", __func__); - usbvision->streaming = stream_off; - - if (!usbvision->remove_pending) { - /* Set packet size to 0 */ - usbvision->iface_alt = 0; - err_code = usb_set_interface(usbvision->dev, usbvision->iface, - usbvision->iface_alt); - if (err_code < 0) { - dev_err(&usbvision->dev->dev, - "%s: usb_set_interface() failed: error %d\n", - __func__, err_code); - usbvision->last_error = err_code; - } - reg_value = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; - usbvision->isoc_packet_size = - (reg_value == 0) ? 0 : (reg_value * 64) - 1; - PDEBUG(DBG_ISOC, "ISO Packet Length:%d", - usbvision->isoc_packet_size); - - usbvision->usb_bandwidth = reg_value >> 1; - PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", - usbvision->usb_bandwidth); - } -} - -int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) -{ - /* inputs #0 and #3 are constant for every SAA711x. */ - /* inputs #1 and #2 are variable for SAA7111 and SAA7113 */ - int mode[4] = { SAA7115_COMPOSITE0, 0, 0, SAA7115_COMPOSITE3 }; - int audio[] = { 1, 0, 0, 0 }; - /* channel 0 is TV with audiochannel 1 (tuner mono) */ - /* channel 1 is Composite with audio channel 0 (line in) */ - /* channel 2 is S-Video with audio channel 0 (line in) */ - /* channel 3 is additional video inputs to the device with audio channel 0 (line in) */ - - RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs); - usbvision->ctl_input = channel; - - /* set the new channel */ - /* Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video */ - /* Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red */ - - switch (usbvision_device_data[usbvision->dev_model].codec) { - case CODEC_SAA7113: - mode[1] = SAA7115_COMPOSITE2; - if (switch_svideo_input) { - /* To handle problems with S-Video Input for - * some devices. Use switch_svideo_input - * parameter when loading the module.*/ - mode[2] = SAA7115_COMPOSITE1; - } else { - mode[2] = SAA7115_SVIDEO1; - } - break; - case CODEC_SAA7111: - default: - /* modes for saa7111 */ - mode[1] = SAA7115_COMPOSITE1; - mode[2] = SAA7115_SVIDEO1; - break; - } - call_all(usbvision, video, s_routing, mode[channel], 0, 0); - usbvision_set_audio(usbvision, audio[channel]); - return 0; -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c deleted file mode 100644 index 89fec029e924..000000000000 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ /dev/null @@ -1,456 +0,0 @@ -/* - * usbvision_i2c.c - * i2c algorithm for USB-I2C Bridges - * - * Copyright (c) 1999-2007 Joerg Heckenbach <joerg@heckenbach-aw.de> - * Dwaine Garden <dwainegarden@rogers.com> - * - * This module is part of usbvision driver project. - * Updates to driver completed by Dwaine P. Garden - * - * 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 <linux/kernel.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/uaccess.h> -#include <linux/ioport.h> -#include <linux/errno.h> -#include <linux/usb.h> -#include <linux/i2c.h> -#include "usbvision.h" - -#define DBG_I2C (1 << 0) - -static int i2c_debug; - -module_param(i2c_debug, int, 0644); /* debug_i2c_usb mode of the device driver */ -MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); - -#define PDEBUG(level, fmt, args...) { \ - if (i2c_debug & (level)) \ - printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \ - __func__, __LINE__ , ## args); \ - } - -static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf, - short len); -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) -{ - struct usb_usbvision *usbvision; - int i, ret = -1; - char buf[4]; - - usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap); - buf[0] = 0x00; - for (i = 0; i <= retries; i++) { - ret = (usbvision_i2c_write(usbvision, addr, buf, 1)); - if (ret == 1) - break; /* success! */ - udelay(5); - if (i == retries) /* no success */ - break; - udelay(10); - } - if (i) { - PDEBUG(DBG_I2C, "Needed %d retries for address %#2x", i, addr); - PDEBUG(DBG_I2C, "Maybe there's no device at this address"); - } - return ret; -} - -static inline int try_read_address(struct i2c_adapter *i2c_adap, - unsigned char addr, int retries) -{ - struct usb_usbvision *usbvision; - int i, ret = -1; - char buf[4]; - - usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap); - for (i = 0; i <= retries; i++) { - ret = (usbvision_i2c_read(usbvision, addr, buf, 1)); - if (ret == 1) - break; /* success! */ - udelay(5); - if (i == retries) /* no success */ - break; - udelay(10); - } - if (i) { - PDEBUG(DBG_I2C, "Needed %d retries for address %#2x", i, addr); - PDEBUG(DBG_I2C, "Maybe there's no device at this address"); - } - return ret; -} - -static inline int usb_find_address(struct i2c_adapter *i2c_adap, - struct i2c_msg *msg, int retries, - unsigned char *add) -{ - unsigned short flags = msg->flags; - - unsigned char addr; - int ret; - - addr = (msg->addr << 1); - if (flags & I2C_M_RD) - addr |= 1; - - add[0] = addr; - if (flags & I2C_M_RD) - ret = try_read_address(i2c_adap, addr, retries); - else - ret = try_write_address(i2c_adap, addr, retries); - - if (ret != 1) - return -EREMOTEIO; - - return 0; -} - -static int -usbvision_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) -{ - struct i2c_msg *pmsg; - struct usb_usbvision *usbvision; - int i, ret; - unsigned char addr = 0; - - 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_I2C, "got NAK from device, message #%d", i); - return (ret < 0) ? ret : -EREMOTEIO; - } - - if (pmsg->flags & I2C_M_RD) { - /* read bytes into buffer */ - ret = (usbvision_i2c_read(usbvision, addr, pmsg->buf, pmsg->len)); - if (ret < pmsg->len) - return (ret < 0) ? ret : -EREMOTEIO; - } else { - /* write bytes from buffer */ - ret = (usbvision_i2c_write(usbvision, addr, pmsg->buf, pmsg->len)); - if (ret < pmsg->len) - return (ret < 0) ? ret : -EREMOTEIO; - } - } - return num; -} - -static u32 functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -/* -----exported algorithm data: ------------------------------------- */ - -static struct i2c_algorithm usbvision_algo = { - .master_xfer = usbvision_i2c_xfer, - .smbus_xfer = NULL, - .functionality = functionality, -}; - - -/* ----------------------------------------------------------------------- */ -/* usbvision specific I2C functions */ -/* ----------------------------------------------------------------------- */ -static struct i2c_adapter i2c_adap_template; - -int usbvision_i2c_register(struct usb_usbvision *usbvision) -{ - static unsigned short saa711x_addrs[] = { - 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */ - 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */ - I2C_CLIENT_END }; - - if (usbvision->registered_i2c) - return 0; - - memcpy(&usbvision->i2c_adap, &i2c_adap_template, - sizeof(struct i2c_adapter)); - - sprintf(usbvision->i2c_adap.name, "%s-%d-%s", i2c_adap_template.name, - usbvision->dev->bus->busnum, usbvision->dev->devpath); - PDEBUG(DBG_I2C, "Adaptername: %s", usbvision->i2c_adap.name); - usbvision->i2c_adap.dev.parent = &usbvision->dev->dev; - - i2c_set_adapdata(&usbvision->i2c_adap, &usbvision->v4l2_dev); - - if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) { - printk(KERN_ERR "usbvision_i2c_register: can't write reg\n"); - return -EBUSY; - } - - PDEBUG(DBG_I2C, "I2C debugging is enabled [i2c]"); - PDEBUG(DBG_I2C, "ALGO debugging is enabled [i2c]"); - - /* register new adapter to i2c module... */ - - usbvision->i2c_adap.algo = &usbvision_algo; - - usbvision->i2c_adap.timeout = 100; /* default values, should */ - usbvision->i2c_adap.retries = 3; /* be replaced by defines */ - - i2c_add_adapter(&usbvision->i2c_adap); - - PDEBUG(DBG_I2C, "i2c bus for %s registered", usbvision->i2c_adap.name); - - /* Request the load of the i2c modules we need */ - switch (usbvision_device_data[usbvision->dev_model].codec) { - case CODEC_SAA7113: - case CODEC_SAA7111: - /* Without this delay the detection of the saa711x is - hit-and-miss. */ - mdelay(10); - v4l2_i2c_new_subdev(&usbvision->v4l2_dev, - &usbvision->i2c_adap, - "saa7115_auto", 0, saa711x_addrs); - break; - } - if (usbvision_device_data[usbvision->dev_model].tuner == 1) { - struct v4l2_subdev *sd; - enum v4l2_i2c_tuner_type type; - struct tuner_setup tun_setup; - - sd = v4l2_i2c_new_subdev(&usbvision->v4l2_dev, - &usbvision->i2c_adap, - "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); - /* depending on whether we found a demod or not, select - the tuner type. */ - type = sd ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; - - sd = v4l2_i2c_new_subdev(&usbvision->v4l2_dev, - &usbvision->i2c_adap, - "tuner", 0, v4l2_i2c_tuner_addrs(type)); - - if (sd == NULL) - return -ENODEV; - if (usbvision->tuner_type != -1) { - tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; - tun_setup.type = usbvision->tuner_type; - tun_setup.addr = v4l2_i2c_subdev_addr(sd); - call_all(usbvision, tuner, s_type_addr, &tun_setup); - } - } - usbvision->registered_i2c = 1; - - return 0; -} - -int usbvision_i2c_unregister(struct usb_usbvision *usbvision) -{ - if (!usbvision->registered_i2c) - return 0; - - i2c_del_adapter(&(usbvision->i2c_adap)); - usbvision->registered_i2c = 0; - - PDEBUG(DBG_I2C, "i2c bus for %s unregistered", usbvision->i2c_adap.name); - - return 0; -} - -static int -usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr, - char *buf, short len) -{ - int rc, retries; - - for (retries = 5;;) { - rc = usbvision_write_reg(usbvision, USBVISION_SER_ADRS, addr); - if (rc < 0) - return rc; - - /* Initiate byte read cycle */ - /* USBVISION_SER_CONT <- d0-d2 n. of bytes to r/w */ - /* d3 0=Wr 1=Rd */ - rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, - (len & 0x07) | 0x18); - if (rc < 0) - return rc; - - /* Test for Busy and ACK */ - do { - /* USBVISION_SER_CONT -> d4 == 0 busy */ - rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT); - } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */ - if (rc < 0) - return rc; - - /* USBVISION_SER_CONT -> d5 == 1 Not ack */ - if ((rc & 0x20) == 0) /* Ack? */ - break; - - /* I2C abort */ - rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00); - if (rc < 0) - return rc; - - if (--retries < 0) - return -1; - } - - switch (len) { - case 4: - buf[3] = usbvision_read_reg(usbvision, USBVISION_SER_DAT4); - case 3: - buf[2] = usbvision_read_reg(usbvision, USBVISION_SER_DAT3); - case 2: - buf[1] = usbvision_read_reg(usbvision, USBVISION_SER_DAT2); - case 1: - buf[0] = usbvision_read_reg(usbvision, USBVISION_SER_DAT1); - break; - default: - printk(KERN_ERR - "usbvision_i2c_read_max4: buffer length > 4\n"); - } - - if (i2c_debug & DBG_I2C) { - int idx; - - for (idx = 0; idx < len; idx++) - PDEBUG(DBG_I2C, "read %x from address %x", (unsigned char)buf[idx], addr); - } - return len; -} - - -static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision, - unsigned char addr, const char *buf, - short len) -{ - int rc, retries; - int i; - unsigned char value[6]; - unsigned char ser_cont; - - ser_cont = (len & 0x07) | 0x10; - - value[0] = addr; - value[1] = ser_cont; - for (i = 0; i < len; i++) - value[i + 2] = buf[i]; - - for (retries = 5;;) { - rc = usb_control_msg(usbvision->dev, - usb_sndctrlpipe(usbvision->dev, 1), - USBVISION_OP_CODE, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_ENDPOINT, 0, - (__u16) USBVISION_SER_ADRS, value, - len + 2, HZ); - - if (rc < 0) - return rc; - - rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, - (len & 0x07) | 0x10); - if (rc < 0) - return rc; - - /* Test for Busy and ACK */ - do { - rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT); - } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */ - if (rc < 0) - return rc; - - if ((rc & 0x20) == 0) /* Ack? */ - break; - - /* I2C abort */ - usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00); - - if (--retries < 0) - return -1; - - } - - if (i2c_debug & DBG_I2C) { - int idx; - - for (idx = 0; idx < len; idx++) - PDEBUG(DBG_I2C, "wrote %x at address %x", (unsigned char)buf[idx], addr); - } - return len; -} - -static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf, - short len) -{ - char *buf_ptr = buf; - int retval; - int wrcount = 0; - int count; - int max_len = 4; - - while (len > 0) { - count = (len > max_len) ? max_len : len; - retval = usbvision_i2c_write_max4(usbvision, addr, buf_ptr, count); - if (retval > 0) { - len -= count; - buf_ptr += count; - wrcount += count; - } else - return (retval < 0) ? retval : -EFAULT; - } - return wrcount; -} - -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; - - while (len > 0) { - count = (len > 3) ? 4 : len; - retval = usbvision_i2c_read_max4(usbvision, addr, temp, count); - if (retval > 0) { - for (i = 0; i < len; i++) - buf[rdcount + i] = temp[i]; - len -= count; - rdcount += count; - } else - return (retval < 0) ? retval : -EFAULT; - } - return rdcount; -} - -static struct i2c_adapter i2c_adap_template = { - .owner = THIS_MODULE, - .name = "usbvision", -}; - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c deleted file mode 100644 index 8a4317979a43..000000000000 --- a/drivers/media/video/usbvision/usbvision-video.c +++ /dev/null @@ -1,1720 +0,0 @@ -/* - * USB USBVISION Video device driver 0.9.10 - * - * - * - * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> - * - * This module is part of usbvision driver project. - * - * 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. - * - * Let's call the version 0.... until compression decoding is completely - * implemented. - * - * This driver is written by Jose Ignacio Gijon and Joerg Heckenbach. - * It was based on USB CPiA driver written by Peter Pregler, - * Scott J. Bertin and Johannes Erdfelt - * Ideas are taken from bttv driver by Ralph Metzler, Marcus Metzler & - * Gerd Knorr and zoran 36120/36125 driver by Pauline Middelink - * Updates to driver completed by Dwaine P. Garden - * - * - * TODO: - * - 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? - * - Clean up the driver. - * - optimization for performance. - * - Add Videotext capability (VBI). Working on it..... - * - Check audio for other devices - * - */ - -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/timer.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/highmem.h> -#include <linux/vmalloc.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/io.h> -#include <linux/videodev2.h> -#include <linux/i2c.h> - -#include <media/saa7115.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <media/tuner.h> - -#include <linux/workqueue.h> - -#include "usbvision.h" -#include "usbvision-cards.h" - -#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" -#define DRIVER_LICENSE "GPL" -#define USBVISION_VERSION_STRING "0.9.11" - -#define ENABLE_HEXDUMP 0 /* Enable if you need it */ - - -#ifdef USBVISION_DEBUG - #define PDEBUG(level, fmt, args...) { \ - if (video_debug & (level)) \ - printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \ - __func__, __LINE__ , ## args); \ - } -#else - #define PDEBUG(level, fmt, args...) do {} while (0) -#endif - -#define DBG_IO (1 << 1) -#define DBG_PROBE (1 << 2) -#define DBG_MMAP (1 << 3) - -/* String operations */ -#define rmspace(str) while (*str == ' ') str++; -#define goto2next(str) while (*str != ' ') str++; while (*str == ' ') str++; - - -/* sequential number of usbvision device */ -static int usbvision_nr; - -static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = { - { 1, 1, 8, V4L2_PIX_FMT_GREY , "GREY" }, - { 1, 2, 16, V4L2_PIX_FMT_RGB565 , "RGB565" }, - { 1, 3, 24, V4L2_PIX_FMT_RGB24 , "RGB24" }, - { 1, 4, 32, V4L2_PIX_FMT_RGB32 , "RGB32" }, - { 1, 2, 16, V4L2_PIX_FMT_RGB555 , "RGB555" }, - { 1, 2, 16, V4L2_PIX_FMT_YUYV , "YUV422" }, - { 1, 2, 12, V4L2_PIX_FMT_YVU420 , "YUV420P" }, /* 1.5 ! */ - { 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" } -}; - -/* Function prototypes */ -static void usbvision_release(struct usb_usbvision *usbvision); - -/* Default initialization of device driver parameters */ -/* Set the default format for ISOC endpoint */ -static int isoc_mode = ISOC_MODE_COMPRESS; -/* Set the default Debug Mode of the device driver */ -static int video_debug; -/* Set the default device to power on at startup */ -static int power_on_at_open = 1; -/* Sequential Number of Video Device */ -static int video_nr = -1; -/* Sequential Number of Radio Device */ -static int radio_nr = -1; - -/* Grab parameters for the device driver */ - -/* Showing parameters under SYSFS */ -module_param(isoc_mode, int, 0444); -module_param(video_debug, int, 0444); -module_param(power_on_at_open, int, 0444); -module_param(video_nr, int, 0444); -module_param(radio_nr, int, 0444); - -MODULE_PARM_DESC(isoc_mode, " Set the default format for ISOC endpoint. Default: 0x60 (Compression On)"); -MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver. Default: 0 (Off)"); -MODULE_PARM_DESC(power_on_at_open, " Set the default device to power on when device is opened. Default: 1 (On)"); -MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX). Default: -1 (autodetect)"); -MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)"); - - -/* Misc stuff */ -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENSE); -MODULE_VERSION(USBVISION_VERSION_STRING); -MODULE_ALIAS(DRIVER_ALIAS); - - -/*****************************************************************************/ -/* 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 */ -/*****************************************************************************/ - -#define YES_NO(x) ((x) ? "Yes" : "No") - -static inline struct usb_usbvision *cd_to_usbvision(struct device *cd) -{ - struct video_device *vdev = - container_of(cd, struct video_device, dev); - return video_get_drvdata(vdev); -} - -static ssize_t show_version(struct device *cd, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%s\n", USBVISION_VERSION_STRING); -} -static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); - -static ssize_t show_model(struct device *cd, - struct device_attribute *attr, char *buf) -{ - struct video_device *vdev = - container_of(cd, struct video_device, dev); - struct usb_usbvision *usbvision = video_get_drvdata(vdev); - return sprintf(buf, "%s\n", - usbvision_device_data[usbvision->dev_model].model_string); -} -static DEVICE_ATTR(model, S_IRUGO, show_model, NULL); - -static ssize_t show_hue(struct device *cd, - struct device_attribute *attr, char *buf) -{ - struct video_device *vdev = - container_of(cd, struct video_device, dev); - struct usb_usbvision *usbvision = video_get_drvdata(vdev); - struct v4l2_control ctrl; - ctrl.id = V4L2_CID_HUE; - ctrl.value = 0; - if (usbvision->user) - call_all(usbvision, core, g_ctrl, &ctrl); - return sprintf(buf, "%d\n", ctrl.value); -} -static DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); - -static ssize_t show_contrast(struct device *cd, - struct device_attribute *attr, char *buf) -{ - struct video_device *vdev = - container_of(cd, struct video_device, dev); - struct usb_usbvision *usbvision = video_get_drvdata(vdev); - struct v4l2_control ctrl; - ctrl.id = V4L2_CID_CONTRAST; - ctrl.value = 0; - if (usbvision->user) - call_all(usbvision, core, g_ctrl, &ctrl); - return sprintf(buf, "%d\n", ctrl.value); -} -static DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); - -static ssize_t show_brightness(struct device *cd, - struct device_attribute *attr, char *buf) -{ - struct video_device *vdev = - container_of(cd, struct video_device, dev); - struct usb_usbvision *usbvision = video_get_drvdata(vdev); - struct v4l2_control ctrl; - ctrl.id = V4L2_CID_BRIGHTNESS; - ctrl.value = 0; - if (usbvision->user) - call_all(usbvision, core, g_ctrl, &ctrl); - return sprintf(buf, "%d\n", ctrl.value); -} -static DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); - -static ssize_t show_saturation(struct device *cd, - struct device_attribute *attr, char *buf) -{ - struct video_device *vdev = - container_of(cd, struct video_device, dev); - struct usb_usbvision *usbvision = video_get_drvdata(vdev); - struct v4l2_control ctrl; - ctrl.id = V4L2_CID_SATURATION; - ctrl.value = 0; - if (usbvision->user) - call_all(usbvision, core, g_ctrl, &ctrl); - return sprintf(buf, "%d\n", ctrl.value); -} -static DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); - -static ssize_t show_streaming(struct device *cd, - struct device_attribute *attr, char *buf) -{ - struct video_device *vdev = - container_of(cd, struct video_device, dev); - struct usb_usbvision *usbvision = video_get_drvdata(vdev); - return sprintf(buf, "%s\n", - YES_NO(usbvision->streaming == stream_on ? 1 : 0)); -} -static DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); - -static ssize_t show_compression(struct device *cd, - struct device_attribute *attr, char *buf) -{ - struct video_device *vdev = - container_of(cd, struct video_device, dev); - struct usb_usbvision *usbvision = video_get_drvdata(vdev); - return sprintf(buf, "%s\n", - YES_NO(usbvision->isoc_mode == ISOC_MODE_COMPRESS)); -} -static DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL); - -static ssize_t show_device_bridge(struct device *cd, - struct device_attribute *attr, char *buf) -{ - struct video_device *vdev = - container_of(cd, struct video_device, dev); - struct usb_usbvision *usbvision = video_get_drvdata(vdev); - return sprintf(buf, "%d\n", usbvision->bridge_type); -} -static DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL); - -static void usbvision_create_sysfs(struct video_device *vdev) -{ - int res; - - if (!vdev) - return; - do { - res = device_create_file(&vdev->dev, &dev_attr_version); - if (res < 0) - break; - res = device_create_file(&vdev->dev, &dev_attr_model); - if (res < 0) - break; - res = device_create_file(&vdev->dev, &dev_attr_hue); - if (res < 0) - break; - res = device_create_file(&vdev->dev, &dev_attr_contrast); - if (res < 0) - break; - res = device_create_file(&vdev->dev, &dev_attr_brightness); - if (res < 0) - break; - res = device_create_file(&vdev->dev, &dev_attr_saturation); - if (res < 0) - break; - res = device_create_file(&vdev->dev, &dev_attr_streaming); - if (res < 0) - break; - res = device_create_file(&vdev->dev, &dev_attr_compression); - if (res < 0) - break; - res = device_create_file(&vdev->dev, &dev_attr_bridge); - if (res >= 0) - return; - } while (0); - - dev_err(&vdev->dev, "%s error: %d\n", __func__, res); -} - -static void usbvision_remove_sysfs(struct video_device *vdev) -{ - if (vdev) { - device_remove_file(&vdev->dev, &dev_attr_version); - device_remove_file(&vdev->dev, &dev_attr_model); - device_remove_file(&vdev->dev, &dev_attr_hue); - device_remove_file(&vdev->dev, &dev_attr_contrast); - device_remove_file(&vdev->dev, &dev_attr_brightness); - device_remove_file(&vdev->dev, &dev_attr_saturation); - device_remove_file(&vdev->dev, &dev_attr_streaming); - device_remove_file(&vdev->dev, &dev_attr_compression); - device_remove_file(&vdev->dev, &dev_attr_bridge); - } -} - -/* - * usbvision_open() - * - * This is part of Video 4 Linux API. The driver can be opened by one - * client only (checks internal counter 'usbvision->user'). The procedure - * then allocates buffers needed for video processing. - * - */ -static int usbvision_v4l2_open(struct file *file) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - int err_code = 0; - - PDEBUG(DBG_IO, "open"); - - if (mutex_lock_interruptible(&usbvision->v4l2_lock)) - return -ERESTARTSYS; - usbvision_reset_power_off_timer(usbvision); - - if (usbvision->user) - err_code = -EBUSY; - else { - /* Allocate memory for the scratch ring buffer */ - err_code = usbvision_scratch_alloc(usbvision); - if (isoc_mode == ISOC_MODE_COMPRESS) { - /* Allocate intermediate decompression buffers - only if needed */ - err_code = usbvision_decompress_alloc(usbvision); - } - if (err_code) { - /* Deallocate all buffers if trouble */ - usbvision_scratch_free(usbvision); - usbvision_decompress_free(usbvision); - } - } - - /* If so far no errors then we shall start the camera */ - if (!err_code) { - if (usbvision->power == 0) { - usbvision_power_on(usbvision); - usbvision_i2c_register(usbvision); - } - - /* Send init sequence only once, it's large! */ - if (!usbvision->initialized) { - int setup_ok = 0; - setup_ok = usbvision_setup(usbvision, isoc_mode); - if (setup_ok) - usbvision->initialized = 1; - else - err_code = -EBUSY; - } - - if (!err_code) { - usbvision_begin_streaming(usbvision); - err_code = usbvision_init_isoc(usbvision); - /* device must be initialized before isoc transfer */ - usbvision_muxsel(usbvision, 0); - usbvision->user++; - } else { - if (power_on_at_open) { - usbvision_i2c_unregister(usbvision); - usbvision_power_off(usbvision); - usbvision->initialized = 0; - } - } - } - - /* prepare queues */ - usbvision_empty_framequeues(usbvision); - mutex_unlock(&usbvision->v4l2_lock); - - PDEBUG(DBG_IO, "success"); - return err_code; -} - -/* - * usbvision_v4l2_close() - * - * This is part of Video 4 Linux API. The procedure - * stops streaming and deallocates all buffers that were earlier - * allocated in usbvision_v4l2_open(). - * - */ -static int usbvision_v4l2_close(struct file *file) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - PDEBUG(DBG_IO, "close"); - - mutex_lock(&usbvision->v4l2_lock); - usbvision_audio_off(usbvision); - usbvision_restart_isoc(usbvision); - usbvision_stop_isoc(usbvision); - - usbvision_decompress_free(usbvision); - usbvision_frames_free(usbvision); - usbvision_empty_framequeues(usbvision); - usbvision_scratch_free(usbvision); - - usbvision->user--; - - if (power_on_at_open) { - /* power off in a little while - to avoid off/on every close/open short sequences */ - usbvision_set_power_off_timer(usbvision); - usbvision->initialized = 0; - } - - if (usbvision->remove_pending) { - printk(KERN_INFO "%s: Final disconnect\n", __func__); - usbvision_release(usbvision); - } - mutex_unlock(&usbvision->v4l2_lock); - - PDEBUG(DBG_IO, "success"); - return 0; -} - - -/* - * usbvision_ioctl() - * - * This is part of Video 4 Linux API. The procedure handles ioctl() calls. - * - */ -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int vidioc_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - int err_code; - - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - /* NT100x has a 8-bit register space */ - err_code = usbvision_read_reg(usbvision, reg->reg&0xff); - if (err_code < 0) { - dev_err(&usbvision->vdev->dev, - "%s: VIDIOC_DBG_G_REGISTER failed: error %d\n", - __func__, err_code); - return err_code; - } - reg->val = err_code; - reg->size = 1; - return 0; -} - -static int vidioc_s_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - int err_code; - - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - /* NT100x has a 8-bit register space */ - err_code = usbvision_write_reg(usbvision, reg->reg & 0xff, reg->val); - if (err_code < 0) { - dev_err(&usbvision->vdev->dev, - "%s: VIDIOC_DBG_S_REGISTER failed: error %d\n", - __func__, err_code); - return err_code; - } - return 0; -} -#endif - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *vc) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); - strlcpy(vc->card, - usbvision_device_data[usbvision->dev_model].model_string, - sizeof(vc->card)); - usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info)); - vc->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_AUDIO | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING | - (usbvision->have_tuner ? V4L2_CAP_TUNER : 0); - return 0; -} - -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *vi) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - int chan; - - if (vi->index >= usbvision->video_inputs) - 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->dev_model].video_channels == 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; - } - break; - case 1: - vi->type = V4L2_INPUT_TYPE_CAMERA; - if (usbvision_device_data[usbvision->dev_model].video_channels == 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->dev_model].video_channels == 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; - } - return 0; -} - -static int vidioc_g_input(struct file *file, void *priv, unsigned int *input) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - *input = usbvision->ctl_input; - return 0; -} - -static int vidioc_s_input(struct file *file, void *priv, unsigned int input) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - if (input >= usbvision->video_inputs) - return -EINVAL; - - usbvision_muxsel(usbvision, input); - usbvision_set_input(usbvision); - usbvision_set_output(usbvision, - usbvision->curwidth, - usbvision->curheight); - return 0; -} - -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - usbvision->tvnorm_id = *id; - - call_all(usbvision, core, s_std, usbvision->tvnorm_id); - /* propagate the change to the decoder */ - usbvision_muxsel(usbvision, usbvision->ctl_input); - - return 0; -} - -static int vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *vt) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - 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_all(usbvision, tuner, g_tuner, vt); - - return 0; -} - -static int vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *vt) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - /* Only no or one tuner for now */ - if (!usbvision->have_tuner || vt->index) - return -EINVAL; - /* let clients handle this */ - call_all(usbvision, tuner, s_tuner, vt); - - return 0; -} - -static int vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *freq) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - freq->tuner = 0; /* Only one tuner */ - if (usbvision->radio) - freq->type = V4L2_TUNER_RADIO; - else - freq->type = V4L2_TUNER_ANALOG_TV; - freq->frequency = usbvision->freq; - - return 0; -} - -static int vidioc_s_frequency(struct file *file, void *priv, - struct v4l2_frequency *freq) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - /* Only no or one tuner for now */ - if (!usbvision->have_tuner || freq->tuner) - return -EINVAL; - - usbvision->freq = freq->frequency; - call_all(usbvision, tuner, s_frequency, freq); - - return 0; -} - -static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - if (usbvision->radio) - strcpy(a->name, "Radio"); - else - strcpy(a->name, "TV"); - - return 0; -} - -static int vidioc_s_audio(struct file *file, void *fh, - struct v4l2_audio *a) -{ - if (a->index) - return -EINVAL; - return 0; -} - -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *ctrl) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - call_all(usbvision, core, queryctrl, ctrl); - - if (!ctrl->type) - return -EINVAL; - - return 0; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - call_all(usbvision, core, g_ctrl, ctrl); - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - call_all(usbvision, core, s_ctrl, ctrl); - return 0; -} - -static int vidioc_reqbufs(struct file *file, - void *priv, struct v4l2_requestbuffers *vr) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - int ret; - - RESTRICT_TO_RANGE(vr->count, 1, USBVISION_NUMFRAMES); - - /* Check input validity: - the user must do a VIDEO CAPTURE and MMAP method. */ - if (vr->memory != V4L2_MEMORY_MMAP) - return -EINVAL; - - if (usbvision->streaming == stream_on) { - ret = usbvision_stream_interrupt(usbvision); - if (ret) - return ret; - } - - usbvision_frames_free(usbvision); - usbvision_empty_framequeues(usbvision); - vr->count = usbvision_frames_alloc(usbvision, vr->count); - - usbvision->cur_frame = NULL; - - return 0; -} - -static int vidioc_querybuf(struct file *file, - void *priv, struct v4l2_buffer *vb) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - struct usbvision_frame *frame; - - /* FIXME : must control - that buffers are mapped (VIDIOC_REQBUFS has been called) */ - if (vb->index >= usbvision->num_frames) - return -EINVAL; - /* Updating the corresponding frame state */ - vb->flags = 0; - frame = &usbvision->frame[vb->index]; - if (frame->grabstate >= frame_state_ready) - vb->flags |= V4L2_BUF_FLAG_QUEUED; - if (frame->grabstate >= frame_state_done) - vb->flags |= V4L2_BUF_FLAG_DONE; - if (frame->grabstate == frame_state_unused) - vb->flags |= V4L2_BUF_FLAG_MAPPED; - vb->memory = V4L2_MEMORY_MMAP; - - vb->m.offset = vb->index * PAGE_ALIGN(usbvision->max_frame_size); - - vb->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; -} - -static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *vb) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - struct usbvision_frame *frame; - unsigned long lock_flags; - - /* FIXME : works only on VIDEO_CAPTURE MODE, MMAP. */ - if (vb->index >= usbvision->num_frames) - return -EINVAL; - - frame = &usbvision->frame[vb->index]; - - if (frame->grabstate != frame_state_unused) - return -EAGAIN; - - /* Mark it as ready and enqueue frame */ - frame->grabstate = frame_state_ready; - frame->scanstate = scan_state_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) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - int ret; - struct usbvision_frame *f; - unsigned long lock_flags; - - 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 = frame_state_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; -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - usbvision->streaming = stream_on; - call_all(usbvision, video, s_stream, 1); - - return 0; -} - -static int vidioc_streamoff(struct file *file, - void *priv, enum v4l2_buf_type type) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (usbvision->streaming == stream_on) { - usbvision_stream_interrupt(usbvision); - /* Stop all video streamings */ - call_all(usbvision, video, s_stream, 0); - } - usbvision_empty_framequeues(usbvision); - - return 0; -} - -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *vfd) -{ - if (vfd->index >= USBVISION_SUPPORTED_PALETTES - 1) - return -EINVAL; - strcpy(vfd->description, usbvision_v4l2_format[vfd->index].desc); - vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; - return 0; -} - -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *vf) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - 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_vid_cap(struct file *file, void *priv, - struct v4l2_format *vf) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - int format_idx; - - /* Find requested format in available ones */ - for (format_idx = 0; format_idx < USBVISION_SUPPORTED_PALETTES; format_idx++) { - if (vf->fmt.pix.pixelformat == - usbvision_v4l2_format[format_idx].format) { - usbvision->palette = usbvision_v4l2_format[format_idx]; - break; - } - } - /* robustness */ - if (format_idx == USBVISION_SUPPORTED_PALETTES) - return -EINVAL; - RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH); - RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT); - - 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_vid_cap(struct file *file, void *priv, - struct v4l2_format *vf) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - int ret; - - ret = vidioc_try_fmt_vid_cap(file, priv, vf); - if (ret) - return ret; - - /* stop io in case it is already in progress */ - if (usbvision->streaming == stream_on) { - ret = usbvision_stream_interrupt(usbvision); - if (ret) - return ret; - } - usbvision_frames_free(usbvision); - usbvision_empty_framequeues(usbvision); - - usbvision->cur_frame = NULL; - - /* by now we are committed to the new data... */ - usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height); - - return 0; -} - -static ssize_t usbvision_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - int noblock = file->f_flags & O_NONBLOCK; - unsigned long lock_flags; - int ret, i; - struct usbvision_frame *frame; - - PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __func__, - (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. */ - if (!usbvision->num_frames) { - /* First, allocate some frames to work with - if this has not been done with VIDIOC_REQBUF */ - usbvision_frames_free(usbvision); - usbvision_empty_framequeues(usbvision); - usbvision_frames_alloc(usbvision, USBVISION_NUMFRAMES); - } - - if (usbvision->streaming != stream_on) { - /* no stream is running, make it running ! */ - usbvision->streaming = stream_on; - call_all(usbvision, video, s_stream, 1); - } - - /* Then, enqueue as many frames as possible - (like a user of VIDIOC_QBUF would do) */ - for (i = 0; i < usbvision->num_frames; i++) { - frame = &usbvision->frame[i]; - if (frame->grabstate == frame_state_unused) { - /* Mark it as ready and enqueue frame */ - frame->grabstate = frame_state_ready; - frame->scanstate = scan_state_scanning; - /* 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); - } - } - - /* Then try to steal a frame (like a VIDIOC_DQBUF would do) */ - if (list_empty(&(usbvision->outqueue))) { - if (noblock) - return -EAGAIN; - - ret = wait_event_interruptible - (usbvision->wait_frame, - !list_empty(&(usbvision->outqueue))); - if (ret) - return ret; - } - - spin_lock_irqsave(&usbvision->queue_lock, lock_flags); - frame = list_entry(usbvision->outqueue.next, - struct usbvision_frame, frame); - list_del(usbvision->outqueue.next); - spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags); - - /* An error returns an empty frame */ - if (frame->grabstate == frame_state_error) { - frame->bytes_read = 0; - return 0; - } - - PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld", - __func__, - 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) - count = frame->scanlength - frame->bytes_read; - - if (copy_to_user(buf, frame->data + frame->bytes_read, count)) - return -EFAULT; - - frame->bytes_read += count; - PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld", - __func__, - (unsigned long)count, frame->bytes_read); - - /* For now, forget the frame if it has not been read in one shot. */ -/* if (frame->bytes_read >= frame->scanlength) {*/ /* All data has been read */ - frame->bytes_read = 0; - - /* Mark it as available to be used again. */ - frame->grabstate = frame_state_unused; -/* } */ - - return count; -} - -static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - int res; - - if (mutex_lock_interruptible(&usbvision->v4l2_lock)) - return -ERESTARTSYS; - res = usbvision_read(file, buf, count, ppos); - mutex_unlock(&usbvision->v4l2_lock); - return res; -} - -static int usbvision_mmap(struct file *file, struct vm_area_struct *vma) -{ - unsigned long size = vma->vm_end - vma->vm_start, - start = vma->vm_start; - void *pos; - u32 i; - struct usb_usbvision *usbvision = video_drvdata(file); - - PDEBUG(DBG_MMAP, "mmap"); - - if (!USBVISION_IS_OPERATIONAL(usbvision)) - return -EFAULT; - - if (!(vma->vm_flags & VM_WRITE) || - size != PAGE_ALIGN(usbvision->max_frame_size)) { - return -EINVAL; - } - - for (i = 0; i < usbvision->num_frames; i++) { - 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"); - return -EINVAL; - } - - /* VM_IO is eventually going to replace PageReserved altogether */ - vma->vm_flags |= VM_IO; - vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ - - pos = usbvision->frame[i].data; - while (size > 0) { - if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { - PDEBUG(DBG_MMAP, "mmap: vm_insert_page failed"); - return -EAGAIN; - } - start += PAGE_SIZE; - pos += PAGE_SIZE; - size -= PAGE_SIZE; - } - - return 0; -} - -static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - int res; - - if (mutex_lock_interruptible(&usbvision->v4l2_lock)) - return -ERESTARTSYS; - res = usbvision_mmap(file, vma); - mutex_unlock(&usbvision->v4l2_lock); - return res; -} - -/* - * Here comes the stuff for radio on usbvision based devices - * - */ -static int usbvision_radio_open(struct file *file) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - int err_code = 0; - - PDEBUG(DBG_IO, "%s:", __func__); - - if (mutex_lock_interruptible(&usbvision->v4l2_lock)) - return -ERESTARTSYS; - if (usbvision->user) { - dev_err(&usbvision->rdev->dev, - "%s: Someone tried to open an already opened USBVision Radio!\n", - __func__); - err_code = -EBUSY; - } else { - if (power_on_at_open) { - usbvision_reset_power_off_timer(usbvision); - if (usbvision->power == 0) { - usbvision_power_on(usbvision); - usbvision_i2c_register(usbvision); - } - } - - /* Alternate interface 1 is is the biggest frame size */ - err_code = usbvision_set_alternate(usbvision); - if (err_code < 0) { - usbvision->last_error = err_code; - err_code = -EBUSY; - goto out; - } - - /* If so far no errors then we shall start the radio */ - usbvision->radio = 1; - call_all(usbvision, tuner, s_radio); - usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO); - usbvision->user++; - } - - if (err_code) { - if (power_on_at_open) { - usbvision_i2c_unregister(usbvision); - usbvision_power_off(usbvision); - usbvision->initialized = 0; - } - } -out: - mutex_unlock(&usbvision->v4l2_lock); - return err_code; -} - - -static int usbvision_radio_close(struct file *file) -{ - struct usb_usbvision *usbvision = video_drvdata(file); - int err_code = 0; - - PDEBUG(DBG_IO, ""); - - mutex_lock(&usbvision->v4l2_lock); - /* Set packet size to 0 */ - usbvision->iface_alt = 0; - err_code = usb_set_interface(usbvision->dev, usbvision->iface, - usbvision->iface_alt); - - usbvision_audio_off(usbvision); - usbvision->radio = 0; - usbvision->user--; - - if (power_on_at_open) { - usbvision_set_power_off_timer(usbvision); - usbvision->initialized = 0; - } - - if (usbvision->remove_pending) { - printk(KERN_INFO "%s: Final disconnect\n", __func__); - usbvision_release(usbvision); - } - - mutex_unlock(&usbvision->v4l2_lock); - PDEBUG(DBG_IO, "success"); - return err_code; -} - -/* Video registration stuff */ - -/* Video template */ -static const struct v4l2_file_operations usbvision_fops = { - .owner = THIS_MODULE, - .open = usbvision_v4l2_open, - .release = usbvision_v4l2_close, - .read = usbvision_v4l2_read, - .mmap = usbvision_v4l2_mmap, - .unlocked_ioctl = video_ioctl2, -/* .poll = video_poll, */ -}; - -static const struct v4l2_ioctl_ops usbvision_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_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_s_audio = vidioc_s_audio, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .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 -}; - -static struct video_device usbvision_video_template = { - .fops = &usbvision_fops, - .ioctl_ops = &usbvision_ioctl_ops, - .name = "usbvision-video", - .release = video_device_release, - .tvnorms = USBVISION_NORMS, - .current_norm = V4L2_STD_PAL -}; - - -/* Radio template */ -static const struct v4l2_file_operations usbvision_radio_fops = { - .owner = THIS_MODULE, - .open = usbvision_radio_open, - .release = usbvision_radio_close, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops usbvision_radio_ioctl_ops = { - .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_s_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, -}; - -static struct video_device usbvision_radio_template = { - .fops = &usbvision_radio_fops, - .name = "usbvision-radio", - .release = video_device_release, - .ioctl_ops = &usbvision_radio_ioctl_ops, - - .tvnorms = USBVISION_NORMS, - .current_norm = V4L2_STD_PAL -}; - - -static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, - struct video_device *vdev_template, - char *name) -{ - struct usb_device *usb_dev = usbvision->dev; - struct video_device *vdev; - - if (usb_dev == NULL) { - dev_err(&usbvision->dev->dev, - "%s: usbvision->dev is not set\n", __func__); - return NULL; - } - - vdev = video_device_alloc(); - if (NULL == vdev) - return NULL; - *vdev = *vdev_template; - vdev->lock = &usbvision->v4l2_lock; - vdev->v4l2_dev = &usbvision->v4l2_dev; - snprintf(vdev->name, sizeof(vdev->name), "%s", name); - video_set_drvdata(vdev, usbvision); - return vdev; -} - -/* unregister video4linux devices */ -static void usbvision_unregister_video(struct usb_usbvision *usbvision) -{ - /* Radio Device: */ - if (usbvision->rdev) { - PDEBUG(DBG_PROBE, "unregister %s [v4l2]", - video_device_node_name(usbvision->rdev)); - if (video_is_registered(usbvision->rdev)) - video_unregister_device(usbvision->rdev); - else - video_device_release(usbvision->rdev); - usbvision->rdev = NULL; - } - - /* Video Device: */ - if (usbvision->vdev) { - PDEBUG(DBG_PROBE, "unregister %s [v4l2]", - video_device_node_name(usbvision->vdev)); - if (video_is_registered(usbvision->vdev)) - video_unregister_device(usbvision->vdev); - else - video_device_release(usbvision->vdev); - usbvision->vdev = NULL; - } -} - -/* register video4linux devices */ -static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) -{ - /* Video Device: */ - 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) - goto err_exit; - printk(KERN_INFO "USBVision[%d]: registered USBVision Video device %s [v4l2]\n", - usbvision->nr, video_device_node_name(usbvision->vdev)); - - /* Radio Device: */ - if (usbvision_device_data[usbvision->dev_model].radio) { - /* usbvision has 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) - goto err_exit; - printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device %s [v4l2]\n", - usbvision->nr, video_device_node_name(usbvision->rdev)); - } - /* all done */ - return 0; - - err_exit: - dev_err(&usbvision->dev->dev, - "USBVision[%d]: video_register_device() failed\n", - usbvision->nr); - usbvision_unregister_video(usbvision); - return -1; -} - -/* - * usbvision_alloc() - * - * This code allocates the struct usb_usbvision. - * It is filled with default values. - * - * Returns NULL on error, a pointer to usb_usbvision else. - * - */ -static struct usb_usbvision *usbvision_alloc(struct usb_device *dev, - struct usb_interface *intf) -{ - struct usb_usbvision *usbvision; - - usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL); - if (usbvision == NULL) - return NULL; - - usbvision->dev = dev; - if (v4l2_device_register(&intf->dev, &usbvision->v4l2_dev)) - goto err_free; - - mutex_init(&usbvision->v4l2_lock); - - /* prepare control urb for control messages during interrupts */ - usbvision->ctrl_urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); - if (usbvision->ctrl_urb == NULL) - goto err_unreg; - init_waitqueue_head(&usbvision->ctrl_urb_wq); - - usbvision_init_power_off_timer(usbvision); - - return usbvision; - -err_unreg: - v4l2_device_unregister(&usbvision->v4l2_dev); -err_free: - kfree(usbvision); - return NULL; -} - -/* - * usbvision_release() - * - * This code does final release of struct usb_usbvision. This happens - * after the device is disconnected -and- all clients closed their files. - * - */ -static void usbvision_release(struct usb_usbvision *usbvision) -{ - PDEBUG(DBG_PROBE, ""); - - usbvision_reset_power_off_timer(usbvision); - - usbvision->initialized = 0; - - usbvision_remove_sysfs(usbvision->vdev); - usbvision_unregister_video(usbvision); - - usb_free_urb(usbvision->ctrl_urb); - - v4l2_device_unregister(&usbvision->v4l2_dev); - kfree(usbvision); - - PDEBUG(DBG_PROBE, "success"); -} - - -/*********************** usb interface **********************************/ - -static void usbvision_configure_video(struct usb_usbvision *usbvision) -{ - int model; - - if (usbvision == NULL) - return; - - model = usbvision->dev_model; - usbvision->palette = usbvision_v4l2_format[2]; /* V4L2_PIX_FMT_RGB24; */ - - if (usbvision_device_data[usbvision->dev_model].vin_reg2_override) { - usbvision->vin_reg2_preset = - usbvision_device_data[usbvision->dev_model].vin_reg2; - } else { - usbvision->vin_reg2_preset = 0; - } - - usbvision->tvnorm_id = usbvision_device_data[model].video_norm; - - usbvision->video_inputs = usbvision_device_data[model].video_channels; - usbvision->ctl_input = 0; - - /* This should be here to make i2c clients to be able to register */ - /* first switch off audio */ - if (usbvision_device_data[model].audio_channels > 0) - usbvision_audio_off(usbvision); - if (!power_on_at_open) { - /* and then power up the noisy tuner */ - usbvision_power_on(usbvision); - usbvision_i2c_register(usbvision); - } -} - -/* - * usbvision_probe() - * - * This procedure queries device descriptor and accepts the interface - * if it looks like USBVISION video device - * - */ -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; - 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); - - 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", __func__, - usbvision_device_data[model].model_string); - - if (usbvision_device_data[model].interface >= 0) - interface = &dev->actconfig->interface[usbvision_device_data[model].interface]->altsetting[0]; - else - interface = &dev->actconfig->interface[ifnum]->altsetting[0]; - endpoint = &interface->endpoint[1].desc; - if (!usb_endpoint_xfer_isoc(endpoint)) { - dev_err(&intf->dev, "%s: interface %d. has non-ISO endpoint!\n", - __func__, ifnum); - dev_err(&intf->dev, "%s: Endpoint attributes %d", - __func__, endpoint->bmAttributes); - return -ENODEV; - } - if (usb_endpoint_dir_out(endpoint)) { - dev_err(&intf->dev, "%s: interface %d. has ISO OUT endpoint!\n", - __func__, ifnum); - return -ENODEV; - } - - usbvision = usbvision_alloc(dev, intf); - if (usbvision == NULL) { - dev_err(&intf->dev, "%s: couldn't allocate USBVision struct\n", __func__); - return -ENOMEM; - } - - if (dev->descriptor.bNumConfigurations > 1) - usbvision->bridge_type = BRIDGE_NT1004; - else if (model == DAZZLE_DVC_90_REV_1_SECAM) - usbvision->bridge_type = BRIDGE_NT1005; - else - usbvision->bridge_type = BRIDGE_NT1003; - PDEBUG(DBG_PROBE, "bridge_type %d", usbvision->bridge_type); - - /* compute alternate max packet sizes */ - uif = dev->actconfig->interface[0]; - - usbvision->num_alt = uif->num_altsetting; - PDEBUG(DBG_PROBE, "Alternate settings: %i", usbvision->num_alt); - usbvision->alt_max_pkt_size = kmalloc(32 * usbvision->num_alt, GFP_KERNEL); - if (usbvision->alt_max_pkt_size == NULL) { - dev_err(&intf->dev, "usbvision: out of memory!\n"); - return -ENOMEM; - } - - for (i = 0; i < usbvision->num_alt; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc. - wMaxPacketSize); - usbvision->alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - PDEBUG(DBG_PROBE, "Alternate setting %i, max size= %i", i, - usbvision->alt_max_pkt_size[i]); - } - - - usbvision->nr = usbvision_nr++; - - usbvision->have_tuner = usbvision_device_data[model].tuner; - if (usbvision->have_tuner) - usbvision->tuner_type = usbvision_device_data[model].tuner_type; - - usbvision->dev_model = model; - usbvision->remove_pending = 0; - usbvision->iface = ifnum; - usbvision->iface_alt = 0; - usbvision->video_endp = endpoint->bEndpointAddress; - usbvision->isoc_packet_size = 0; - usbvision->usb_bandwidth = 0; - usbvision->user = 0; - usbvision->streaming = stream_off; - usbvision_configure_video(usbvision); - usbvision_register_video(usbvision); - - usbvision_create_sysfs(usbvision->vdev); - - PDEBUG(DBG_PROBE, "success"); - return 0; -} - - -/* - * usbvision_disconnect() - * - * This procedure stops all driver activity, deallocates interface-private - * structure (pointed by 'ptr') and after that driver should be removable - * with no ill consequences. - * - */ -static void __devexit usbvision_disconnect(struct usb_interface *intf) -{ - struct usb_usbvision *usbvision = to_usbvision(usb_get_intfdata(intf)); - - PDEBUG(DBG_PROBE, ""); - - if (usbvision == NULL) { - pr_err("%s: usb_get_intfdata() failed\n", __func__); - return; - } - - mutex_lock(&usbvision->v4l2_lock); - - /* At this time we ask to cancel outstanding URBs */ - usbvision_stop_isoc(usbvision); - - v4l2_device_disconnect(&usbvision->v4l2_dev); - - if (usbvision->power) { - usbvision_i2c_unregister(usbvision); - usbvision_power_off(usbvision); - } - usbvision->remove_pending = 1; /* Now all ISO data will be ignored */ - - usb_put_dev(usbvision->dev); - usbvision->dev = NULL; /* USB device is no more */ - - mutex_unlock(&usbvision->v4l2_lock); - - if (usbvision->user) { - printk(KERN_INFO "%s: In use, disconnect pending\n", - __func__); - wake_up_interruptible(&usbvision->wait_frame); - wake_up_interruptible(&usbvision->wait_stream); - } else { - usbvision_release(usbvision); - } - - PDEBUG(DBG_PROBE, "success"); -} - -static struct usb_driver usbvision_driver = { - .name = "usbvision", - .id_table = usbvision_table, - .probe = usbvision_probe, - .disconnect = __devexit_p(usbvision_disconnect), -}; - -/* - * usbvision_init() - * - * This code is run to initialize the driver. - * - */ -static int __init usbvision_init(void) -{ - int err_code; - - PDEBUG(DBG_PROBE, ""); - - PDEBUG(DBG_IO, "IO debugging is enabled [video]"); - PDEBUG(DBG_PROBE, "PROBE debugging is enabled [video]"); - PDEBUG(DBG_MMAP, "MMAP debugging is enabled [video]"); - - /* disable planar mode support unless compression enabled */ - if (isoc_mode != ISOC_MODE_COMPRESS) { - /* FIXME : not the right way to set supported flag */ - usbvision_v4l2_format[6].supported = 0; /* V4L2_PIX_FMT_YVU420 */ - usbvision_v4l2_format[7].supported = 0; /* V4L2_PIX_FMT_YUV422P */ - } - - err_code = usb_register(&usbvision_driver); - - if (err_code == 0) { - printk(KERN_INFO DRIVER_DESC " : " USBVISION_VERSION_STRING "\n"); - PDEBUG(DBG_PROBE, "success"); - } - return err_code; -} - -static void __exit usbvision_exit(void) -{ - PDEBUG(DBG_PROBE, ""); - - usb_deregister(&usbvision_driver); - PDEBUG(DBG_PROBE, "success"); -} - -module_init(usbvision_init); -module_exit(usbvision_exit); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h deleted file mode 100644 index 43cf61fe4943..000000000000 --- a/drivers/media/video/usbvision/usbvision.h +++ /dev/null @@ -1,535 +0,0 @@ -/* - * USBVISION.H - * usbvision header file - * - * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de> - * Dwaine Garden <dwainegarden@rogers.com> - * - * - * Report problems to v4l MailingList: linux-media@vger.kernel.org - * - * This module is part of usbvision driver project. - * Updates to driver completed by Dwaine P. Garden - * v4l2 conversion by Thierry Merle <thierry.merle@free.fr> - * - * 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. - */ - - -#ifndef __LINUX_USBVISION_H -#define __LINUX_USBVISION_H - -#include <linux/list.h> -#include <linux/usb.h> -#include <linux/i2c.h> -#include <linux/mutex.h> -#include <media/v4l2-device.h> -#include <media/tuner.h> -#include <linux/videodev2.h> - -#define USBVISION_DEBUG /* Turn on debug messages */ - -#define USBVISION_PWR_REG 0x00 - #define USBVISION_SSPND_EN (1 << 1) - #define USBVISION_RES2 (1 << 2) - #define USBVISION_PWR_VID (1 << 5) - #define USBVISION_E2_EN (1 << 7) -#define USBVISION_CONFIG_REG 0x01 -#define USBVISION_ADRS_REG 0x02 -#define USBVISION_ALTER_REG 0x03 -#define USBVISION_FORCE_ALTER_REG 0x04 -#define USBVISION_STATUS_REG 0x05 -#define USBVISION_IOPIN_REG 0x06 - #define USBVISION_IO_1 (1 << 0) - #define USBVISION_IO_2 (1 << 1) - #define USBVISION_AUDIO_IN 0 - #define USBVISION_AUDIO_TV 1 - #define USBVISION_AUDIO_RADIO 2 - #define USBVISION_AUDIO_MUTE 3 -#define USBVISION_SER_MODE 0x07 - #define USBVISION_CLK_OUT (1 << 0) - #define USBVISION_DAT_IO (1 << 1) - #define USBVISION_SENS_OUT (1 << 2) - #define USBVISION_SER_MODE_SOFT (0 << 4) - #define USBVISION_SER_MODE_SIO (1 << 4) -#define USBVISION_SER_ADRS 0x08 -#define USBVISION_SER_CONT 0x09 -#define USBVISION_SER_DAT1 0x0A -#define USBVISION_SER_DAT2 0x0B -#define USBVISION_SER_DAT3 0x0C -#define USBVISION_SER_DAT4 0x0D -#define USBVISION_EE_DATA 0x0E -#define USBVISION_EE_LSBAD 0x0F -#define USBVISION_EE_CONT 0x10 -#define USBVISION_DRM_CONT 0x12 - #define USBVISION_REF (1 << 0) - #define USBVISION_RES_UR (1 << 2) - #define USBVISION_RES_FDL (1 << 3) - #define USBVISION_RES_VDW (1 << 4) -#define USBVISION_DRM_PRM1 0x13 -#define USBVISION_DRM_PRM2 0x14 -#define USBVISION_DRM_PRM3 0x15 -#define USBVISION_DRM_PRM4 0x16 -#define USBVISION_DRM_PRM5 0x17 -#define USBVISION_DRM_PRM6 0x18 -#define USBVISION_DRM_PRM7 0x19 -#define USBVISION_DRM_PRM8 0x1A -#define USBVISION_VIN_REG1 0x1B - #define USBVISION_8_422_SYNC 0x01 - #define USBVISION_16_422_SYNC 0x02 - #define USBVISION_VSNC_POL (1 << 3) - #define USBVISION_HSNC_POL (1 << 4) - #define USBVISION_FID_POL (1 << 5) - #define USBVISION_HVALID_PO (1 << 6) - #define USBVISION_VCLK_POL (1 << 7) -#define USBVISION_VIN_REG2 0x1C - #define USBVISION_AUTO_FID (1 << 0) - #define USBVISION_NONE_INTER (1 << 1) - #define USBVISION_NOHVALID (1 << 2) - #define USBVISION_UV_ID (1 << 3) - #define USBVISION_FIX_2C (1 << 4) - #define USBVISION_SEND_FID (1 << 5) - #define USBVISION_KEEP_BLANK (1 << 7) -#define USBVISION_LXSIZE_I 0x1D -#define USBVISION_MXSIZE_I 0x1E -#define USBVISION_LYSIZE_I 0x1F -#define USBVISION_MYSIZE_I 0x20 -#define USBVISION_LX_OFFST 0x21 -#define USBVISION_MX_OFFST 0x22 -#define USBVISION_LY_OFFST 0x23 -#define USBVISION_MY_OFFST 0x24 -#define USBVISION_FRM_RATE 0x25 -#define USBVISION_LXSIZE_O 0x26 -#define USBVISION_MXSIZE_O 0x27 -#define USBVISION_LYSIZE_O 0x28 -#define USBVISION_MYSIZE_O 0x29 -#define USBVISION_FILT_CONT 0x2A -#define USBVISION_VO_MODE 0x2B -#define USBVISION_INTRA_CYC 0x2C -#define USBVISION_STRIP_SZ 0x2D -#define USBVISION_FORCE_INTRA 0x2E -#define USBVISION_FORCE_UP 0x2F -#define USBVISION_BUF_THR 0x30 -#define USBVISION_DVI_YUV 0x31 -#define USBVISION_AUDIO_CONT 0x32 -#define USBVISION_AUD_PK_LEN 0x33 -#define USBVISION_BLK_PK_LEN 0x34 -#define USBVISION_PCM_THR1 0x38 -#define USBVISION_PCM_THR2 0x39 -#define USBVISION_DIST_THR_L 0x3A -#define USBVISION_DIST_THR_H 0x3B -#define USBVISION_MAX_DIST_L 0x3C -#define USBVISION_MAX_DIST_H 0x3D -#define USBVISION_OP_CODE 0x33 - -#define MAX_BYTES_PER_PIXEL 4 - -#define MIN_FRAME_WIDTH 64 -#define MAX_USB_WIDTH 320 /* 384 */ -#define MAX_FRAME_WIDTH 320 /* 384 */ /* streching sometimes causes crashes*/ - -#define MIN_FRAME_HEIGHT 48 -#define MAX_USB_HEIGHT 240 /* 288 */ -#define MAX_FRAME_HEIGHT 240 /* 288 */ /* Streching sometimes causes crashes*/ - -#define MAX_FRAME_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL) -#define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) /* bytesize of clipmask */ - -#define USBVISION_URB_FRAMES 32 - -#define USBVISION_NUM_HEADERMARKER 20 -#define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */ -#define USBVISION_NUMSBUF 2 /* Dimensioning the USB S buffering */ - -#define USBVISION_POWEROFF_TIME (3 * HZ) /* 3 seconds */ - - -#define FRAMERATE_MIN 0 -#define FRAMERATE_MAX 31 - -enum { - ISOC_MODE_YUV422 = 0x03, - ISOC_MODE_YUV420 = 0x14, - ISOC_MODE_COMPRESS = 0x60, -}; - -/* This macro restricts an int variable to an inclusive range */ -#define RESTRICT_TO_RANGE(v, mi, ma) \ - { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); } - -/* - * We use macros to do YUV -> RGB conversion because this is - * very important for speed and totally unimportant for size. - * - * YUV -> RGB Conversion - * --------------------- - * - * B = 1.164*(Y-16) + 2.018*(V-128) - * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128) - * R = 1.164*(Y-16) + 1.596*(U-128) - * - * If you fancy integer arithmetics (as you should), hear this: - * - * 65536*B = 76284*(Y-16) + 132252*(V-128) - * 65536*G = 76284*(Y-16) - 53281*(U-128) - 25625*(V-128) - * 65536*R = 76284*(Y-16) + 104595*(U-128) - * - * Make sure the output values are within [0..255] range. - */ -#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x))) -#define YUV_TO_RGB_BY_THE_BOOK(my, mu, mv, mr, mg, mb) { \ - int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \ - mm_y = (my) - 16; \ - mm_u = (mu) - 128; \ - mm_v = (mv) - 128; \ - mm_yc = mm_y * 76284; \ - mm_b = (mm_yc + 132252 * mm_v) >> 16; \ - mm_g = (mm_yc - 53281 * mm_u - 25625 * mm_v) >> 16; \ - mm_r = (mm_yc + 104595 * mm_u) >> 16; \ - mb = LIMIT_RGB(mm_b); \ - mg = LIMIT_RGB(mm_g); \ - mr = LIMIT_RGB(mm_r); \ -} - -/* Debugging aid */ -#define USBVISION_SAY_AND_WAIT(what) { \ - wait_queue_head_t wq; \ - init_waitqueue_head(&wq); \ - printk(KERN_INFO "Say: %s\n", what); \ - interruptible_sleep_on_timeout(&wq, HZ * 3); \ -} - -/* - * This macro checks if usbvision is still operational. The 'usbvision' - * pointer must be valid, usbvision->dev must be valid, we are not - * removing the device and the device has not erred on us. - */ -#define USBVISION_IS_OPERATIONAL(udevice) (\ - (udevice != NULL) && \ - ((udevice)->dev != NULL) && \ - ((udevice)->last_error == 0) && \ - (!(udevice)->remove_pending)) - -#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 */ -/* ----------------------------------------------------------------- */ -enum scan_state { - scan_state_scanning, /* Scanning for header */ - scan_state_lines /* Parsing lines */ -}; - -/* Completion states of the data parser */ -enum parse_state { - parse_state_continue, /* Just parse next item */ - parse_state_next_frame, /* Frame done, send it to V4L */ - parse_state_out, /* Not enough data for frame */ - parse_state_end_parse /* End parsing */ -}; - -enum frame_state { - frame_state_unused, /* Unused (no MCAPTURE) */ - frame_state_ready, /* Ready to start grabbing */ - frame_state_grabbing, /* In the process of being grabbed into */ - frame_state_done, /* Finished grabbing, but not been synced yet */ - frame_state_done_hold, /* Are syncing or reading */ - frame_state_error, /* Something bad happened while processing */ -}; - -/* stream states */ -enum stream_state { - stream_off, /* Driver streaming is completely OFF */ - stream_idle, /* Driver streaming is ready to be put ON by the application */ - stream_interrupt, /* Driver streaming must be interrupted */ - stream_on, /* Driver streaming is put ON by the application */ -}; - -enum isoc_state { - isoc_state_in_frame, /* Isoc packet is member of frame */ - isoc_state_no_frame, /* Isoc packet is not member of any frame */ -}; - -struct usb_device; - -struct usbvision_sbuf { - char *data; - struct urb *urb; -}; - -#define USBVISION_MAGIC_1 0x55 -#define USBVISION_MAGIC_2 0xAA -#define USBVISION_HEADER_LENGTH 0x0c -#define USBVISION_SAA7111_ADDR 0x48 -#define USBVISION_SAA7113_ADDR 0x4a -#define USBVISION_IIC_LRACK 0x20 -#define USBVISION_IIC_LRNACK 0x30 -#define USBVISION_FRAME_FORMAT_PARAM_INTRA (1<<7) - -struct usbvision_v4l2_format_st { - int supported; - int bytes_per_pixel; - int depth; - int format; - char *desc; -}; -#define USBVISION_SUPPORTED_PALETTES ARRAY_SIZE(usbvision_v4l2_format) - -struct usbvision_frame_header { - unsigned char magic_1; /* 0 magic */ - unsigned char magic_2; /* 1 magic */ - unsigned char header_length; /* 2 */ - unsigned char frame_num; /* 3 */ - unsigned char frame_phase; /* 4 */ - unsigned char frame_latency; /* 5 */ - unsigned char data_format; /* 6 */ - unsigned char format_param; /* 7 */ - unsigned char frame_width_lo; /* 8 */ - unsigned char frame_width_hi; /* 9 */ - unsigned char frame_height_lo; /* 10 */ - unsigned char frame_height_hi; /* 11 */ - __u16 frame_width; /* 8 - 9 after endian correction*/ - __u16 frame_height; /* 10 - 11 after endian correction*/ -}; - -struct usbvision_frame { - char *data; /* Frame buffer */ - struct usbvision_frame_header isoc_header; /* Header from stream */ - - int width; /* Width application is expecting */ - int height; /* Height */ - int index; /* Frame index */ - int frmwidth; /* Width the frame actually is */ - int frmheight; /* Height */ - - volatile int grabstate; /* State of grabbing */ - int scanstate; /* State of scanning */ - - struct list_head frame; - - int curline; /* Line of frame we're working on */ - - long scanlength; /* uncompressed, raw data length of frame */ - long bytes_read; /* amount of scanlength that has been read from data */ - struct usbvision_v4l2_format_st v4l2_format; /* format the user needs*/ - int v4l2_linesize; /* bytes for one videoline*/ - struct timeval timestamp; - int sequence; /* How many video frames we send to user */ -}; - -#define CODEC_SAA7113 7113 -#define CODEC_SAA7111 7111 -#define CODEC_WEBCAM 3000 -#define BRIDGE_NT1003 1003 -#define BRIDGE_NT1004 1004 -#define BRIDGE_NT1005 1005 - -struct usbvision_device_data_st { - __u64 video_norm; - const char *model_string; - int interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */ - __u16 codec; - unsigned video_channels:3; - unsigned audio_channels:2; - unsigned radio:1; - unsigned vbi:1; - unsigned tuner:1; - unsigned vin_reg1_override:1; /* Override default value with */ - unsigned vin_reg2_override:1; /* vin_reg1, vin_reg2, etc. */ - unsigned dvi_yuv_override:1; - __u8 vin_reg1; - __u8 vin_reg2; - __u8 dvi_yuv; - __u8 tuner_type; - __s16 x_offset; - __s16 y_offset; -}; - -/* Declared on usbvision-cards.c */ -extern struct usbvision_device_data_st usbvision_device_data[]; -extern struct usb_device_id usbvision_table[]; - -struct usb_usbvision { - struct v4l2_device v4l2_dev; - struct video_device *vdev; /* Video Device */ - struct video_device *rdev; /* Radio Device */ - - /* i2c Declaration Section*/ - struct i2c_adapter i2c_adap; - int registered_i2c; - - struct urb *ctrl_urb; - unsigned char ctrl_urb_buffer[8]; - int ctrl_urb_busy; - struct usb_ctrlrequest ctrl_urb_setup; - wait_queue_head_t ctrl_urb_wq; /* Processes waiting */ - - /* configuration part */ - int have_tuner; - int tuner_type; - int bridge_type; /* NT1003, NT1004, NT1005 */ - int radio; - int video_inputs; /* # of inputs */ - unsigned long freq; - int audio_mute; - int audio_channel; - int isoc_mode; /* format of video data for the usb isoc-transfer */ - unsigned int nr; /* Number of the device */ - - /* Device structure */ - struct usb_device *dev; - /* usb transfer */ - int num_alt; /* Number of alternative settings */ - unsigned int *alt_max_pkt_size; /* array of max_packet_size */ - unsigned char iface; /* Video interface number */ - unsigned char iface_alt; /* Alt settings */ - unsigned char vin_reg2_preset; - struct mutex v4l2_lock; - struct timer_list power_off_timer; - struct work_struct power_off_work; - int power; /* is the device powered on? */ - int user; /* user count for exclusive use */ - int initialized; /* Had we already sent init sequence? */ - int dev_model; /* What type of USBVISION device we got? */ - enum stream_state streaming; /* Are we streaming Isochronous? */ - int last_error; /* What calamity struck us? */ - int curwidth; /* width of the frame the device is currently set to*/ - int curheight; /* height of the frame the device is currently set to*/ - int stretch_width; /* stretch-factor for frame width (from usb to screen)*/ - int stretch_height; /* stretch-factor for frame height (from usb to screen)*/ - char *fbuf; /* Videodev buffer area for mmap*/ - int max_frame_size; /* Bytes in one video frame */ - int fbuf_size; /* Videodev buffer size */ - spinlock_t queue_lock; /* spinlock for protecting mods on inqueue and outqueue */ - struct list_head inqueue, outqueue; /* queued frame list and ready to dequeue frame list */ - wait_queue_head_t wait_frame; /* Processes waiting */ - wait_queue_head_t wait_stream; /* Processes waiting */ - struct usbvision_frame *cur_frame; /* pointer to current frame, set by usbvision_find_header */ - struct usbvision_frame frame[USBVISION_NUMFRAMES]; /* frame buffer */ - int num_frames; /* number of frames allocated */ - struct usbvision_sbuf sbuf[USBVISION_NUMSBUF]; /* S buffering */ - volatile int remove_pending; /* If set then about to exit */ - - /* Scratch space from the Isochronous Pipe.*/ - unsigned char *scratch; - int scratch_read_ptr; - int scratch_write_ptr; - int scratch_headermarker[USBVISION_NUM_HEADERMARKER]; - int scratch_headermarker_read_ptr; - int scratch_headermarker_write_ptr; - enum isoc_state isocstate; - struct usbvision_v4l2_format_st palette; - - struct v4l2_capability vcap; /* Video capabilities */ - unsigned int ctl_input; /* selected input */ - v4l2_std_id tvnorm_id; /* selected tv norm */ - unsigned char video_endp; /* 0x82 for USBVISION devices based */ - - /* Decompression stuff: */ - unsigned char *intra_frame_buffer; /* Buffer for reference frame */ - int block_pos; /* for test only */ - int request_intra; /* 0 = normal; 1 = intra frame is requested; */ - int last_isoc_frame_num; /* check for lost isoc frames */ - int isoc_packet_size; /* need to calculate used_bandwidth */ - int used_bandwidth; /* used bandwidth 0-100%, need to set compr_level */ - int compr_level; /* How strong (100) or weak (0) is compression */ - int last_compr_level; /* How strong (100) or weak (0) was compression */ - int usb_bandwidth; /* Mbit/s */ - - /* Statistics that can be overlayed on the screen */ - unsigned long isoc_urb_count; /* How many URBs we received so far */ - unsigned long urb_length; /* Length of last URB */ - unsigned long isoc_data_count; /* How many bytes we received */ - unsigned long header_count; /* How many frame headers we found */ - unsigned long scratch_ovf_count; /* How many times we overflowed scratch */ - unsigned long isoc_skip_count; /* How many empty ISO packets received */ - unsigned long isoc_err_count; /* How many bad ISO packets received */ - unsigned long isoc_packet_count; /* How many packets we totally got */ - unsigned long time_in_irq; /* How long do we need for interrupt */ - int isoc_measure_bandwidth_count; - int frame_num; /* How many video frames we send to user */ - int max_strip_len; /* How big is the biggest strip */ - int comprblock_pos; - int strip_len_errors; /* How many times was block_pos greater than strip_len */ - int strip_magic_errors; - int strip_line_number_errors; - int compr_block_types[4]; -}; - -static inline struct usb_usbvision *to_usbvision(struct v4l2_device *v4l2_dev) -{ - return container_of(v4l2_dev, struct usb_usbvision, v4l2_dev); -} - -#define call_all(usbvision, o, f, args...) \ - v4l2_device_call_all(&usbvision->v4l2_dev, 0, o, f, ##args) - -/* --------------------------------------------------------------- */ -/* defined in usbvision-i2c.c */ -/* i2c-algo-usb declaration */ -/* --------------------------------------------------------------- */ - -/* ----------------------------------------------------------------------- */ -/* usbvision specific I2C functions */ -/* ----------------------------------------------------------------------- */ -int usbvision_i2c_register(struct usb_usbvision *usbvision); -int usbvision_i2c_unregister(struct usb_usbvision *usbvision); - -/* defined in usbvision-core.c */ -int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg); -int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, - unsigned char value); - -int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames); -void usbvision_frames_free(struct usb_usbvision *usbvision); -int usbvision_scratch_alloc(struct usb_usbvision *usbvision); -void usbvision_scratch_free(struct usb_usbvision *usbvision); -int usbvision_decompress_alloc(struct usb_usbvision *usbvision); -void usbvision_decompress_free(struct usb_usbvision *usbvision); - -int usbvision_setup(struct usb_usbvision *usbvision, int format); -int usbvision_init_isoc(struct usb_usbvision *usbvision); -int usbvision_restart_isoc(struct usb_usbvision *usbvision); -void usbvision_stop_isoc(struct usb_usbvision *usbvision); -int usbvision_set_alternate(struct usb_usbvision *dev); - -int usbvision_set_audio(struct usb_usbvision *usbvision, int audio_channel); -int usbvision_audio_off(struct usb_usbvision *usbvision); - -int usbvision_begin_streaming(struct usb_usbvision *usbvision); -void usbvision_empty_framequeues(struct usb_usbvision *dev); -int usbvision_stream_interrupt(struct usb_usbvision *dev); - -int usbvision_muxsel(struct usb_usbvision *usbvision, int channel); -int usbvision_set_input(struct usb_usbvision *usbvision); -int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height); - -void usbvision_init_power_off_timer(struct usb_usbvision *usbvision); -void usbvision_set_power_off_timer(struct usb_usbvision *usbvision); -void usbvision_reset_power_off_timer(struct usb_usbvision *usbvision); -int usbvision_power_off(struct usb_usbvision *usbvision); -int usbvision_power_on(struct usb_usbvision *usbvision); - -#endif /* __LINUX_USBVISION_H */ - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/uvc/Kconfig b/drivers/media/video/uvc/Kconfig deleted file mode 100644 index 541c9f1e4c6a..000000000000 --- a/drivers/media/video/uvc/Kconfig +++ /dev/null @@ -1,19 +0,0 @@ -config USB_VIDEO_CLASS - tristate "USB Video Class (UVC)" - select VIDEOBUF2_VMALLOC - ---help--- - Support for the USB Video Class (UVC). Currently only video - input devices, such as webcams, are supported. - - For more information see: <http://linux-uvc.berlios.de/> - -config USB_VIDEO_CLASS_INPUT_EVDEV - bool "UVC input events device support" - default y - depends on USB_VIDEO_CLASS - depends on USB_VIDEO_CLASS=INPUT || INPUT=y - ---help--- - This option makes USB Video Class devices register an input device - to report button events. - - If you are in doubt, say Y. diff --git a/drivers/media/video/uvc/Makefile b/drivers/media/video/uvc/Makefile deleted file mode 100644 index c26d12fdb8f4..000000000000 --- a/drivers/media/video/uvc/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \ - uvc_status.o uvc_isight.o uvc_debugfs.o -ifeq ($(CONFIG_MEDIA_CONTROLLER),y) -uvcvideo-objs += uvc_entity.o -endif -obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c deleted file mode 100644 index f7061a5ef1d2..000000000000 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ /dev/null @@ -1,2165 +0,0 @@ -/* - * uvc_ctrl.c -- USB Video Class driver - Controls - * - * Copyright (C) 2005-2010 - * Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * 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. - * - */ - -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/uaccess.h> -#include <linux/usb.h> -#include <linux/videodev2.h> -#include <linux/vmalloc.h> -#include <linux/wait.h> -#include <linux/atomic.h> -#include <media/v4l2-ctrls.h> - -#include "uvcvideo.h" - -#define UVC_CTRL_DATA_CURRENT 0 -#define UVC_CTRL_DATA_BACKUP 1 -#define UVC_CTRL_DATA_MIN 2 -#define UVC_CTRL_DATA_MAX 3 -#define UVC_CTRL_DATA_RES 4 -#define UVC_CTRL_DATA_DEF 5 -#define UVC_CTRL_DATA_LAST 6 - -/* ------------------------------------------------------------------------ - * Controls - */ - -static struct uvc_control_info uvc_ctrls[] = { - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_BRIGHTNESS_CONTROL, - .index = 0, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_CONTRAST_CONTROL, - .index = 1, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_HUE_CONTROL, - .index = 2, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE - | UVC_CTRL_FLAG_AUTO_UPDATE, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_SATURATION_CONTROL, - .index = 3, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_SHARPNESS_CONTROL, - .index = 4, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_GAMMA_CONTROL, - .index = 5, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL, - .index = 6, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE - | UVC_CTRL_FLAG_AUTO_UPDATE, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL, - .index = 7, - .size = 4, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE - | UVC_CTRL_FLAG_AUTO_UPDATE, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL, - .index = 8, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_GAIN_CONTROL, - .index = 9, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL, - .index = 10, - .size = 1, - .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR - | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_HUE_AUTO_CONTROL, - .index = 11, - .size = 1, - .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR - | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, - .index = 12, - .size = 1, - .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR - | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, - .index = 13, - .size = 1, - .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR - | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_DIGITAL_MULTIPLIER_CONTROL, - .index = 14, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL, - .index = 15, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL, - .index = 16, - .size = 1, - .flags = UVC_CTRL_FLAG_GET_CUR, - }, - { - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_ANALOG_LOCK_STATUS_CONTROL, - .index = 17, - .size = 1, - .flags = UVC_CTRL_FLAG_GET_CUR, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_SCANNING_MODE_CONTROL, - .index = 0, - .size = 1, - .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR - | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_AE_MODE_CONTROL, - .index = 1, - .size = 1, - .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR - | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_GET_RES - | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_AE_PRIORITY_CONTROL, - .index = 2, - .size = 1, - .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR - | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, - .index = 3, - .size = 4, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL, - .index = 4, - .size = 1, - .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_FOCUS_ABSOLUTE_CONTROL, - .index = 5, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE - | UVC_CTRL_FLAG_AUTO_UPDATE, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_FOCUS_RELATIVE_CONTROL, - .index = 6, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN - | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES - | UVC_CTRL_FLAG_GET_DEF - | UVC_CTRL_FLAG_AUTO_UPDATE, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_IRIS_ABSOLUTE_CONTROL, - .index = 7, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE - | UVC_CTRL_FLAG_AUTO_UPDATE, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_IRIS_RELATIVE_CONTROL, - .index = 8, - .size = 1, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_AUTO_UPDATE, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_ZOOM_ABSOLUTE_CONTROL, - .index = 9, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE - | UVC_CTRL_FLAG_AUTO_UPDATE, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_ZOOM_RELATIVE_CONTROL, - .index = 10, - .size = 3, - .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN - | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES - | UVC_CTRL_FLAG_GET_DEF - | UVC_CTRL_FLAG_AUTO_UPDATE, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL, - .index = 11, - .size = 8, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE - | UVC_CTRL_FLAG_AUTO_UPDATE, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_PANTILT_RELATIVE_CONTROL, - .index = 12, - .size = 4, - .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN - | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES - | UVC_CTRL_FLAG_GET_DEF - | UVC_CTRL_FLAG_AUTO_UPDATE, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_ROLL_ABSOLUTE_CONTROL, - .index = 13, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR - | UVC_CTRL_FLAG_GET_RANGE - | UVC_CTRL_FLAG_RESTORE - | UVC_CTRL_FLAG_AUTO_UPDATE, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_ROLL_RELATIVE_CONTROL, - .index = 14, - .size = 2, - .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN - | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES - | UVC_CTRL_FLAG_GET_DEF - | UVC_CTRL_FLAG_AUTO_UPDATE, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_FOCUS_AUTO_CONTROL, - .index = 17, - .size = 1, - .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR - | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE, - }, - { - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_PRIVACY_CONTROL, - .index = 18, - .size = 1, - .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR - | UVC_CTRL_FLAG_RESTORE - | UVC_CTRL_FLAG_AUTO_UPDATE, - }, -}; - -static struct uvc_menu_info power_line_frequency_controls[] = { - { 0, "Disabled" }, - { 1, "50 Hz" }, - { 2, "60 Hz" }, -}; - -static struct uvc_menu_info exposure_auto_controls[] = { - { 2, "Auto Mode" }, - { 1, "Manual Mode" }, - { 4, "Shutter Priority Mode" }, - { 8, "Aperture Priority Mode" }, -}; - -static __s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping, - __u8 query, const __u8 *data) -{ - __s8 zoom = (__s8)data[0]; - - switch (query) { - case UVC_GET_CUR: - return (zoom == 0) ? 0 : (zoom > 0 ? data[2] : -data[2]); - - case UVC_GET_MIN: - case UVC_GET_MAX: - case UVC_GET_RES: - case UVC_GET_DEF: - default: - return data[2]; - } -} - -static void uvc_ctrl_set_zoom(struct uvc_control_mapping *mapping, - __s32 value, __u8 *data) -{ - data[0] = value == 0 ? 0 : (value > 0) ? 1 : 0xff; - data[2] = min((int)abs(value), 0xff); -} - -static struct uvc_control_mapping uvc_ctrl_mappings[] = { - { - .id = V4L2_CID_BRIGHTNESS, - .name = "Brightness", - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_BRIGHTNESS_CONTROL, - .size = 16, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_SIGNED, - }, - { - .id = V4L2_CID_CONTRAST, - .name = "Contrast", - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_CONTRAST_CONTROL, - .size = 16, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, - }, - { - .id = V4L2_CID_HUE, - .name = "Hue", - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_HUE_CONTROL, - .size = 16, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_SIGNED, - .master_id = V4L2_CID_HUE_AUTO, - .master_manual = 0, - }, - { - .id = V4L2_CID_SATURATION, - .name = "Saturation", - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_SATURATION_CONTROL, - .size = 16, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, - }, - { - .id = V4L2_CID_SHARPNESS, - .name = "Sharpness", - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_SHARPNESS_CONTROL, - .size = 16, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, - }, - { - .id = V4L2_CID_GAMMA, - .name = "Gamma", - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_GAMMA_CONTROL, - .size = 16, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, - }, - { - .id = V4L2_CID_BACKLIGHT_COMPENSATION, - .name = "Backlight Compensation", - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL, - .size = 16, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, - }, - { - .id = V4L2_CID_GAIN, - .name = "Gain", - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_GAIN_CONTROL, - .size = 16, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, - }, - { - .id = V4L2_CID_POWER_LINE_FREQUENCY, - .name = "Power Line Frequency", - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL, - .size = 2, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_MENU, - .data_type = UVC_CTRL_DATA_TYPE_ENUM, - .menu_info = power_line_frequency_controls, - .menu_count = ARRAY_SIZE(power_line_frequency_controls), - }, - { - .id = V4L2_CID_HUE_AUTO, - .name = "Hue, Auto", - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_HUE_AUTO_CONTROL, - .size = 1, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, - .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, - .slave_ids = { V4L2_CID_HUE, }, - }, - { - .id = V4L2_CID_EXPOSURE_AUTO, - .name = "Exposure, Auto", - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_AE_MODE_CONTROL, - .size = 4, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_MENU, - .data_type = UVC_CTRL_DATA_TYPE_BITMASK, - .menu_info = exposure_auto_controls, - .menu_count = ARRAY_SIZE(exposure_auto_controls), - .slave_ids = { V4L2_CID_EXPOSURE_ABSOLUTE, }, - }, - { - .id = V4L2_CID_EXPOSURE_AUTO_PRIORITY, - .name = "Exposure, Auto Priority", - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_AE_PRIORITY_CONTROL, - .size = 1, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, - .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, - }, - { - .id = V4L2_CID_EXPOSURE_ABSOLUTE, - .name = "Exposure (Absolute)", - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, - .size = 32, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, - .master_id = V4L2_CID_EXPOSURE_AUTO, - .master_manual = V4L2_EXPOSURE_MANUAL, - }, - { - .id = V4L2_CID_AUTO_WHITE_BALANCE, - .name = "White Balance Temperature, Auto", - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, - .size = 1, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, - .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, - .slave_ids = { V4L2_CID_WHITE_BALANCE_TEMPERATURE, }, - }, - { - .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, - .name = "White Balance Temperature", - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL, - .size = 16, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, - .master_id = V4L2_CID_AUTO_WHITE_BALANCE, - .master_manual = 0, - }, - { - .id = V4L2_CID_AUTO_WHITE_BALANCE, - .name = "White Balance Component, Auto", - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, - .size = 1, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, - .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, - .slave_ids = { V4L2_CID_BLUE_BALANCE, - V4L2_CID_RED_BALANCE }, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .name = "White Balance Blue Component", - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL, - .size = 16, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_SIGNED, - .master_id = V4L2_CID_AUTO_WHITE_BALANCE, - .master_manual = 0, - }, - { - .id = V4L2_CID_RED_BALANCE, - .name = "White Balance Red Component", - .entity = UVC_GUID_UVC_PROCESSING, - .selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL, - .size = 16, - .offset = 16, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_SIGNED, - .master_id = V4L2_CID_AUTO_WHITE_BALANCE, - .master_manual = 0, - }, - { - .id = V4L2_CID_FOCUS_ABSOLUTE, - .name = "Focus (absolute)", - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_FOCUS_ABSOLUTE_CONTROL, - .size = 16, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, - .master_id = V4L2_CID_FOCUS_AUTO, - .master_manual = 0, - }, - { - .id = V4L2_CID_FOCUS_AUTO, - .name = "Focus, Auto", - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_FOCUS_AUTO_CONTROL, - .size = 1, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, - .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, - .slave_ids = { V4L2_CID_FOCUS_ABSOLUTE, }, - }, - { - .id = V4L2_CID_IRIS_ABSOLUTE, - .name = "Iris, Absolute", - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_IRIS_ABSOLUTE_CONTROL, - .size = 16, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, - }, - { - .id = V4L2_CID_IRIS_RELATIVE, - .name = "Iris, Relative", - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_IRIS_RELATIVE_CONTROL, - .size = 8, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_SIGNED, - }, - { - .id = V4L2_CID_ZOOM_ABSOLUTE, - .name = "Zoom, Absolute", - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_ZOOM_ABSOLUTE_CONTROL, - .size = 16, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, - }, - { - .id = V4L2_CID_ZOOM_CONTINUOUS, - .name = "Zoom, Continuous", - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_ZOOM_RELATIVE_CONTROL, - .size = 0, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_SIGNED, - .get = uvc_ctrl_get_zoom, - .set = uvc_ctrl_set_zoom, - }, - { - .id = V4L2_CID_PAN_ABSOLUTE, - .name = "Pan (Absolute)", - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL, - .size = 32, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, - }, - { - .id = V4L2_CID_TILT_ABSOLUTE, - .name = "Tilt (Absolute)", - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL, - .size = 32, - .offset = 32, - .v4l2_type = V4L2_CTRL_TYPE_INTEGER, - .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, - }, - { - .id = V4L2_CID_PRIVACY, - .name = "Privacy", - .entity = UVC_GUID_UVC_CAMERA, - .selector = UVC_CT_PRIVACY_CONTROL, - .size = 1, - .offset = 0, - .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, - .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, - }, -}; - -/* ------------------------------------------------------------------------ - * Utility functions - */ - -static inline __u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id) -{ - return ctrl->uvc_data + id * ctrl->info.size; -} - -static inline int uvc_test_bit(const __u8 *data, int bit) -{ - return (data[bit >> 3] >> (bit & 7)) & 1; -} - -static inline void uvc_clear_bit(__u8 *data, int bit) -{ - data[bit >> 3] &= ~(1 << (bit & 7)); -} - -/* Extract the bit string specified by mapping->offset and mapping->size - * from the little-endian data stored at 'data' and return the result as - * a signed 32bit integer. Sign extension will be performed if the mapping - * references a signed data type. - */ -static __s32 uvc_get_le_value(struct uvc_control_mapping *mapping, - __u8 query, const __u8 *data) -{ - int bits = mapping->size; - int offset = mapping->offset; - __s32 value = 0; - __u8 mask; - - data += offset / 8; - offset &= 7; - mask = ((1LL << bits) - 1) << offset; - - for (; bits > 0; data++) { - __u8 byte = *data & mask; - value |= offset > 0 ? (byte >> offset) : (byte << (-offset)); - bits -= 8 - (offset > 0 ? offset : 0); - offset -= 8; - mask = (1 << bits) - 1; - } - - /* Sign-extend the value if needed. */ - if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) - value |= -(value & (1 << (mapping->size - 1))); - - return value; -} - -/* Set the bit string specified by mapping->offset and mapping->size - * in the little-endian data stored at 'data' to the value 'value'. - */ -static void uvc_set_le_value(struct uvc_control_mapping *mapping, - __s32 value, __u8 *data) -{ - int bits = mapping->size; - int offset = mapping->offset; - __u8 mask; - - /* According to the v4l2 spec, writing any value to a button control - * should result in the action belonging to the button control being - * triggered. UVC devices however want to see a 1 written -> override - * value. - */ - if (mapping->v4l2_type == V4L2_CTRL_TYPE_BUTTON) - value = -1; - - data += offset / 8; - offset &= 7; - - for (; bits > 0; data++) { - mask = ((1LL << bits) - 1) << offset; - *data = (*data & ~mask) | ((value << offset) & mask); - value >>= offset ? offset : 8; - bits -= 8 - offset; - offset = 0; - } -} - -/* ------------------------------------------------------------------------ - * Terminal and unit management - */ - -static const __u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING; -static const __u8 uvc_camera_guid[16] = UVC_GUID_UVC_CAMERA; -static const __u8 uvc_media_transport_input_guid[16] = - UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT; - -static int uvc_entity_match_guid(const struct uvc_entity *entity, - const __u8 guid[16]) -{ - switch (UVC_ENTITY_TYPE(entity)) { - case UVC_ITT_CAMERA: - return memcmp(uvc_camera_guid, guid, 16) == 0; - - case UVC_ITT_MEDIA_TRANSPORT_INPUT: - return memcmp(uvc_media_transport_input_guid, guid, 16) == 0; - - case UVC_VC_PROCESSING_UNIT: - return memcmp(uvc_processing_guid, guid, 16) == 0; - - case UVC_VC_EXTENSION_UNIT: - return memcmp(entity->extension.guidExtensionCode, - guid, 16) == 0; - - default: - return 0; - } -} - -/* ------------------------------------------------------------------------ - * UVC Controls - */ - -static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id, - struct uvc_control_mapping **mapping, struct uvc_control **control, - int next) -{ - struct uvc_control *ctrl; - struct uvc_control_mapping *map; - unsigned int i; - - if (entity == NULL) - return; - - for (i = 0; i < entity->ncontrols; ++i) { - ctrl = &entity->controls[i]; - if (!ctrl->initialized) - continue; - - list_for_each_entry(map, &ctrl->info.mappings, list) { - if ((map->id == v4l2_id) && !next) { - *control = ctrl; - *mapping = map; - return; - } - - if ((*mapping == NULL || (*mapping)->id > map->id) && - (map->id > v4l2_id) && next) { - *control = ctrl; - *mapping = map; - } - } - } -} - -static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, - __u32 v4l2_id, struct uvc_control_mapping **mapping) -{ - struct uvc_control *ctrl = NULL; - struct uvc_entity *entity; - int next = v4l2_id & V4L2_CTRL_FLAG_NEXT_CTRL; - - *mapping = NULL; - - /* Mask the query flags. */ - v4l2_id &= V4L2_CTRL_ID_MASK; - - /* Find the control. */ - list_for_each_entry(entity, &chain->entities, chain) { - __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); - if (ctrl && !next) - return ctrl; - } - - if (ctrl == NULL && !next) - uvc_trace(UVC_TRACE_CONTROL, "Control 0x%08x not found.\n", - v4l2_id); - - return ctrl; -} - -static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain, - struct uvc_control *ctrl) -{ - int ret; - - if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) { - ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id, - chain->dev->intfnum, ctrl->info.selector, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF), - ctrl->info.size); - if (ret < 0) - return ret; - } - - if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN) { - ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id, - chain->dev->intfnum, ctrl->info.selector, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN), - ctrl->info.size); - if (ret < 0) - return ret; - } - if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) { - ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id, - chain->dev->intfnum, ctrl->info.selector, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX), - ctrl->info.size); - if (ret < 0) - return ret; - } - if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) { - ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id, - chain->dev->intfnum, ctrl->info.selector, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES), - ctrl->info.size); - if (ret < 0) { - if (UVC_ENTITY_TYPE(ctrl->entity) != - UVC_VC_EXTENSION_UNIT) - return ret; - - /* GET_RES is mandatory for XU controls, but some - * cameras still choke on it. Ignore errors and set the - * resolution value to zero. - */ - uvc_warn_once(chain->dev, UVC_WARN_XU_GET_RES, - "UVC non compliance - GET_RES failed on " - "an XU control. Enabling workaround.\n"); - memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES), 0, - ctrl->info.size); - } - } - - ctrl->cached = 1; - return 0; -} - -static int __uvc_ctrl_get(struct uvc_video_chain *chain, - struct uvc_control *ctrl, struct uvc_control_mapping *mapping, - s32 *value) -{ - struct uvc_menu_info *menu; - unsigned int i; - int ret; - - if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) - return -EINVAL; - - if (!ctrl->loaded) { - ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id, - chain->dev->intfnum, ctrl->info.selector, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), - ctrl->info.size); - if (ret < 0) - return ret; - - ctrl->loaded = 1; - } - - *value = mapping->get(mapping, UVC_GET_CUR, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); - - if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { - menu = mapping->menu_info; - for (i = 0; i < mapping->menu_count; ++i, ++menu) { - if (menu->value == *value) { - *value = i; - break; - } - } - } - - return 0; -} - -static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, - struct uvc_control *ctrl, - struct uvc_control_mapping *mapping, - struct v4l2_queryctrl *v4l2_ctrl) -{ - struct uvc_control_mapping *master_map = NULL; - struct uvc_control *master_ctrl = NULL; - struct uvc_menu_info *menu; - unsigned int i; - - memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl); - v4l2_ctrl->id = mapping->id; - v4l2_ctrl->type = mapping->v4l2_type; - strlcpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name); - v4l2_ctrl->flags = 0; - - if (!(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) - v4l2_ctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; - if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR)) - v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; - - if (mapping->master_id) - __uvc_find_control(ctrl->entity, mapping->master_id, - &master_map, &master_ctrl, 0); - if (master_ctrl && (master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) { - s32 val; - int ret = __uvc_ctrl_get(chain, master_ctrl, master_map, &val); - if (ret < 0) - return ret; - - if (val != mapping->master_manual) - v4l2_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; - } - - if (!ctrl->cached) { - int ret = uvc_ctrl_populate_cache(chain, ctrl); - if (ret < 0) - return ret; - } - - if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) { - v4l2_ctrl->default_value = mapping->get(mapping, UVC_GET_DEF, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF)); - } - - switch (mapping->v4l2_type) { - case V4L2_CTRL_TYPE_MENU: - v4l2_ctrl->minimum = 0; - v4l2_ctrl->maximum = mapping->menu_count - 1; - v4l2_ctrl->step = 1; - - menu = mapping->menu_info; - for (i = 0; i < mapping->menu_count; ++i, ++menu) { - if (menu->value == v4l2_ctrl->default_value) { - v4l2_ctrl->default_value = i; - break; - } - } - - return 0; - - case V4L2_CTRL_TYPE_BOOLEAN: - v4l2_ctrl->minimum = 0; - v4l2_ctrl->maximum = 1; - v4l2_ctrl->step = 1; - return 0; - - case V4L2_CTRL_TYPE_BUTTON: - v4l2_ctrl->minimum = 0; - v4l2_ctrl->maximum = 0; - v4l2_ctrl->step = 0; - return 0; - - default: - break; - } - - if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN) - v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN)); - - if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) - v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX)); - - if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) - v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); - - return 0; -} - -int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, - struct v4l2_queryctrl *v4l2_ctrl) -{ - struct uvc_control *ctrl; - struct uvc_control_mapping *mapping; - int ret; - - ret = mutex_lock_interruptible(&chain->ctrl_mutex); - if (ret < 0) - return -ERESTARTSYS; - - ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping); - if (ctrl == NULL) { - ret = -EINVAL; - goto done; - } - - ret = __uvc_query_v4l2_ctrl(chain, ctrl, mapping, v4l2_ctrl); -done: - mutex_unlock(&chain->ctrl_mutex); - return ret; -} - -/* - * Mapping V4L2 controls to UVC controls can be straighforward if done well. - * Most of the UVC controls exist in V4L2, and can be mapped directly. Some - * must be grouped (for instance the Red Balance, Blue Balance and Do White - * Balance V4L2 controls use the White Balance Component UVC control) or - * otherwise translated. The approach we take here is to use a translation - * table for the controls that can be mapped directly, and handle the others - * manually. - */ -int uvc_query_v4l2_menu(struct uvc_video_chain *chain, - struct v4l2_querymenu *query_menu) -{ - struct uvc_menu_info *menu_info; - struct uvc_control_mapping *mapping; - struct uvc_control *ctrl; - u32 index = query_menu->index; - u32 id = query_menu->id; - int ret; - - memset(query_menu, 0, sizeof(*query_menu)); - query_menu->id = id; - query_menu->index = index; - - ret = mutex_lock_interruptible(&chain->ctrl_mutex); - if (ret < 0) - return -ERESTARTSYS; - - ctrl = uvc_find_control(chain, query_menu->id, &mapping); - if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) { - ret = -EINVAL; - goto done; - } - - if (query_menu->index >= mapping->menu_count) { - ret = -EINVAL; - goto done; - } - - menu_info = &mapping->menu_info[query_menu->index]; - - if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK && - (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) { - s32 bitmap; - - if (!ctrl->cached) { - ret = uvc_ctrl_populate_cache(chain, ctrl); - if (ret < 0) - goto done; - } - - bitmap = mapping->get(mapping, UVC_GET_RES, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); - if (!(bitmap & menu_info->value)) { - ret = -EINVAL; - goto done; - } - } - - strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name); - -done: - mutex_unlock(&chain->ctrl_mutex); - return ret; -} - -/* -------------------------------------------------------------------------- - * Ctrl event handling - */ - -static void uvc_ctrl_fill_event(struct uvc_video_chain *chain, - struct v4l2_event *ev, - struct uvc_control *ctrl, - struct uvc_control_mapping *mapping, - s32 value, u32 changes) -{ - struct v4l2_queryctrl v4l2_ctrl; - - __uvc_query_v4l2_ctrl(chain, ctrl, mapping, &v4l2_ctrl); - - memset(ev->reserved, 0, sizeof(ev->reserved)); - ev->type = V4L2_EVENT_CTRL; - ev->id = v4l2_ctrl.id; - ev->u.ctrl.value = value; - ev->u.ctrl.changes = changes; - ev->u.ctrl.type = v4l2_ctrl.type; - ev->u.ctrl.flags = v4l2_ctrl.flags; - ev->u.ctrl.minimum = v4l2_ctrl.minimum; - ev->u.ctrl.maximum = v4l2_ctrl.maximum; - ev->u.ctrl.step = v4l2_ctrl.step; - ev->u.ctrl.default_value = v4l2_ctrl.default_value; -} - -static void uvc_ctrl_send_event(struct uvc_fh *handle, - struct uvc_control *ctrl, struct uvc_control_mapping *mapping, - s32 value, u32 changes) -{ - struct v4l2_subscribed_event *sev; - struct v4l2_event ev; - - if (list_empty(&mapping->ev_subs)) - return; - - uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, value, changes); - - list_for_each_entry(sev, &mapping->ev_subs, node) { - if (sev->fh && (sev->fh != &handle->vfh || - (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK) || - (changes & V4L2_EVENT_CTRL_CH_FLAGS))) - v4l2_event_queue_fh(sev->fh, &ev); - } -} - -static void uvc_ctrl_send_slave_event(struct uvc_fh *handle, - struct uvc_control *master, u32 slave_id, - const struct v4l2_ext_control *xctrls, unsigned int xctrls_count) -{ - struct uvc_control_mapping *mapping = NULL; - struct uvc_control *ctrl = NULL; - u32 changes = V4L2_EVENT_CTRL_CH_FLAGS; - unsigned int i; - s32 val = 0; - - /* - * We can skip sending an event for the slave if the slave - * is being modified in the same transaction. - */ - for (i = 0; i < xctrls_count; i++) { - if (xctrls[i].id == slave_id) - return; - } - - __uvc_find_control(master->entity, slave_id, &mapping, &ctrl, 0); - if (ctrl == NULL) - return; - - if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0) - changes |= V4L2_EVENT_CTRL_CH_VALUE; - - uvc_ctrl_send_event(handle, ctrl, mapping, val, changes); -} - -static void uvc_ctrl_send_events(struct uvc_fh *handle, - const struct v4l2_ext_control *xctrls, unsigned int xctrls_count) -{ - struct uvc_control_mapping *mapping; - struct uvc_control *ctrl; - u32 changes = V4L2_EVENT_CTRL_CH_VALUE; - unsigned int i; - unsigned int j; - - for (i = 0; i < xctrls_count; ++i) { - ctrl = uvc_find_control(handle->chain, xctrls[i].id, &mapping); - - for (j = 0; j < ARRAY_SIZE(mapping->slave_ids); ++j) { - if (!mapping->slave_ids[j]) - break; - uvc_ctrl_send_slave_event(handle, ctrl, - mapping->slave_ids[j], - xctrls, xctrls_count); - } - - /* - * If the master is being modified in the same transaction - * flags may change too. - */ - if (mapping->master_id) { - for (j = 0; j < xctrls_count; j++) { - if (xctrls[j].id == mapping->master_id) { - changes |= V4L2_EVENT_CTRL_CH_FLAGS; - break; - } - } - } - - uvc_ctrl_send_event(handle, ctrl, mapping, xctrls[i].value, - changes); - } -} - -static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems) -{ - struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh); - struct uvc_control_mapping *mapping; - struct uvc_control *ctrl; - int ret; - - ret = mutex_lock_interruptible(&handle->chain->ctrl_mutex); - if (ret < 0) - return -ERESTARTSYS; - - ctrl = uvc_find_control(handle->chain, sev->id, &mapping); - if (ctrl == NULL) { - ret = -EINVAL; - goto done; - } - - list_add_tail(&sev->node, &mapping->ev_subs); - if (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL) { - struct v4l2_event ev; - u32 changes = V4L2_EVENT_CTRL_CH_FLAGS; - s32 val = 0; - - if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0) - changes |= V4L2_EVENT_CTRL_CH_VALUE; - - uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, val, - changes); - /* Mark the queue as active, allowing this initial - event to be accepted. */ - sev->elems = elems; - v4l2_event_queue_fh(sev->fh, &ev); - } - -done: - mutex_unlock(&handle->chain->ctrl_mutex); - return ret; -} - -static void uvc_ctrl_del_event(struct v4l2_subscribed_event *sev) -{ - struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh); - - mutex_lock(&handle->chain->ctrl_mutex); - list_del(&sev->node); - mutex_unlock(&handle->chain->ctrl_mutex); -} - -const struct v4l2_subscribed_event_ops uvc_ctrl_sub_ev_ops = { - .add = uvc_ctrl_add_event, - .del = uvc_ctrl_del_event, - .replace = v4l2_ctrl_replace, - .merge = v4l2_ctrl_merge, -}; - -/* -------------------------------------------------------------------------- - * Control transactions - * - * To make extended set operations as atomic as the hardware allows, controls - * are handled using begin/commit/rollback operations. - * - * At the beginning of a set request, uvc_ctrl_begin should be called to - * initialize the request. This function acquires the control lock. - * - * When setting a control, the new value is stored in the control data field - * at position UVC_CTRL_DATA_CURRENT. The control is then marked as dirty for - * later processing. If the UVC and V4L2 control sizes differ, the current - * value is loaded from the hardware before storing the new value in the data - * field. - * - * After processing all controls in the transaction, uvc_ctrl_commit or - * uvc_ctrl_rollback must be called to apply the pending changes to the - * hardware or revert them. When applying changes, all controls marked as - * dirty will be modified in the UVC device, and the dirty flag will be - * cleared. When reverting controls, the control data field - * UVC_CTRL_DATA_CURRENT is reverted to its previous value - * (UVC_CTRL_DATA_BACKUP) for all dirty controls. Both functions release the - * control lock. - */ -int uvc_ctrl_begin(struct uvc_video_chain *chain) -{ - return mutex_lock_interruptible(&chain->ctrl_mutex) ? -ERESTARTSYS : 0; -} - -static int uvc_ctrl_commit_entity(struct uvc_device *dev, - struct uvc_entity *entity, int rollback) -{ - struct uvc_control *ctrl; - unsigned int i; - int ret; - - if (entity == NULL) - return 0; - - for (i = 0; i < entity->ncontrols; ++i) { - ctrl = &entity->controls[i]; - if (!ctrl->initialized) - continue; - - /* Reset the loaded flag for auto-update controls that were - * marked as loaded in uvc_ctrl_get/uvc_ctrl_set to prevent - * uvc_ctrl_get from using the cached value, and for write-only - * controls to prevent uvc_ctrl_set from setting bits not - * explicitly set by the user. - */ - if (ctrl->info.flags & UVC_CTRL_FLAG_AUTO_UPDATE || - !(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) - ctrl->loaded = 0; - - if (!ctrl->dirty) - continue; - - if (!rollback) - ret = uvc_query_ctrl(dev, UVC_SET_CUR, ctrl->entity->id, - dev->intfnum, ctrl->info.selector, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), - ctrl->info.size); - else - ret = 0; - - if (rollback || ret < 0) - memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), - ctrl->info.size); - - ctrl->dirty = 0; - - if (ret < 0) - return ret; - } - - return 0; -} - -int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback, - const struct v4l2_ext_control *xctrls, - unsigned int xctrls_count) -{ - struct uvc_video_chain *chain = handle->chain; - struct uvc_entity *entity; - int ret = 0; - - /* Find the control. */ - list_for_each_entry(entity, &chain->entities, chain) { - ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback); - if (ret < 0) - goto done; - } - - if (!rollback) - uvc_ctrl_send_events(handle, xctrls, xctrls_count); -done: - mutex_unlock(&chain->ctrl_mutex); - return ret; -} - -int uvc_ctrl_get(struct uvc_video_chain *chain, - struct v4l2_ext_control *xctrl) -{ - struct uvc_control *ctrl; - struct uvc_control_mapping *mapping; - - ctrl = uvc_find_control(chain, xctrl->id, &mapping); - if (ctrl == NULL) - return -EINVAL; - - return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value); -} - -int uvc_ctrl_set(struct uvc_video_chain *chain, - struct v4l2_ext_control *xctrl) -{ - struct uvc_control *ctrl; - struct uvc_control_mapping *mapping; - s32 value; - u32 step; - s32 min; - s32 max; - int ret; - - ctrl = uvc_find_control(chain, xctrl->id, &mapping); - if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) == 0) - return -EINVAL; - - /* Clamp out of range values. */ - switch (mapping->v4l2_type) { - case V4L2_CTRL_TYPE_INTEGER: - if (!ctrl->cached) { - ret = uvc_ctrl_populate_cache(chain, ctrl); - if (ret < 0) - return ret; - } - - min = mapping->get(mapping, UVC_GET_MIN, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN)); - max = mapping->get(mapping, UVC_GET_MAX, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX)); - step = mapping->get(mapping, UVC_GET_RES, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); - if (step == 0) - step = 1; - - xctrl->value = min + (xctrl->value - min + step/2) / step * step; - xctrl->value = clamp(xctrl->value, min, max); - value = xctrl->value; - break; - - case V4L2_CTRL_TYPE_BOOLEAN: - xctrl->value = clamp(xctrl->value, 0, 1); - value = xctrl->value; - break; - - case V4L2_CTRL_TYPE_MENU: - if (xctrl->value < 0 || xctrl->value >= mapping->menu_count) - return -ERANGE; - value = mapping->menu_info[xctrl->value].value; - - /* Valid menu indices are reported by the GET_RES request for - * UVC controls that support it. - */ - if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK && - (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) { - if (!ctrl->cached) { - ret = uvc_ctrl_populate_cache(chain, ctrl); - if (ret < 0) - return ret; - } - - step = mapping->get(mapping, UVC_GET_RES, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); - if (!(step & value)) - return -ERANGE; - } - - break; - - default: - value = xctrl->value; - break; - } - - /* If the mapping doesn't span the whole UVC control, the current value - * needs to be loaded from the device to perform the read-modify-write - * operation. - */ - if (!ctrl->loaded && (ctrl->info.size * 8) != mapping->size) { - if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) { - memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), - 0, ctrl->info.size); - } else { - ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, - ctrl->entity->id, chain->dev->intfnum, - ctrl->info.selector, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), - ctrl->info.size); - if (ret < 0) - return ret; - } - - ctrl->loaded = 1; - } - - /* Backup the current value in case we need to rollback later. */ - if (!ctrl->dirty) { - memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), - ctrl->info.size); - } - - mapping->set(mapping, value, - uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); - - ctrl->dirty = 1; - ctrl->modified = 1; - return 0; -} - -/* -------------------------------------------------------------------------- - * Dynamic controls - */ - -static void uvc_ctrl_fixup_xu_info(struct uvc_device *dev, - const struct uvc_control *ctrl, struct uvc_control_info *info) -{ - struct uvc_ctrl_fixup { - struct usb_device_id id; - u8 entity; - u8 selector; - u8 flags; - }; - - static const struct uvc_ctrl_fixup fixups[] = { - { { USB_DEVICE(0x046d, 0x08c2) }, 9, 1, - UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX | - UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR | - UVC_CTRL_FLAG_AUTO_UPDATE }, - { { USB_DEVICE(0x046d, 0x08cc) }, 9, 1, - UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX | - UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR | - UVC_CTRL_FLAG_AUTO_UPDATE }, - { { USB_DEVICE(0x046d, 0x0994) }, 9, 1, - UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX | - UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR | - UVC_CTRL_FLAG_AUTO_UPDATE }, - }; - - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(fixups); ++i) { - if (!usb_match_one_id(dev->intf, &fixups[i].id)) - continue; - - if (fixups[i].entity == ctrl->entity->id && - fixups[i].selector == info->selector) { - info->flags = fixups[i].flags; - return; - } - } -} - -/* - * Query control information (size and flags) for XU controls. - */ -static int uvc_ctrl_fill_xu_info(struct uvc_device *dev, - const struct uvc_control *ctrl, struct uvc_control_info *info) -{ - u8 *data; - int ret; - - data = kmalloc(2, GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - memcpy(info->entity, ctrl->entity->extension.guidExtensionCode, - sizeof(info->entity)); - info->index = ctrl->index; - info->selector = ctrl->index + 1; - - /* Query and verify the control length (GET_LEN) */ - ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id, dev->intfnum, - info->selector, data, 2); - if (ret < 0) { - uvc_trace(UVC_TRACE_CONTROL, - "GET_LEN failed on control %pUl/%u (%d).\n", - info->entity, info->selector, ret); - goto done; - } - - info->size = le16_to_cpup((__le16 *)data); - - /* Query the control information (GET_INFO) */ - ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, dev->intfnum, - info->selector, data, 1); - if (ret < 0) { - uvc_trace(UVC_TRACE_CONTROL, - "GET_INFO failed on control %pUl/%u (%d).\n", - info->entity, info->selector, ret); - goto done; - } - - info->flags = UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX - | UVC_CTRL_FLAG_GET_RES | UVC_CTRL_FLAG_GET_DEF - | (data[0] & UVC_CONTROL_CAP_GET ? - UVC_CTRL_FLAG_GET_CUR : 0) - | (data[0] & UVC_CONTROL_CAP_SET ? - UVC_CTRL_FLAG_SET_CUR : 0) - | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ? - UVC_CTRL_FLAG_AUTO_UPDATE : 0); - - uvc_ctrl_fixup_xu_info(dev, ctrl, info); - - uvc_trace(UVC_TRACE_CONTROL, "XU control %pUl/%u queried: len %u, " - "flags { get %u set %u auto %u }.\n", - info->entity, info->selector, info->size, - (info->flags & UVC_CTRL_FLAG_GET_CUR) ? 1 : 0, - (info->flags & UVC_CTRL_FLAG_SET_CUR) ? 1 : 0, - (info->flags & UVC_CTRL_FLAG_AUTO_UPDATE) ? 1 : 0); - -done: - kfree(data); - return ret; -} - -static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl, - const struct uvc_control_info *info); - -static int uvc_ctrl_init_xu_ctrl(struct uvc_device *dev, - struct uvc_control *ctrl) -{ - struct uvc_control_info info; - int ret; - - if (ctrl->initialized) - return 0; - - ret = uvc_ctrl_fill_xu_info(dev, ctrl, &info); - if (ret < 0) - return ret; - - ret = uvc_ctrl_add_info(dev, ctrl, &info); - if (ret < 0) - uvc_trace(UVC_TRACE_CONTROL, "Failed to initialize control " - "%pUl/%u on device %s entity %u\n", info.entity, - info.selector, dev->udev->devpath, ctrl->entity->id); - - return ret; -} - -int uvc_xu_ctrl_query(struct uvc_video_chain *chain, - struct uvc_xu_control_query *xqry) -{ - struct uvc_entity *entity; - struct uvc_control *ctrl; - unsigned int i, found = 0; - __u32 reqflags; - __u16 size; - __u8 *data = NULL; - int ret; - - /* Find the extension unit. */ - list_for_each_entry(entity, &chain->entities, chain) { - if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT && - entity->id == xqry->unit) - break; - } - - if (entity->id != xqry->unit) { - uvc_trace(UVC_TRACE_CONTROL, "Extension unit %u not found.\n", - xqry->unit); - return -ENOENT; - } - - /* Find the control and perform delayed initialization if needed. */ - for (i = 0; i < entity->ncontrols; ++i) { - ctrl = &entity->controls[i]; - if (ctrl->index == xqry->selector - 1) { - found = 1; - break; - } - } - - if (!found) { - uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u not found.\n", - entity->extension.guidExtensionCode, xqry->selector); - return -ENOENT; - } - - if (mutex_lock_interruptible(&chain->ctrl_mutex)) - return -ERESTARTSYS; - - ret = uvc_ctrl_init_xu_ctrl(chain->dev, ctrl); - if (ret < 0) { - ret = -ENOENT; - goto done; - } - - /* Validate the required buffer size and flags for the request */ - reqflags = 0; - size = ctrl->info.size; - - switch (xqry->query) { - case UVC_GET_CUR: - reqflags = UVC_CTRL_FLAG_GET_CUR; - break; - case UVC_GET_MIN: - reqflags = UVC_CTRL_FLAG_GET_MIN; - break; - case UVC_GET_MAX: - reqflags = UVC_CTRL_FLAG_GET_MAX; - break; - case UVC_GET_DEF: - reqflags = UVC_CTRL_FLAG_GET_DEF; - break; - case UVC_GET_RES: - reqflags = UVC_CTRL_FLAG_GET_RES; - break; - case UVC_SET_CUR: - reqflags = UVC_CTRL_FLAG_SET_CUR; - break; - case UVC_GET_LEN: - size = 2; - break; - case UVC_GET_INFO: - size = 1; - break; - default: - ret = -EINVAL; - goto done; - } - - if (size != xqry->size) { - ret = -ENOBUFS; - goto done; - } - - if (reqflags && !(ctrl->info.flags & reqflags)) { - ret = -EBADRQC; - goto done; - } - - data = kmalloc(size, GFP_KERNEL); - if (data == NULL) { - ret = -ENOMEM; - goto done; - } - - if (xqry->query == UVC_SET_CUR && - copy_from_user(data, xqry->data, size)) { - ret = -EFAULT; - goto done; - } - - ret = uvc_query_ctrl(chain->dev, xqry->query, xqry->unit, - chain->dev->intfnum, xqry->selector, data, size); - if (ret < 0) - goto done; - - if (xqry->query != UVC_SET_CUR && - copy_to_user(xqry->data, data, size)) - ret = -EFAULT; -done: - kfree(data); - mutex_unlock(&chain->ctrl_mutex); - return ret; -} - -/* -------------------------------------------------------------------------- - * Suspend/resume - */ - -/* - * Restore control values after resume, skipping controls that haven't been - * changed. - * - * TODO - * - Don't restore modified controls that are back to their default value. - * - Handle restore order (Auto-Exposure Mode should be restored before - * Exposure Time). - */ -int uvc_ctrl_resume_device(struct uvc_device *dev) -{ - struct uvc_control *ctrl; - struct uvc_entity *entity; - unsigned int i; - int ret; - - /* Walk the entities list and restore controls when possible. */ - list_for_each_entry(entity, &dev->entities, list) { - - for (i = 0; i < entity->ncontrols; ++i) { - ctrl = &entity->controls[i]; - - if (!ctrl->initialized || !ctrl->modified || - (ctrl->info.flags & UVC_CTRL_FLAG_RESTORE) == 0) - continue; - - printk(KERN_INFO "restoring control %pUl/%u/%u\n", - ctrl->info.entity, ctrl->info.index, - ctrl->info.selector); - ctrl->dirty = 1; - } - - ret = uvc_ctrl_commit_entity(dev, entity, 0); - if (ret < 0) - return ret; - } - - return 0; -} - -/* -------------------------------------------------------------------------- - * Control and mapping handling - */ - -/* - * Add control information to a given control. - */ -static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl, - const struct uvc_control_info *info) -{ - int ret = 0; - - memcpy(&ctrl->info, info, sizeof(*info)); - INIT_LIST_HEAD(&ctrl->info.mappings); - - /* Allocate an array to save control values (cur, def, max, etc.) */ - ctrl->uvc_data = kzalloc(ctrl->info.size * UVC_CTRL_DATA_LAST + 1, - GFP_KERNEL); - if (ctrl->uvc_data == NULL) { - ret = -ENOMEM; - goto done; - } - - ctrl->initialized = 1; - - uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s " - "entity %u\n", ctrl->info.entity, ctrl->info.selector, - dev->udev->devpath, ctrl->entity->id); - -done: - if (ret < 0) - kfree(ctrl->uvc_data); - return ret; -} - -/* - * Add a control mapping to a given control. - */ -static int __uvc_ctrl_add_mapping(struct uvc_device *dev, - struct uvc_control *ctrl, const struct uvc_control_mapping *mapping) -{ - struct uvc_control_mapping *map; - unsigned int size; - - /* Most mappings come from static kernel data and need to be duplicated. - * Mappings that come from userspace will be unnecessarily duplicated, - * this could be optimized. - */ - map = kmemdup(mapping, sizeof(*mapping), GFP_KERNEL); - if (map == NULL) - return -ENOMEM; - - INIT_LIST_HEAD(&map->ev_subs); - - size = sizeof(*mapping->menu_info) * mapping->menu_count; - map->menu_info = kmemdup(mapping->menu_info, size, GFP_KERNEL); - if (map->menu_info == NULL) { - kfree(map); - return -ENOMEM; - } - - if (map->get == NULL) - map->get = uvc_get_le_value; - if (map->set == NULL) - map->set = uvc_set_le_value; - - list_add_tail(&map->list, &ctrl->info.mappings); - uvc_trace(UVC_TRACE_CONTROL, - "Adding mapping '%s' to control %pUl/%u.\n", - map->name, ctrl->info.entity, ctrl->info.selector); - - return 0; -} - -int uvc_ctrl_add_mapping(struct uvc_video_chain *chain, - const struct uvc_control_mapping *mapping) -{ - struct uvc_device *dev = chain->dev; - struct uvc_control_mapping *map; - struct uvc_entity *entity; - struct uvc_control *ctrl; - int found = 0; - int ret; - - if (mapping->id & ~V4L2_CTRL_ID_MASK) { - uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', control " - "id 0x%08x is invalid.\n", mapping->name, - mapping->id); - return -EINVAL; - } - - /* Search for the matching (GUID/CS) control on the current chain */ - list_for_each_entry(entity, &chain->entities, chain) { - unsigned int i; - - if (UVC_ENTITY_TYPE(entity) != UVC_VC_EXTENSION_UNIT || - !uvc_entity_match_guid(entity, mapping->entity)) - continue; - - for (i = 0; i < entity->ncontrols; ++i) { - ctrl = &entity->controls[i]; - if (ctrl->index == mapping->selector - 1) { - found = 1; - break; - } - } - - if (found) - break; - } - if (!found) - return -ENOENT; - - if (mutex_lock_interruptible(&chain->ctrl_mutex)) - return -ERESTARTSYS; - - /* Perform delayed initialization of XU controls */ - ret = uvc_ctrl_init_xu_ctrl(dev, ctrl); - if (ret < 0) { - ret = -ENOENT; - goto done; - } - - list_for_each_entry(map, &ctrl->info.mappings, list) { - if (mapping->id == map->id) { - uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', " - "control id 0x%08x already exists.\n", - mapping->name, mapping->id); - ret = -EEXIST; - goto done; - } - } - - /* Prevent excess memory consumption */ - if (atomic_inc_return(&dev->nmappings) > UVC_MAX_CONTROL_MAPPINGS) { - atomic_dec(&dev->nmappings); - uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', maximum " - "mappings count (%u) exceeded.\n", mapping->name, - UVC_MAX_CONTROL_MAPPINGS); - ret = -ENOMEM; - goto done; - } - - ret = __uvc_ctrl_add_mapping(dev, ctrl, mapping); - if (ret < 0) - atomic_dec(&dev->nmappings); - -done: - mutex_unlock(&chain->ctrl_mutex); - return ret; -} - -/* - * Prune an entity of its bogus controls using a blacklist. Bogus controls - * are currently the ones that crash the camera or unconditionally return an - * error when queried. - */ -static void uvc_ctrl_prune_entity(struct uvc_device *dev, - struct uvc_entity *entity) -{ - struct uvc_ctrl_blacklist { - struct usb_device_id id; - u8 index; - }; - - static const struct uvc_ctrl_blacklist processing_blacklist[] = { - { { USB_DEVICE(0x13d3, 0x509b) }, 9 }, /* Gain */ - { { USB_DEVICE(0x1c4f, 0x3000) }, 6 }, /* WB Temperature */ - { { USB_DEVICE(0x5986, 0x0241) }, 2 }, /* Hue */ - }; - static const struct uvc_ctrl_blacklist camera_blacklist[] = { - { { USB_DEVICE(0x06f8, 0x3005) }, 9 }, /* Zoom, Absolute */ - }; - - const struct uvc_ctrl_blacklist *blacklist; - unsigned int size; - unsigned int count; - unsigned int i; - u8 *controls; - - switch (UVC_ENTITY_TYPE(entity)) { - case UVC_VC_PROCESSING_UNIT: - blacklist = processing_blacklist; - count = ARRAY_SIZE(processing_blacklist); - controls = entity->processing.bmControls; - size = entity->processing.bControlSize; - break; - - case UVC_ITT_CAMERA: - blacklist = camera_blacklist; - count = ARRAY_SIZE(camera_blacklist); - controls = entity->camera.bmControls; - size = entity->camera.bControlSize; - break; - - default: - return; - } - - for (i = 0; i < count; ++i) { - if (!usb_match_one_id(dev->intf, &blacklist[i].id)) - continue; - - if (blacklist[i].index >= 8 * size || - !uvc_test_bit(controls, blacklist[i].index)) - continue; - - uvc_trace(UVC_TRACE_CONTROL, "%u/%u control is black listed, " - "removing it.\n", entity->id, blacklist[i].index); - - uvc_clear_bit(controls, blacklist[i].index); - } -} - -/* - * Add control information and hardcoded stock control mappings to the given - * device. - */ -static void uvc_ctrl_init_ctrl(struct uvc_device *dev, struct uvc_control *ctrl) -{ - const struct uvc_control_info *info = uvc_ctrls; - const struct uvc_control_info *iend = info + ARRAY_SIZE(uvc_ctrls); - const struct uvc_control_mapping *mapping = uvc_ctrl_mappings; - const struct uvc_control_mapping *mend = - mapping + ARRAY_SIZE(uvc_ctrl_mappings); - - /* XU controls initialization requires querying the device for control - * information. As some buggy UVC devices will crash when queried - * repeatedly in a tight loop, delay XU controls initialization until - * first use. - */ - if (UVC_ENTITY_TYPE(ctrl->entity) == UVC_VC_EXTENSION_UNIT) - return; - - for (; info < iend; ++info) { - if (uvc_entity_match_guid(ctrl->entity, info->entity) && - ctrl->index == info->index) { - uvc_ctrl_add_info(dev, ctrl, info); - break; - } - } - - if (!ctrl->initialized) - return; - - for (; mapping < mend; ++mapping) { - if (uvc_entity_match_guid(ctrl->entity, mapping->entity) && - ctrl->info.selector == mapping->selector) - __uvc_ctrl_add_mapping(dev, ctrl, mapping); - } -} - -/* - * Initialize device controls. - */ -int uvc_ctrl_init_device(struct uvc_device *dev) -{ - struct uvc_entity *entity; - unsigned int i; - - /* Walk the entities list and instantiate controls */ - list_for_each_entry(entity, &dev->entities, list) { - struct uvc_control *ctrl; - unsigned int bControlSize = 0, ncontrols; - __u8 *bmControls = NULL; - - if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT) { - bmControls = entity->extension.bmControls; - bControlSize = entity->extension.bControlSize; - } else if (UVC_ENTITY_TYPE(entity) == UVC_VC_PROCESSING_UNIT) { - bmControls = entity->processing.bmControls; - bControlSize = entity->processing.bControlSize; - } else if (UVC_ENTITY_TYPE(entity) == UVC_ITT_CAMERA) { - bmControls = entity->camera.bmControls; - bControlSize = entity->camera.bControlSize; - } - - /* Remove bogus/blacklisted controls */ - uvc_ctrl_prune_entity(dev, entity); - - /* Count supported controls and allocate the controls array */ - ncontrols = memweight(bmControls, bControlSize); - if (ncontrols == 0) - continue; - - entity->controls = kcalloc(ncontrols, sizeof(*ctrl), - GFP_KERNEL); - if (entity->controls == NULL) - return -ENOMEM; - entity->ncontrols = ncontrols; - - /* Initialize all supported controls */ - ctrl = entity->controls; - for (i = 0; i < bControlSize * 8; ++i) { - if (uvc_test_bit(bmControls, i) == 0) - continue; - - ctrl->entity = entity; - ctrl->index = i; - - uvc_ctrl_init_ctrl(dev, ctrl); - ctrl++; - } - } - - return 0; -} - -/* - * Cleanup device controls. - */ -static void uvc_ctrl_cleanup_mappings(struct uvc_device *dev, - struct uvc_control *ctrl) -{ - struct uvc_control_mapping *mapping, *nm; - - list_for_each_entry_safe(mapping, nm, &ctrl->info.mappings, list) { - list_del(&mapping->list); - kfree(mapping->menu_info); - kfree(mapping); - } -} - -void uvc_ctrl_cleanup_device(struct uvc_device *dev) -{ - struct uvc_entity *entity; - unsigned int i; - - /* Free controls and control mappings for all entities. */ - list_for_each_entry(entity, &dev->entities, list) { - for (i = 0; i < entity->ncontrols; ++i) { - struct uvc_control *ctrl = &entity->controls[i]; - - if (!ctrl->initialized) - continue; - - uvc_ctrl_cleanup_mappings(dev, ctrl); - kfree(ctrl->uvc_data); - } - - kfree(entity->controls); - } -} diff --git a/drivers/media/video/uvc/uvc_debugfs.c b/drivers/media/video/uvc/uvc_debugfs.c deleted file mode 100644 index 14561a5abb79..000000000000 --- a/drivers/media/video/uvc/uvc_debugfs.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * uvc_debugfs.c -- USB Video Class driver - Debugging support - * - * Copyright (C) 2011 - * Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * 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. - * - */ - -#include <linux/module.h> -#include <linux/debugfs.h> -#include <linux/slab.h> -#include <linux/usb.h> - -#include "uvcvideo.h" - -/* ----------------------------------------------------------------------------- - * Statistics - */ - -#define UVC_DEBUGFS_BUF_SIZE 1024 - -struct uvc_debugfs_buffer { - size_t count; - char data[UVC_DEBUGFS_BUF_SIZE]; -}; - -static int uvc_debugfs_stats_open(struct inode *inode, struct file *file) -{ - struct uvc_streaming *stream = inode->i_private; - struct uvc_debugfs_buffer *buf; - - buf = kmalloc(sizeof(*buf), GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - buf->count = uvc_video_stats_dump(stream, buf->data, sizeof(buf->data)); - - file->private_data = buf; - return 0; -} - -static ssize_t uvc_debugfs_stats_read(struct file *file, char __user *user_buf, - size_t nbytes, loff_t *ppos) -{ - struct uvc_debugfs_buffer *buf = file->private_data; - - return simple_read_from_buffer(user_buf, nbytes, ppos, buf->data, - buf->count); -} - -static int uvc_debugfs_stats_release(struct inode *inode, struct file *file) -{ - kfree(file->private_data); - file->private_data = NULL; - - return 0; -} - -static const struct file_operations uvc_debugfs_stats_fops = { - .owner = THIS_MODULE, - .open = uvc_debugfs_stats_open, - .llseek = no_llseek, - .read = uvc_debugfs_stats_read, - .release = uvc_debugfs_stats_release, -}; - -/* ----------------------------------------------------------------------------- - * Global and stream initialization/cleanup - */ - -static struct dentry *uvc_debugfs_root_dir; - -int uvc_debugfs_init_stream(struct uvc_streaming *stream) -{ - struct usb_device *udev = stream->dev->udev; - struct dentry *dent; - char dir_name[32]; - - if (uvc_debugfs_root_dir == NULL) - return -ENODEV; - - sprintf(dir_name, "%u-%u", udev->bus->busnum, udev->devnum); - - dent = debugfs_create_dir(dir_name, uvc_debugfs_root_dir); - if (IS_ERR_OR_NULL(dent)) { - uvc_printk(KERN_INFO, "Unable to create debugfs %s " - "directory.\n", dir_name); - return -ENODEV; - } - - stream->debugfs_dir = dent; - - dent = debugfs_create_file("stats", 0444, stream->debugfs_dir, - stream, &uvc_debugfs_stats_fops); - if (IS_ERR_OR_NULL(dent)) { - uvc_printk(KERN_INFO, "Unable to create debugfs stats file.\n"); - uvc_debugfs_cleanup_stream(stream); - return -ENODEV; - } - - return 0; -} - -void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream) -{ - if (stream->debugfs_dir == NULL) - return; - - debugfs_remove_recursive(stream->debugfs_dir); - stream->debugfs_dir = NULL; -} - -int uvc_debugfs_init(void) -{ - struct dentry *dir; - - dir = debugfs_create_dir("uvcvideo", usb_debug_root); - if (IS_ERR_OR_NULL(dir)) { - uvc_printk(KERN_INFO, "Unable to create debugfs directory\n"); - return -ENODATA; - } - - uvc_debugfs_root_dir = dir; - return 0; -} - -void uvc_debugfs_cleanup(void) -{ - if (uvc_debugfs_root_dir != NULL) - debugfs_remove_recursive(uvc_debugfs_root_dir); -} diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c deleted file mode 100644 index 45d7aa162d9d..000000000000 --- a/drivers/media/video/uvc/uvc_driver.c +++ /dev/null @@ -1,2472 +0,0 @@ -/* - * uvc_driver.c -- USB Video Class driver - * - * Copyright (C) 2005-2010 - * Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * 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 driver aims to support video input and ouput devices compliant with the - * 'USB Video Class' specification. - * - * The driver doesn't support the deprecated v4l1 interface. It implements the - * mmap capture method only, and doesn't do any image format conversion in - * software. If your user-space application doesn't support YUYV or MJPEG, fix - * it :-). Please note that the MJPEG data have been stripped from their - * Huffman tables (DHT marker), you will need to add it back if your JPEG - * codec can't handle MJPEG data. - */ - -#include <linux/atomic.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/videodev2.h> -#include <linux/vmalloc.h> -#include <linux/wait.h> -#include <linux/version.h> -#include <asm/unaligned.h> - -#include <media/v4l2-common.h> - -#include "uvcvideo.h" - -#define DRIVER_AUTHOR "Laurent Pinchart " \ - "<laurent.pinchart@ideasonboard.com>" -#define DRIVER_DESC "USB Video Class driver" - -unsigned int uvc_clock_param = CLOCK_MONOTONIC; -unsigned int uvc_no_drop_param; -static unsigned int uvc_quirks_param = -1; -unsigned int uvc_trace_param; -unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT; - -/* ------------------------------------------------------------------------ - * Video formats - */ - -static struct uvc_format_desc uvc_fmts[] = { - { - .name = "YUV 4:2:2 (YUYV)", - .guid = UVC_GUID_FORMAT_YUY2, - .fcc = V4L2_PIX_FMT_YUYV, - }, - { - .name = "YUV 4:2:2 (YUYV)", - .guid = UVC_GUID_FORMAT_YUY2_ISIGHT, - .fcc = V4L2_PIX_FMT_YUYV, - }, - { - .name = "YUV 4:2:0 (NV12)", - .guid = UVC_GUID_FORMAT_NV12, - .fcc = V4L2_PIX_FMT_NV12, - }, - { - .name = "MJPEG", - .guid = UVC_GUID_FORMAT_MJPEG, - .fcc = V4L2_PIX_FMT_MJPEG, - }, - { - .name = "YVU 4:2:0 (YV12)", - .guid = UVC_GUID_FORMAT_YV12, - .fcc = V4L2_PIX_FMT_YVU420, - }, - { - .name = "YUV 4:2:0 (I420)", - .guid = UVC_GUID_FORMAT_I420, - .fcc = V4L2_PIX_FMT_YUV420, - }, - { - .name = "YUV 4:2:0 (M420)", - .guid = UVC_GUID_FORMAT_M420, - .fcc = V4L2_PIX_FMT_M420, - }, - { - .name = "YUV 4:2:2 (UYVY)", - .guid = UVC_GUID_FORMAT_UYVY, - .fcc = V4L2_PIX_FMT_UYVY, - }, - { - .name = "Greyscale 8-bit (Y800)", - .guid = UVC_GUID_FORMAT_Y800, - .fcc = V4L2_PIX_FMT_GREY, - }, - { - .name = "Greyscale 8-bit (Y8 )", - .guid = UVC_GUID_FORMAT_Y8, - .fcc = V4L2_PIX_FMT_GREY, - }, - { - .name = "Greyscale 10-bit (Y10 )", - .guid = UVC_GUID_FORMAT_Y10, - .fcc = V4L2_PIX_FMT_Y10, - }, - { - .name = "Greyscale 12-bit (Y12 )", - .guid = UVC_GUID_FORMAT_Y12, - .fcc = V4L2_PIX_FMT_Y12, - }, - { - .name = "Greyscale 16-bit (Y16 )", - .guid = UVC_GUID_FORMAT_Y16, - .fcc = V4L2_PIX_FMT_Y16, - }, - { - .name = "RGB Bayer", - .guid = UVC_GUID_FORMAT_BY8, - .fcc = V4L2_PIX_FMT_SBGGR8, - }, - { - .name = "RGB565", - .guid = UVC_GUID_FORMAT_RGBP, - .fcc = V4L2_PIX_FMT_RGB565, - }, - { - .name = "H.264", - .guid = UVC_GUID_FORMAT_H264, - .fcc = V4L2_PIX_FMT_H264, - }, -}; - -/* ------------------------------------------------------------------------ - * Utility functions - */ - -struct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts, - __u8 epaddr) -{ - struct usb_host_endpoint *ep; - unsigned int i; - - for (i = 0; i < alts->desc.bNumEndpoints; ++i) { - ep = &alts->endpoint[i]; - if (ep->desc.bEndpointAddress == epaddr) - return ep; - } - - return NULL; -} - -static struct uvc_format_desc *uvc_format_by_guid(const __u8 guid[16]) -{ - unsigned int len = ARRAY_SIZE(uvc_fmts); - unsigned int i; - - for (i = 0; i < len; ++i) { - if (memcmp(guid, uvc_fmts[i].guid, 16) == 0) - return &uvc_fmts[i]; - } - - return NULL; -} - -static __u32 uvc_colorspace(const __u8 primaries) -{ - static const __u8 colorprimaries[] = { - 0, - V4L2_COLORSPACE_SRGB, - V4L2_COLORSPACE_470_SYSTEM_M, - V4L2_COLORSPACE_470_SYSTEM_BG, - V4L2_COLORSPACE_SMPTE170M, - V4L2_COLORSPACE_SMPTE240M, - }; - - if (primaries < ARRAY_SIZE(colorprimaries)) - return colorprimaries[primaries]; - - return 0; -} - -/* Simplify a fraction using a simple continued fraction decomposition. The - * idea here is to convert fractions such as 333333/10000000 to 1/30 using - * 32 bit arithmetic only. The algorithm is not perfect and relies upon two - * arbitrary parameters to remove non-significative terms from the simple - * continued fraction decomposition. Using 8 and 333 for n_terms and threshold - * respectively seems to give nice results. - */ -void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator, - unsigned int n_terms, unsigned int threshold) -{ - uint32_t *an; - uint32_t x, y, r; - unsigned int i, n; - - an = kmalloc(n_terms * sizeof *an, GFP_KERNEL); - if (an == NULL) - return; - - /* Convert the fraction to a simple continued fraction. See - * http://mathforum.org/dr.math/faq/faq.fractions.html - * Stop if the current term is bigger than or equal to the given - * threshold. - */ - x = *numerator; - y = *denominator; - - for (n = 0; n < n_terms && y != 0; ++n) { - an[n] = x / y; - if (an[n] >= threshold) { - if (n < 2) - n++; - break; - } - - r = x - an[n] * y; - x = y; - y = r; - } - - /* Expand the simple continued fraction back to an integer fraction. */ - x = 0; - y = 1; - - for (i = n; i > 0; --i) { - r = y; - y = an[i-1] * y + x; - x = r; - } - - *numerator = y; - *denominator = x; - kfree(an); -} - -/* Convert a fraction to a frame interval in 100ns multiples. The idea here is - * to compute numerator / denominator * 10000000 using 32 bit fixed point - * arithmetic only. - */ -uint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator) -{ - uint32_t multiplier; - - /* Saturate the result if the operation would overflow. */ - if (denominator == 0 || - numerator/denominator >= ((uint32_t)-1)/10000000) - return (uint32_t)-1; - - /* Divide both the denominator and the multiplier by two until - * numerator * multiplier doesn't overflow. If anyone knows a better - * algorithm please let me know. - */ - multiplier = 10000000; - while (numerator > ((uint32_t)-1)/multiplier) { - multiplier /= 2; - denominator /= 2; - } - - return denominator ? numerator * multiplier / denominator : 0; -} - -/* ------------------------------------------------------------------------ - * Terminal and unit management - */ - -struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id) -{ - struct uvc_entity *entity; - - list_for_each_entry(entity, &dev->entities, list) { - if (entity->id == id) - return entity; - } - - return NULL; -} - -static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev, - int id, struct uvc_entity *entity) -{ - unsigned int i; - - if (entity == NULL) - entity = list_entry(&dev->entities, struct uvc_entity, list); - - list_for_each_entry_continue(entity, &dev->entities, list) { - for (i = 0; i < entity->bNrInPins; ++i) - if (entity->baSourceID[i] == id) - return entity; - } - - return NULL; -} - -static struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id) -{ - struct uvc_streaming *stream; - - list_for_each_entry(stream, &dev->streams, list) { - if (stream->header.bTerminalLink == id) - return stream; - } - - return NULL; -} - -/* ------------------------------------------------------------------------ - * Descriptors parsing - */ - -static int uvc_parse_format(struct uvc_device *dev, - struct uvc_streaming *streaming, struct uvc_format *format, - __u32 **intervals, unsigned char *buffer, int buflen) -{ - struct usb_interface *intf = streaming->intf; - struct usb_host_interface *alts = intf->cur_altsetting; - struct uvc_format_desc *fmtdesc; - struct uvc_frame *frame; - const unsigned char *start = buffer; - unsigned int interval; - unsigned int i, n; - __u8 ftype; - - format->type = buffer[2]; - format->index = buffer[3]; - - switch (buffer[2]) { - case UVC_VS_FORMAT_UNCOMPRESSED: - case UVC_VS_FORMAT_FRAME_BASED: - n = buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED ? 27 : 28; - if (buflen < n) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " - "interface %d FORMAT error\n", - dev->udev->devnum, - alts->desc.bInterfaceNumber); - return -EINVAL; - } - - /* Find the format descriptor from its GUID. */ - fmtdesc = uvc_format_by_guid(&buffer[5]); - - if (fmtdesc != NULL) { - strlcpy(format->name, fmtdesc->name, - sizeof format->name); - format->fcc = fmtdesc->fcc; - } else { - uvc_printk(KERN_INFO, "Unknown video format %pUl\n", - &buffer[5]); - snprintf(format->name, sizeof(format->name), "%pUl\n", - &buffer[5]); - format->fcc = 0; - } - - format->bpp = buffer[21]; - if (buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED) { - ftype = UVC_VS_FRAME_UNCOMPRESSED; - } else { - ftype = UVC_VS_FRAME_FRAME_BASED; - if (buffer[27]) - format->flags = UVC_FMT_FLAG_COMPRESSED; - } - break; - - case UVC_VS_FORMAT_MJPEG: - if (buflen < 11) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " - "interface %d FORMAT error\n", - dev->udev->devnum, - alts->desc.bInterfaceNumber); - return -EINVAL; - } - - strlcpy(format->name, "MJPEG", sizeof format->name); - format->fcc = V4L2_PIX_FMT_MJPEG; - format->flags = UVC_FMT_FLAG_COMPRESSED; - format->bpp = 0; - ftype = UVC_VS_FRAME_MJPEG; - break; - - case UVC_VS_FORMAT_DV: - if (buflen < 9) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " - "interface %d FORMAT error\n", - dev->udev->devnum, - alts->desc.bInterfaceNumber); - return -EINVAL; - } - - switch (buffer[8] & 0x7f) { - case 0: - strlcpy(format->name, "SD-DV", sizeof format->name); - break; - case 1: - strlcpy(format->name, "SDL-DV", sizeof format->name); - break; - case 2: - strlcpy(format->name, "HD-DV", sizeof format->name); - break; - default: - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " - "interface %d: unknown DV format %u\n", - dev->udev->devnum, - alts->desc.bInterfaceNumber, buffer[8]); - return -EINVAL; - } - - strlcat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz", - sizeof format->name); - - format->fcc = V4L2_PIX_FMT_DV; - format->flags = UVC_FMT_FLAG_COMPRESSED | UVC_FMT_FLAG_STREAM; - format->bpp = 0; - ftype = 0; - - /* Create a dummy frame descriptor. */ - frame = &format->frame[0]; - memset(&format->frame[0], 0, sizeof format->frame[0]); - frame->bFrameIntervalType = 1; - frame->dwDefaultFrameInterval = 1; - frame->dwFrameInterval = *intervals; - *(*intervals)++ = 1; - format->nframes = 1; - break; - - case UVC_VS_FORMAT_MPEG2TS: - case UVC_VS_FORMAT_STREAM_BASED: - /* Not supported yet. */ - default: - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " - "interface %d unsupported format %u\n", - dev->udev->devnum, alts->desc.bInterfaceNumber, - buffer[2]); - return -EINVAL; - } - - uvc_trace(UVC_TRACE_DESCR, "Found format %s.\n", format->name); - - buflen -= buffer[0]; - buffer += buffer[0]; - - /* Parse the frame descriptors. Only uncompressed, MJPEG and frame - * based formats have frame descriptors. - */ - while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && - buffer[2] == ftype) { - frame = &format->frame[format->nframes]; - if (ftype != UVC_VS_FRAME_FRAME_BASED) - n = buflen > 25 ? buffer[25] : 0; - else - n = buflen > 21 ? buffer[21] : 0; - - n = n ? n : 3; - - if (buflen < 26 + 4*n) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " - "interface %d FRAME error\n", dev->udev->devnum, - alts->desc.bInterfaceNumber); - return -EINVAL; - } - - frame->bFrameIndex = buffer[3]; - frame->bmCapabilities = buffer[4]; - frame->wWidth = get_unaligned_le16(&buffer[5]); - frame->wHeight = get_unaligned_le16(&buffer[7]); - frame->dwMinBitRate = get_unaligned_le32(&buffer[9]); - frame->dwMaxBitRate = get_unaligned_le32(&buffer[13]); - if (ftype != UVC_VS_FRAME_FRAME_BASED) { - frame->dwMaxVideoFrameBufferSize = - get_unaligned_le32(&buffer[17]); - frame->dwDefaultFrameInterval = - get_unaligned_le32(&buffer[21]); - frame->bFrameIntervalType = buffer[25]; - } else { - frame->dwMaxVideoFrameBufferSize = 0; - frame->dwDefaultFrameInterval = - get_unaligned_le32(&buffer[17]); - frame->bFrameIntervalType = buffer[21]; - } - frame->dwFrameInterval = *intervals; - - /* Several UVC chipsets screw up dwMaxVideoFrameBufferSize - * completely. Observed behaviours range from setting the - * value to 1.1x the actual frame size to hardwiring the - * 16 low bits to 0. This results in a higher than necessary - * memory usage as well as a wrong image size information. For - * uncompressed formats this can be fixed by computing the - * value from the frame size. - */ - if (!(format->flags & UVC_FMT_FLAG_COMPRESSED)) - frame->dwMaxVideoFrameBufferSize = format->bpp - * frame->wWidth * frame->wHeight / 8; - - /* Some bogus devices report dwMinFrameInterval equal to - * dwMaxFrameInterval and have dwFrameIntervalStep set to - * zero. Setting all null intervals to 1 fixes the problem and - * some other divisions by zero that could happen. - */ - for (i = 0; i < n; ++i) { - interval = get_unaligned_le32(&buffer[26+4*i]); - *(*intervals)++ = interval ? interval : 1; - } - - /* Make sure that the default frame interval stays between - * the boundaries. - */ - n -= frame->bFrameIntervalType ? 1 : 2; - frame->dwDefaultFrameInterval = - min(frame->dwFrameInterval[n], - max(frame->dwFrameInterval[0], - frame->dwDefaultFrameInterval)); - - if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) { - frame->bFrameIntervalType = 1; - frame->dwFrameInterval[0] = - frame->dwDefaultFrameInterval; - } - - uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n", - frame->wWidth, frame->wHeight, - 10000000/frame->dwDefaultFrameInterval, - (100000000/frame->dwDefaultFrameInterval)%10); - - format->nframes++; - buflen -= buffer[0]; - buffer += buffer[0]; - } - - if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && - buffer[2] == UVC_VS_STILL_IMAGE_FRAME) { - buflen -= buffer[0]; - buffer += buffer[0]; - } - - if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && - buffer[2] == UVC_VS_COLORFORMAT) { - if (buflen < 6) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " - "interface %d COLORFORMAT error\n", - dev->udev->devnum, - alts->desc.bInterfaceNumber); - return -EINVAL; - } - - format->colorspace = uvc_colorspace(buffer[3]); - - buflen -= buffer[0]; - buffer += buffer[0]; - } - - return buffer - start; -} - -static int uvc_parse_streaming(struct uvc_device *dev, - struct usb_interface *intf) -{ - struct uvc_streaming *streaming = NULL; - struct uvc_format *format; - struct uvc_frame *frame; - struct usb_host_interface *alts = &intf->altsetting[0]; - unsigned char *_buffer, *buffer = alts->extra; - int _buflen, buflen = alts->extralen; - unsigned int nformats = 0, nframes = 0, nintervals = 0; - unsigned int size, i, n, p; - __u32 *interval; - __u16 psize; - int ret = -EINVAL; - - if (intf->cur_altsetting->desc.bInterfaceSubClass - != UVC_SC_VIDEOSTREAMING) { - uvc_trace(UVC_TRACE_DESCR, "device %d interface %d isn't a " - "video streaming interface\n", dev->udev->devnum, - intf->altsetting[0].desc.bInterfaceNumber); - return -EINVAL; - } - - if (usb_driver_claim_interface(&uvc_driver.driver, intf, dev)) { - uvc_trace(UVC_TRACE_DESCR, "device %d interface %d is already " - "claimed\n", dev->udev->devnum, - intf->altsetting[0].desc.bInterfaceNumber); - return -EINVAL; - } - - streaming = kzalloc(sizeof *streaming, GFP_KERNEL); - if (streaming == NULL) { - usb_driver_release_interface(&uvc_driver.driver, intf); - return -EINVAL; - } - - mutex_init(&streaming->mutex); - streaming->dev = dev; - streaming->intf = usb_get_intf(intf); - streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; - - /* The Pico iMage webcam has its class-specific interface descriptors - * after the endpoint descriptors. - */ - if (buflen == 0) { - for (i = 0; i < alts->desc.bNumEndpoints; ++i) { - struct usb_host_endpoint *ep = &alts->endpoint[i]; - - if (ep->extralen == 0) - continue; - - if (ep->extralen > 2 && - ep->extra[1] == USB_DT_CS_INTERFACE) { - uvc_trace(UVC_TRACE_DESCR, "trying extra data " - "from endpoint %u.\n", i); - buffer = alts->endpoint[i].extra; - buflen = alts->endpoint[i].extralen; - break; - } - } - } - - /* Skip the standard interface descriptors. */ - while (buflen > 2 && buffer[1] != USB_DT_CS_INTERFACE) { - buflen -= buffer[0]; - buffer += buffer[0]; - } - - if (buflen <= 2) { - uvc_trace(UVC_TRACE_DESCR, "no class-specific streaming " - "interface descriptors found.\n"); - goto error; - } - - /* Parse the header descriptor. */ - switch (buffer[2]) { - case UVC_VS_OUTPUT_HEADER: - streaming->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - size = 9; - break; - - case UVC_VS_INPUT_HEADER: - streaming->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - size = 13; - break; - - default: - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " - "%d HEADER descriptor not found.\n", dev->udev->devnum, - alts->desc.bInterfaceNumber); - goto error; - } - - p = buflen >= 4 ? buffer[3] : 0; - n = buflen >= size ? buffer[size-1] : 0; - - if (buflen < size + p*n) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " - "interface %d HEADER descriptor is invalid.\n", - dev->udev->devnum, alts->desc.bInterfaceNumber); - goto error; - } - - streaming->header.bNumFormats = p; - streaming->header.bEndpointAddress = buffer[6]; - if (buffer[2] == UVC_VS_INPUT_HEADER) { - streaming->header.bmInfo = buffer[7]; - streaming->header.bTerminalLink = buffer[8]; - streaming->header.bStillCaptureMethod = buffer[9]; - streaming->header.bTriggerSupport = buffer[10]; - streaming->header.bTriggerUsage = buffer[11]; - } else { - streaming->header.bTerminalLink = buffer[7]; - } - streaming->header.bControlSize = n; - - streaming->header.bmaControls = kmemdup(&buffer[size], p * n, - GFP_KERNEL); - if (streaming->header.bmaControls == NULL) { - ret = -ENOMEM; - goto error; - } - - buflen -= buffer[0]; - buffer += buffer[0]; - - _buffer = buffer; - _buflen = buflen; - - /* Count the format and frame descriptors. */ - while (_buflen > 2 && _buffer[1] == USB_DT_CS_INTERFACE) { - switch (_buffer[2]) { - case UVC_VS_FORMAT_UNCOMPRESSED: - case UVC_VS_FORMAT_MJPEG: - case UVC_VS_FORMAT_FRAME_BASED: - nformats++; - break; - - case UVC_VS_FORMAT_DV: - /* DV format has no frame descriptor. We will create a - * dummy frame descriptor with a dummy frame interval. - */ - nformats++; - nframes++; - nintervals++; - break; - - case UVC_VS_FORMAT_MPEG2TS: - case UVC_VS_FORMAT_STREAM_BASED: - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " - "interface %d FORMAT %u is not supported.\n", - dev->udev->devnum, - alts->desc.bInterfaceNumber, _buffer[2]); - break; - - case UVC_VS_FRAME_UNCOMPRESSED: - case UVC_VS_FRAME_MJPEG: - nframes++; - if (_buflen > 25) - nintervals += _buffer[25] ? _buffer[25] : 3; - break; - - case UVC_VS_FRAME_FRAME_BASED: - nframes++; - if (_buflen > 21) - nintervals += _buffer[21] ? _buffer[21] : 3; - break; - } - - _buflen -= _buffer[0]; - _buffer += _buffer[0]; - } - - if (nformats == 0) { - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " - "%d has no supported formats defined.\n", - dev->udev->devnum, alts->desc.bInterfaceNumber); - goto error; - } - - size = nformats * sizeof *format + nframes * sizeof *frame - + nintervals * sizeof *interval; - format = kzalloc(size, GFP_KERNEL); - if (format == NULL) { - ret = -ENOMEM; - goto error; - } - - frame = (struct uvc_frame *)&format[nformats]; - interval = (__u32 *)&frame[nframes]; - - streaming->format = format; - streaming->nformats = nformats; - - /* Parse the format descriptors. */ - while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE) { - switch (buffer[2]) { - case UVC_VS_FORMAT_UNCOMPRESSED: - case UVC_VS_FORMAT_MJPEG: - case UVC_VS_FORMAT_DV: - case UVC_VS_FORMAT_FRAME_BASED: - format->frame = frame; - ret = uvc_parse_format(dev, streaming, format, - &interval, buffer, buflen); - if (ret < 0) - goto error; - - frame += format->nframes; - format++; - - buflen -= ret; - buffer += ret; - continue; - - default: - break; - } - - buflen -= buffer[0]; - buffer += buffer[0]; - } - - if (buflen) - uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " - "%d has %u bytes of trailing descriptor garbage.\n", - dev->udev->devnum, alts->desc.bInterfaceNumber, buflen); - - /* Parse the alternate settings to find the maximum bandwidth. */ - for (i = 0; i < intf->num_altsetting; ++i) { - struct usb_host_endpoint *ep; - alts = &intf->altsetting[i]; - ep = uvc_find_endpoint(alts, - streaming->header.bEndpointAddress); - if (ep == NULL) - continue; - - psize = le16_to_cpu(ep->desc.wMaxPacketSize); - psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); - if (psize > streaming->maxpsize) - streaming->maxpsize = psize; - } - - list_add_tail(&streaming->list, &dev->streams); - return 0; - -error: - usb_driver_release_interface(&uvc_driver.driver, intf); - usb_put_intf(intf); - kfree(streaming->format); - kfree(streaming->header.bmaControls); - kfree(streaming); - return ret; -} - -static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, - unsigned int num_pads, unsigned int extra_size) -{ - struct uvc_entity *entity; - unsigned int num_inputs; - unsigned int size; - unsigned int i; - - extra_size = ALIGN(extra_size, sizeof(*entity->pads)); - num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1; - size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads - + num_inputs; - entity = kzalloc(size, GFP_KERNEL); - if (entity == NULL) - return NULL; - - entity->id = id; - entity->type = type; - - entity->num_links = 0; - entity->num_pads = num_pads; - entity->pads = ((void *)(entity + 1)) + extra_size; - - for (i = 0; i < num_inputs; ++i) - entity->pads[i].flags = MEDIA_PAD_FL_SINK; - if (!UVC_ENTITY_IS_OTERM(entity)) - entity->pads[num_pads-1].flags = MEDIA_PAD_FL_SOURCE; - - entity->bNrInPins = num_inputs; - entity->baSourceID = (__u8 *)(&entity->pads[num_pads]); - - return entity; -} - -/* Parse vendor-specific extensions. */ -static int uvc_parse_vendor_control(struct uvc_device *dev, - const unsigned char *buffer, int buflen) -{ - struct usb_device *udev = dev->udev; - struct usb_host_interface *alts = dev->intf->cur_altsetting; - struct uvc_entity *unit; - unsigned int n, p; - int handled = 0; - - switch (le16_to_cpu(dev->udev->descriptor.idVendor)) { - case 0x046d: /* Logitech */ - if (buffer[1] != 0x41 || buffer[2] != 0x01) - break; - - /* Logitech implements several vendor specific functions - * through vendor specific extension units (LXU). - * - * The LXU descriptors are similar to XU descriptors - * (see "USB Device Video Class for Video Devices", section - * 3.7.2.6 "Extension Unit Descriptor") with the following - * differences: - * - * ---------------------------------------------------------- - * 0 bLength 1 Number - * Size of this descriptor, in bytes: 24+p+n*2 - * ---------------------------------------------------------- - * 23+p+n bmControlsType N Bitmap - * Individual bits in the set are defined: - * 0: Absolute - * 1: Relative - * - * This bitset is mapped exactly the same as bmControls. - * ---------------------------------------------------------- - * 23+p+n*2 bReserved 1 Boolean - * ---------------------------------------------------------- - * 24+p+n*2 iExtension 1 Index - * Index of a string descriptor that describes this - * extension unit. - * ---------------------------------------------------------- - */ - p = buflen >= 22 ? buffer[21] : 0; - n = buflen >= 25 + p ? buffer[22+p] : 0; - - if (buflen < 25 + p + 2*n) { - uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " - "interface %d EXTENSION_UNIT error\n", - udev->devnum, alts->desc.bInterfaceNumber); - break; - } - - unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3], - p + 1, 2*n); - if (unit == NULL) - return -ENOMEM; - - memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); - unit->extension.bNumControls = buffer[20]; - memcpy(unit->baSourceID, &buffer[22], p); - unit->extension.bControlSize = buffer[22+p]; - unit->extension.bmControls = (__u8 *)unit + sizeof(*unit); - unit->extension.bmControlsType = (__u8 *)unit + sizeof(*unit) - + n; - memcpy(unit->extension.bmControls, &buffer[23+p], 2*n); - - if (buffer[24+p+2*n] != 0) - usb_string(udev, buffer[24+p+2*n], unit->name, - sizeof unit->name); - else - sprintf(unit->name, "Extension %u", buffer[3]); - - list_add_tail(&unit->list, &dev->entities); - handled = 1; - break; - } - - return handled; -} - -static int uvc_parse_standard_control(struct uvc_device *dev, - const unsigned char *buffer, int buflen) -{ - struct usb_device *udev = dev->udev; - struct uvc_entity *unit, *term; - struct usb_interface *intf; - struct usb_host_interface *alts = dev->intf->cur_altsetting; - unsigned int i, n, p, len; - __u16 type; - - switch (buffer[2]) { - case UVC_VC_HEADER: - n = buflen >= 12 ? buffer[11] : 0; - - if (buflen < 12 || buflen < 12 + n) { - uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " - "interface %d HEADER error\n", udev->devnum, - alts->desc.bInterfaceNumber); - return -EINVAL; - } - - dev->uvc_version = get_unaligned_le16(&buffer[3]); - dev->clock_frequency = get_unaligned_le32(&buffer[7]); - - /* Parse all USB Video Streaming interfaces. */ - for (i = 0; i < n; ++i) { - intf = usb_ifnum_to_if(udev, buffer[12+i]); - if (intf == NULL) { - uvc_trace(UVC_TRACE_DESCR, "device %d " - "interface %d doesn't exists\n", - udev->devnum, i); - continue; - } - - uvc_parse_streaming(dev, intf); - } - break; - - case UVC_VC_INPUT_TERMINAL: - if (buflen < 8) { - uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " - "interface %d INPUT_TERMINAL error\n", - udev->devnum, alts->desc.bInterfaceNumber); - return -EINVAL; - } - - /* Make sure the terminal type MSB is not null, otherwise it - * could be confused with a unit. - */ - type = get_unaligned_le16(&buffer[4]); - if ((type & 0xff00) == 0) { - uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " - "interface %d INPUT_TERMINAL %d has invalid " - "type 0x%04x, skipping\n", udev->devnum, - alts->desc.bInterfaceNumber, - buffer[3], type); - return 0; - } - - n = 0; - p = 0; - len = 8; - - if (type == UVC_ITT_CAMERA) { - n = buflen >= 15 ? buffer[14] : 0; - len = 15; - - } else if (type == UVC_ITT_MEDIA_TRANSPORT_INPUT) { - n = buflen >= 9 ? buffer[8] : 0; - p = buflen >= 10 + n ? buffer[9+n] : 0; - len = 10; - } - - if (buflen < len + n + p) { - uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " - "interface %d INPUT_TERMINAL error\n", - udev->devnum, alts->desc.bInterfaceNumber); - return -EINVAL; - } - - term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3], - 1, n + p); - if (term == NULL) - return -ENOMEM; - - if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) { - term->camera.bControlSize = n; - term->camera.bmControls = (__u8 *)term + sizeof *term; - term->camera.wObjectiveFocalLengthMin = - get_unaligned_le16(&buffer[8]); - term->camera.wObjectiveFocalLengthMax = - get_unaligned_le16(&buffer[10]); - term->camera.wOcularFocalLength = - get_unaligned_le16(&buffer[12]); - memcpy(term->camera.bmControls, &buffer[15], n); - } else if (UVC_ENTITY_TYPE(term) == - UVC_ITT_MEDIA_TRANSPORT_INPUT) { - term->media.bControlSize = n; - term->media.bmControls = (__u8 *)term + sizeof *term; - term->media.bTransportModeSize = p; - term->media.bmTransportModes = (__u8 *)term - + sizeof *term + n; - memcpy(term->media.bmControls, &buffer[9], n); - memcpy(term->media.bmTransportModes, &buffer[10+n], p); - } - - if (buffer[7] != 0) - usb_string(udev, buffer[7], term->name, - sizeof term->name); - else if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) - sprintf(term->name, "Camera %u", buffer[3]); - else if (UVC_ENTITY_TYPE(term) == UVC_ITT_MEDIA_TRANSPORT_INPUT) - sprintf(term->name, "Media %u", buffer[3]); - else - sprintf(term->name, "Input %u", buffer[3]); - - list_add_tail(&term->list, &dev->entities); - break; - - case UVC_VC_OUTPUT_TERMINAL: - if (buflen < 9) { - uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " - "interface %d OUTPUT_TERMINAL error\n", - udev->devnum, alts->desc.bInterfaceNumber); - return -EINVAL; - } - - /* Make sure the terminal type MSB is not null, otherwise it - * could be confused with a unit. - */ - type = get_unaligned_le16(&buffer[4]); - if ((type & 0xff00) == 0) { - uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " - "interface %d OUTPUT_TERMINAL %d has invalid " - "type 0x%04x, skipping\n", udev->devnum, - alts->desc.bInterfaceNumber, buffer[3], type); - return 0; - } - - term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3], - 1, 0); - if (term == NULL) - return -ENOMEM; - - memcpy(term->baSourceID, &buffer[7], 1); - - if (buffer[8] != 0) - usb_string(udev, buffer[8], term->name, - sizeof term->name); - else - sprintf(term->name, "Output %u", buffer[3]); - - list_add_tail(&term->list, &dev->entities); - break; - - case UVC_VC_SELECTOR_UNIT: - p = buflen >= 5 ? buffer[4] : 0; - - if (buflen < 5 || buflen < 6 + p) { - uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " - "interface %d SELECTOR_UNIT error\n", - udev->devnum, alts->desc.bInterfaceNumber); - return -EINVAL; - } - - unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0); - if (unit == NULL) - return -ENOMEM; - - memcpy(unit->baSourceID, &buffer[5], p); - - if (buffer[5+p] != 0) - usb_string(udev, buffer[5+p], unit->name, - sizeof unit->name); - else - sprintf(unit->name, "Selector %u", buffer[3]); - - list_add_tail(&unit->list, &dev->entities); - break; - - case UVC_VC_PROCESSING_UNIT: - n = buflen >= 8 ? buffer[7] : 0; - p = dev->uvc_version >= 0x0110 ? 10 : 9; - - if (buflen < p + n) { - uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " - "interface %d PROCESSING_UNIT error\n", - udev->devnum, alts->desc.bInterfaceNumber); - return -EINVAL; - } - - unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n); - if (unit == NULL) - return -ENOMEM; - - memcpy(unit->baSourceID, &buffer[4], 1); - unit->processing.wMaxMultiplier = - get_unaligned_le16(&buffer[5]); - unit->processing.bControlSize = buffer[7]; - unit->processing.bmControls = (__u8 *)unit + sizeof *unit; - memcpy(unit->processing.bmControls, &buffer[8], n); - if (dev->uvc_version >= 0x0110) - unit->processing.bmVideoStandards = buffer[9+n]; - - if (buffer[8+n] != 0) - usb_string(udev, buffer[8+n], unit->name, - sizeof unit->name); - else - sprintf(unit->name, "Processing %u", buffer[3]); - - list_add_tail(&unit->list, &dev->entities); - break; - - case UVC_VC_EXTENSION_UNIT: - p = buflen >= 22 ? buffer[21] : 0; - n = buflen >= 24 + p ? buffer[22+p] : 0; - - if (buflen < 24 + p + n) { - uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " - "interface %d EXTENSION_UNIT error\n", - udev->devnum, alts->desc.bInterfaceNumber); - return -EINVAL; - } - - unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n); - if (unit == NULL) - return -ENOMEM; - - memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); - unit->extension.bNumControls = buffer[20]; - memcpy(unit->baSourceID, &buffer[22], p); - unit->extension.bControlSize = buffer[22+p]; - unit->extension.bmControls = (__u8 *)unit + sizeof *unit; - memcpy(unit->extension.bmControls, &buffer[23+p], n); - - if (buffer[23+p+n] != 0) - usb_string(udev, buffer[23+p+n], unit->name, - sizeof unit->name); - else - sprintf(unit->name, "Extension %u", buffer[3]); - - list_add_tail(&unit->list, &dev->entities); - break; - - default: - uvc_trace(UVC_TRACE_DESCR, "Found an unknown CS_INTERFACE " - "descriptor (%u)\n", buffer[2]); - break; - } - - return 0; -} - -static int uvc_parse_control(struct uvc_device *dev) -{ - struct usb_host_interface *alts = dev->intf->cur_altsetting; - unsigned char *buffer = alts->extra; - int buflen = alts->extralen; - int ret; - - /* Parse the default alternate setting only, as the UVC specification - * defines a single alternate setting, the default alternate setting - * zero. - */ - - while (buflen > 2) { - if (uvc_parse_vendor_control(dev, buffer, buflen) || - buffer[1] != USB_DT_CS_INTERFACE) - goto next_descriptor; - - if ((ret = uvc_parse_standard_control(dev, buffer, buflen)) < 0) - return ret; - -next_descriptor: - buflen -= buffer[0]; - buffer += buffer[0]; - } - - /* Check if the optional status endpoint is present. Built-in iSight - * webcams have an interrupt endpoint but spit proprietary data that - * don't conform to the UVC status endpoint messages. Don't try to - * handle the interrupt endpoint for those cameras. - */ - if (alts->desc.bNumEndpoints == 1 && - !(dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)) { - struct usb_host_endpoint *ep = &alts->endpoint[0]; - struct usb_endpoint_descriptor *desc = &ep->desc; - - if (usb_endpoint_is_int_in(desc) && - le16_to_cpu(desc->wMaxPacketSize) >= 8 && - desc->bInterval != 0) { - uvc_trace(UVC_TRACE_DESCR, "Found a Status endpoint " - "(addr %02x).\n", desc->bEndpointAddress); - dev->int_ep = ep; - } - } - - return 0; -} - -/* ------------------------------------------------------------------------ - * UVC device scan - */ - -/* - * Scan the UVC descriptors to locate a chain starting at an Output Terminal - * and containing the following units: - * - * - one or more Output Terminals (USB Streaming or Display) - * - zero or one Processing Unit - * - zero, one or more single-input Selector Units - * - zero or one multiple-input Selector Units, provided all inputs are - * connected to input terminals - * - zero, one or mode single-input Extension Units - * - one or more Input Terminals (Camera, External or USB Streaming) - * - * The terminal and units must match on of the following structures: - * - * ITT_*(0) -> +---------+ +---------+ +---------+ -> TT_STREAMING(0) - * ... | SU{0,1} | -> | PU{0,1} | -> | XU{0,n} | ... - * ITT_*(n) -> +---------+ +---------+ +---------+ -> TT_STREAMING(n) - * - * +---------+ +---------+ -> OTT_*(0) - * TT_STREAMING -> | PU{0,1} | -> | XU{0,n} | ... - * +---------+ +---------+ -> OTT_*(n) - * - * The Processing Unit and Extension Units can be in any order. Additional - * Extension Units connected to the main chain as single-unit branches are - * also supported. Single-input Selector Units are ignored. - */ -static int uvc_scan_chain_entity(struct uvc_video_chain *chain, - struct uvc_entity *entity) -{ - switch (UVC_ENTITY_TYPE(entity)) { - case UVC_VC_EXTENSION_UNIT: - if (uvc_trace_param & UVC_TRACE_PROBE) - printk(" <- XU %d", entity->id); - - if (entity->bNrInPins != 1) { - uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more " - "than 1 input pin.\n", entity->id); - return -1; - } - - break; - - case UVC_VC_PROCESSING_UNIT: - if (uvc_trace_param & UVC_TRACE_PROBE) - printk(" <- PU %d", entity->id); - - if (chain->processing != NULL) { - uvc_trace(UVC_TRACE_DESCR, "Found multiple " - "Processing Units in chain.\n"); - return -1; - } - - chain->processing = entity; - break; - - case UVC_VC_SELECTOR_UNIT: - if (uvc_trace_param & UVC_TRACE_PROBE) - printk(" <- SU %d", entity->id); - - /* Single-input selector units are ignored. */ - if (entity->bNrInPins == 1) - break; - - if (chain->selector != NULL) { - uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector " - "Units in chain.\n"); - return -1; - } - - chain->selector = entity; - break; - - case UVC_ITT_VENDOR_SPECIFIC: - case UVC_ITT_CAMERA: - case UVC_ITT_MEDIA_TRANSPORT_INPUT: - if (uvc_trace_param & UVC_TRACE_PROBE) - printk(" <- IT %d\n", entity->id); - - break; - - case UVC_OTT_VENDOR_SPECIFIC: - case UVC_OTT_DISPLAY: - case UVC_OTT_MEDIA_TRANSPORT_OUTPUT: - if (uvc_trace_param & UVC_TRACE_PROBE) - printk(" OT %d", entity->id); - - break; - - case UVC_TT_STREAMING: - if (UVC_ENTITY_IS_ITERM(entity)) { - if (uvc_trace_param & UVC_TRACE_PROBE) - printk(" <- IT %d\n", entity->id); - } else { - if (uvc_trace_param & UVC_TRACE_PROBE) - printk(" OT %d", entity->id); - } - - break; - - default: - uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type " - "0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity)); - return -1; - } - - list_add_tail(&entity->chain, &chain->entities); - return 0; -} - -static int uvc_scan_chain_forward(struct uvc_video_chain *chain, - struct uvc_entity *entity, struct uvc_entity *prev) -{ - struct uvc_entity *forward; - int found; - - /* Forward scan */ - forward = NULL; - found = 0; - - while (1) { - forward = uvc_entity_by_reference(chain->dev, entity->id, - forward); - if (forward == NULL) - break; - if (forward == prev) - continue; - - switch (UVC_ENTITY_TYPE(forward)) { - case UVC_VC_EXTENSION_UNIT: - if (forward->bNrInPins != 1) { - uvc_trace(UVC_TRACE_DESCR, "Extension unit %d " - "has more than 1 input pin.\n", - entity->id); - return -EINVAL; - } - - list_add_tail(&forward->chain, &chain->entities); - if (uvc_trace_param & UVC_TRACE_PROBE) { - if (!found) - printk(" (->"); - - printk(" XU %d", forward->id); - found = 1; - } - break; - - case UVC_OTT_VENDOR_SPECIFIC: - case UVC_OTT_DISPLAY: - case UVC_OTT_MEDIA_TRANSPORT_OUTPUT: - case UVC_TT_STREAMING: - if (UVC_ENTITY_IS_ITERM(forward)) { - uvc_trace(UVC_TRACE_DESCR, "Unsupported input " - "terminal %u.\n", forward->id); - return -EINVAL; - } - - list_add_tail(&forward->chain, &chain->entities); - if (uvc_trace_param & UVC_TRACE_PROBE) { - if (!found) - printk(" (->"); - - printk(" OT %d", forward->id); - found = 1; - } - break; - } - } - if (found) - printk(")"); - - return 0; -} - -static int uvc_scan_chain_backward(struct uvc_video_chain *chain, - struct uvc_entity **_entity) -{ - struct uvc_entity *entity = *_entity; - struct uvc_entity *term; - int id = -EINVAL, i; - - switch (UVC_ENTITY_TYPE(entity)) { - case UVC_VC_EXTENSION_UNIT: - case UVC_VC_PROCESSING_UNIT: - id = entity->baSourceID[0]; - break; - - case UVC_VC_SELECTOR_UNIT: - /* Single-input selector units are ignored. */ - if (entity->bNrInPins == 1) { - id = entity->baSourceID[0]; - break; - } - - if (uvc_trace_param & UVC_TRACE_PROBE) - printk(" <- IT"); - - chain->selector = entity; - for (i = 0; i < entity->bNrInPins; ++i) { - id = entity->baSourceID[i]; - term = uvc_entity_by_id(chain->dev, id); - if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) { - uvc_trace(UVC_TRACE_DESCR, "Selector unit %d " - "input %d isn't connected to an " - "input terminal\n", entity->id, i); - return -1; - } - - if (uvc_trace_param & UVC_TRACE_PROBE) - printk(" %d", term->id); - - list_add_tail(&term->chain, &chain->entities); - uvc_scan_chain_forward(chain, term, entity); - } - - if (uvc_trace_param & UVC_TRACE_PROBE) - printk("\n"); - - id = 0; - break; - - case UVC_ITT_VENDOR_SPECIFIC: - case UVC_ITT_CAMERA: - case UVC_ITT_MEDIA_TRANSPORT_INPUT: - case UVC_OTT_VENDOR_SPECIFIC: - case UVC_OTT_DISPLAY: - case UVC_OTT_MEDIA_TRANSPORT_OUTPUT: - case UVC_TT_STREAMING: - id = UVC_ENTITY_IS_OTERM(entity) ? entity->baSourceID[0] : 0; - break; - } - - if (id <= 0) { - *_entity = NULL; - return id; - } - - entity = uvc_entity_by_id(chain->dev, id); - if (entity == NULL) { - uvc_trace(UVC_TRACE_DESCR, "Found reference to " - "unknown entity %d.\n", id); - return -EINVAL; - } - - *_entity = entity; - return 0; -} - -static int uvc_scan_chain(struct uvc_video_chain *chain, - struct uvc_entity *term) -{ - struct uvc_entity *entity, *prev; - - uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain:"); - - entity = term; - prev = NULL; - - while (entity != NULL) { - /* Entity must not be part of an existing chain */ - if (entity->chain.next || entity->chain.prev) { - uvc_trace(UVC_TRACE_DESCR, "Found reference to " - "entity %d already in chain.\n", entity->id); - return -EINVAL; - } - - /* Process entity */ - if (uvc_scan_chain_entity(chain, entity) < 0) - return -EINVAL; - - /* Forward scan */ - if (uvc_scan_chain_forward(chain, entity, prev) < 0) - return -EINVAL; - - /* Backward scan */ - prev = entity; - if (uvc_scan_chain_backward(chain, &entity) < 0) - return -EINVAL; - } - - return 0; -} - -static unsigned int uvc_print_terms(struct list_head *terms, u16 dir, - char *buffer) -{ - struct uvc_entity *term; - unsigned int nterms = 0; - char *p = buffer; - - list_for_each_entry(term, terms, chain) { - if (!UVC_ENTITY_IS_TERM(term) || - UVC_TERM_DIRECTION(term) != dir) - continue; - - if (nterms) - p += sprintf(p, ","); - if (++nterms >= 4) { - p += sprintf(p, "..."); - break; - } - p += sprintf(p, "%u", term->id); - } - - return p - buffer; -} - -static const char *uvc_print_chain(struct uvc_video_chain *chain) -{ - static char buffer[43]; - char *p = buffer; - - p += uvc_print_terms(&chain->entities, UVC_TERM_INPUT, p); - p += sprintf(p, " -> "); - uvc_print_terms(&chain->entities, UVC_TERM_OUTPUT, p); - - return buffer; -} - -/* - * Scan the device for video chains and register video devices. - * - * Chains are scanned starting at their output terminals and walked backwards. - */ -static int uvc_scan_device(struct uvc_device *dev) -{ - struct uvc_video_chain *chain; - struct uvc_entity *term; - - list_for_each_entry(term, &dev->entities, list) { - if (!UVC_ENTITY_IS_OTERM(term)) - continue; - - /* If the terminal is already included in a chain, skip it. - * This can happen for chains that have multiple output - * terminals, where all output terminals beside the first one - * will be inserted in the chain in forward scans. - */ - if (term->chain.next || term->chain.prev) - continue; - - chain = kzalloc(sizeof(*chain), GFP_KERNEL); - if (chain == NULL) - return -ENOMEM; - - INIT_LIST_HEAD(&chain->entities); - mutex_init(&chain->ctrl_mutex); - chain->dev = dev; - - if (uvc_scan_chain(chain, term) < 0) { - kfree(chain); - continue; - } - - uvc_trace(UVC_TRACE_PROBE, "Found a valid video chain (%s).\n", - uvc_print_chain(chain)); - - list_add_tail(&chain->list, &dev->chains); - } - - if (list_empty(&dev->chains)) { - uvc_printk(KERN_INFO, "No valid video chain found.\n"); - return -1; - } - - return 0; -} - -/* ------------------------------------------------------------------------ - * Video device registration and unregistration - */ - -/* - * Delete the UVC device. - * - * Called by the kernel when the last reference to the uvc_device structure - * is released. - * - * As this function is called after or during disconnect(), all URBs have - * already been canceled by the USB core. There is no need to kill the - * interrupt URB manually. - */ -static void uvc_delete(struct uvc_device *dev) -{ - struct list_head *p, *n; - - usb_put_intf(dev->intf); - usb_put_dev(dev->udev); - - uvc_status_cleanup(dev); - uvc_ctrl_cleanup_device(dev); - - if (dev->vdev.dev) - v4l2_device_unregister(&dev->vdev); -#ifdef CONFIG_MEDIA_CONTROLLER - if (media_devnode_is_registered(&dev->mdev.devnode)) - media_device_unregister(&dev->mdev); -#endif - - list_for_each_safe(p, n, &dev->chains) { - struct uvc_video_chain *chain; - chain = list_entry(p, struct uvc_video_chain, list); - kfree(chain); - } - - list_for_each_safe(p, n, &dev->entities) { - struct uvc_entity *entity; - entity = list_entry(p, struct uvc_entity, list); -#ifdef CONFIG_MEDIA_CONTROLLER - uvc_mc_cleanup_entity(entity); -#endif - if (entity->vdev) { - video_device_release(entity->vdev); - entity->vdev = NULL; - } - kfree(entity); - } - - list_for_each_safe(p, n, &dev->streams) { - struct uvc_streaming *streaming; - streaming = list_entry(p, struct uvc_streaming, list); - usb_driver_release_interface(&uvc_driver.driver, - streaming->intf); - usb_put_intf(streaming->intf); - kfree(streaming->format); - kfree(streaming->header.bmaControls); - kfree(streaming); - } - - kfree(dev); -} - -static void uvc_release(struct video_device *vdev) -{ - struct uvc_streaming *stream = video_get_drvdata(vdev); - struct uvc_device *dev = stream->dev; - - /* Decrement the registered streams count and delete the device when it - * reaches zero. - */ - if (atomic_dec_and_test(&dev->nstreams)) - uvc_delete(dev); -} - -/* - * Unregister the video devices. - */ -static void uvc_unregister_video(struct uvc_device *dev) -{ - struct uvc_streaming *stream; - - /* Unregistering all video devices might result in uvc_delete() being - * called from inside the loop if there's no open file handle. To avoid - * that, increment the stream count before iterating over the streams - * and decrement it when done. - */ - atomic_inc(&dev->nstreams); - - list_for_each_entry(stream, &dev->streams, list) { - if (stream->vdev == NULL) - continue; - - video_unregister_device(stream->vdev); - stream->vdev = NULL; - - uvc_debugfs_cleanup_stream(stream); - } - - /* Decrement the stream count and call uvc_delete explicitly if there - * are no stream left. - */ - if (atomic_dec_and_test(&dev->nstreams)) - uvc_delete(dev); -} - -static int uvc_register_video(struct uvc_device *dev, - struct uvc_streaming *stream) -{ - struct video_device *vdev; - int ret; - - /* Initialize the streaming interface with default streaming - * parameters. - */ - ret = uvc_video_init(stream); - if (ret < 0) { - uvc_printk(KERN_ERR, "Failed to initialize the device " - "(%d).\n", ret); - return ret; - } - - uvc_debugfs_init_stream(stream); - - /* Register the device with V4L. */ - vdev = video_device_alloc(); - if (vdev == NULL) { - uvc_printk(KERN_ERR, "Failed to allocate video device (%d).\n", - ret); - return -ENOMEM; - } - - /* We already hold a reference to dev->udev. The video device will be - * unregistered before the reference is released, so we don't need to - * get another one. - */ - vdev->v4l2_dev = &dev->vdev; - vdev->fops = &uvc_fops; - vdev->release = uvc_release; - strlcpy(vdev->name, dev->name, sizeof vdev->name); - - /* Set the driver data before calling video_register_device, otherwise - * uvc_v4l2_open might race us. - */ - stream->vdev = vdev; - video_set_drvdata(vdev, stream); - - ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); - if (ret < 0) { - uvc_printk(KERN_ERR, "Failed to register video device (%d).\n", - ret); - stream->vdev = NULL; - video_device_release(vdev); - return ret; - } - - atomic_inc(&dev->nstreams); - return 0; -} - -/* - * Register all video devices in all chains. - */ -static int uvc_register_terms(struct uvc_device *dev, - struct uvc_video_chain *chain) -{ - struct uvc_streaming *stream; - struct uvc_entity *term; - int ret; - - list_for_each_entry(term, &chain->entities, chain) { - if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING) - continue; - - stream = uvc_stream_by_id(dev, term->id); - if (stream == NULL) { - uvc_printk(KERN_INFO, "No streaming interface found " - "for terminal %u.", term->id); - continue; - } - - stream->chain = chain; - ret = uvc_register_video(dev, stream); - if (ret < 0) - return ret; - - term->vdev = stream->vdev; - } - - return 0; -} - -static int uvc_register_chains(struct uvc_device *dev) -{ - struct uvc_video_chain *chain; - int ret; - - list_for_each_entry(chain, &dev->chains, list) { - ret = uvc_register_terms(dev, chain); - if (ret < 0) - return ret; - -#ifdef CONFIG_MEDIA_CONTROLLER - ret = uvc_mc_register_entities(chain); - if (ret < 0) { - uvc_printk(KERN_INFO, "Failed to register entites " - "(%d).\n", ret); - } -#endif - } - - return 0; -} - -/* ------------------------------------------------------------------------ - * USB probe, disconnect, suspend and resume - */ - -static int uvc_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct uvc_device *dev; - int ret; - - if (id->idVendor && id->idProduct) - uvc_trace(UVC_TRACE_PROBE, "Probing known UVC device %s " - "(%04x:%04x)\n", udev->devpath, id->idVendor, - id->idProduct); - else - uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n", - udev->devpath); - - /* Allocate memory for the device and initialize it. */ - if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL) - return -ENOMEM; - - INIT_LIST_HEAD(&dev->entities); - INIT_LIST_HEAD(&dev->chains); - INIT_LIST_HEAD(&dev->streams); - atomic_set(&dev->nstreams, 0); - atomic_set(&dev->users, 0); - atomic_set(&dev->nmappings, 0); - - dev->udev = usb_get_dev(udev); - dev->intf = usb_get_intf(intf); - dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; - dev->quirks = (uvc_quirks_param == -1) - ? id->driver_info : uvc_quirks_param; - - if (udev->product != NULL) - strlcpy(dev->name, udev->product, sizeof dev->name); - else - snprintf(dev->name, sizeof dev->name, - "UVC Camera (%04x:%04x)", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - - /* Parse the Video Class control descriptor. */ - if (uvc_parse_control(dev) < 0) { - uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC " - "descriptors.\n"); - goto error; - } - - uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n", - dev->uvc_version >> 8, dev->uvc_version & 0xff, - udev->product ? udev->product : "<unnamed>", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - - if (dev->quirks != id->driver_info) { - uvc_printk(KERN_INFO, "Forcing device quirks to 0x%x by module " - "parameter for testing purpose.\n", dev->quirks); - uvc_printk(KERN_INFO, "Please report required quirks to the " - "linux-uvc-devel mailing list.\n"); - } - - /* Register the media and V4L2 devices. */ -#ifdef CONFIG_MEDIA_CONTROLLER - dev->mdev.dev = &intf->dev; - strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model)); - if (udev->serial) - strlcpy(dev->mdev.serial, udev->serial, - sizeof(dev->mdev.serial)); - strcpy(dev->mdev.bus_info, udev->devpath); - dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); - dev->mdev.driver_version = LINUX_VERSION_CODE; - if (media_device_register(&dev->mdev) < 0) - goto error; - - dev->vdev.mdev = &dev->mdev; -#endif - if (v4l2_device_register(&intf->dev, &dev->vdev) < 0) - goto error; - - /* Initialize controls. */ - if (uvc_ctrl_init_device(dev) < 0) - goto error; - - /* Scan the device for video chains. */ - if (uvc_scan_device(dev) < 0) - goto error; - - /* Register video device nodes. */ - if (uvc_register_chains(dev) < 0) - goto error; - - /* Save our data pointer in the interface data. */ - usb_set_intfdata(intf, dev); - - /* Initialize the interrupt URB. */ - if ((ret = uvc_status_init(dev)) < 0) { - uvc_printk(KERN_INFO, "Unable to initialize the status " - "endpoint (%d), status interrupt will not be " - "supported.\n", ret); - } - - uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n"); - usb_enable_autosuspend(udev); - return 0; - -error: - uvc_unregister_video(dev); - return -ENODEV; -} - -static void uvc_disconnect(struct usb_interface *intf) -{ - struct uvc_device *dev = usb_get_intfdata(intf); - - /* Set the USB interface data to NULL. This can be done outside the - * lock, as there's no other reader. - */ - usb_set_intfdata(intf, NULL); - - if (intf->cur_altsetting->desc.bInterfaceSubClass == - UVC_SC_VIDEOSTREAMING) - return; - - dev->state |= UVC_DEV_DISCONNECTED; - - uvc_unregister_video(dev); -} - -static int uvc_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct uvc_device *dev = usb_get_intfdata(intf); - struct uvc_streaming *stream; - - uvc_trace(UVC_TRACE_SUSPEND, "Suspending interface %u\n", - intf->cur_altsetting->desc.bInterfaceNumber); - - /* Controls are cached on the fly so they don't need to be saved. */ - if (intf->cur_altsetting->desc.bInterfaceSubClass == - UVC_SC_VIDEOCONTROL) - return uvc_status_suspend(dev); - - list_for_each_entry(stream, &dev->streams, list) { - if (stream->intf == intf) - return uvc_video_suspend(stream); - } - - uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB interface " - "mismatch.\n"); - return -EINVAL; -} - -static int __uvc_resume(struct usb_interface *intf, int reset) -{ - struct uvc_device *dev = usb_get_intfdata(intf); - struct uvc_streaming *stream; - - uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n", - intf->cur_altsetting->desc.bInterfaceNumber); - - if (intf->cur_altsetting->desc.bInterfaceSubClass == - UVC_SC_VIDEOCONTROL) { - if (reset) { - int ret = uvc_ctrl_resume_device(dev); - - if (ret < 0) - return ret; - } - - return uvc_status_resume(dev); - } - - list_for_each_entry(stream, &dev->streams, list) { - if (stream->intf == intf) - return uvc_video_resume(stream, reset); - } - - uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB interface " - "mismatch.\n"); - return -EINVAL; -} - -static int uvc_resume(struct usb_interface *intf) -{ - return __uvc_resume(intf, 0); -} - -static int uvc_reset_resume(struct usb_interface *intf) -{ - return __uvc_resume(intf, 1); -} - -/* ------------------------------------------------------------------------ - * Module parameters - */ - -static int uvc_clock_param_get(char *buffer, struct kernel_param *kp) -{ - if (uvc_clock_param == CLOCK_MONOTONIC) - return sprintf(buffer, "CLOCK_MONOTONIC"); - else - return sprintf(buffer, "CLOCK_REALTIME"); -} - -static int uvc_clock_param_set(const char *val, struct kernel_param *kp) -{ - if (strncasecmp(val, "clock_", strlen("clock_")) == 0) - val += strlen("clock_"); - - if (strcasecmp(val, "monotonic") == 0) - uvc_clock_param = CLOCK_MONOTONIC; - else if (strcasecmp(val, "realtime") == 0) - uvc_clock_param = CLOCK_REALTIME; - else - return -EINVAL; - - return 0; -} - -module_param_call(clock, uvc_clock_param_set, uvc_clock_param_get, - &uvc_clock_param, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(clock, "Video buffers timestamp clock"); -module_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(nodrop, "Don't drop incomplete frames"); -module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(quirks, "Forced device quirks"); -module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(trace, "Trace level bitmask"); -module_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); - -/* ------------------------------------------------------------------------ - * Driver initialization and cleanup - */ - -/* - * The Logitech cameras listed below have their interface class set to - * VENDOR_SPEC because they don't announce themselves as UVC devices, even - * though they are compliant. - */ -static struct usb_device_id uvc_ids[] = { - /* LogiLink Wireless Webcam */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x0416, - .idProduct = 0xa91a, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX }, - /* Genius eFace 2025 */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x0458, - .idProduct = 0x706e, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX }, - /* Microsoft Lifecam NX-6000 */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x045e, - .idProduct = 0x00f8, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX }, - /* Microsoft Lifecam VX-7000 */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x045e, - .idProduct = 0x0723, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX }, - /* Logitech Quickcam Fusion */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x046d, - .idProduct = 0x08c1, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0 }, - /* Logitech Quickcam Orbit MP */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x046d, - .idProduct = 0x08c2, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0 }, - /* Logitech Quickcam Pro for Notebook */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x046d, - .idProduct = 0x08c3, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0 }, - /* Logitech Quickcam Pro 5000 */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x046d, - .idProduct = 0x08c5, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0 }, - /* Logitech Quickcam OEM Dell Notebook */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x046d, - .idProduct = 0x08c6, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0 }, - /* Logitech Quickcam OEM Cisco VT Camera II */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x046d, - .idProduct = 0x08c7, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0 }, - /* Chicony CNF7129 (Asus EEE 100HE) */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x04f2, - .idProduct = 0xb071, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_RESTRICT_FRAME_RATE }, - /* Alcor Micro AU3820 (Future Boy PC USB Webcam) */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x058f, - .idProduct = 0x3820, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX }, - /* Dell XPS m1530 */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x05a9, - .idProduct = 0x2640, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_DEF }, - /* Apple Built-In iSight */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x05ac, - .idProduct = 0x8501, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX - | UVC_QUIRK_BUILTIN_ISIGHT }, - /* Foxlink ("HP Webcam" on HP Mini 5103) */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x05c8, - .idProduct = 0x0403, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, - /* Genesys Logic USB 2.0 PC Camera */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x05e3, - .idProduct = 0x0505, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_STREAM_NO_FID }, - /* Hercules Classic Silver */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x06f8, - .idProduct = 0x300c, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, - /* ViMicro Vega */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x0ac8, - .idProduct = 0x332d, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, - /* ViMicro - Minoru3D */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x0ac8, - .idProduct = 0x3410, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, - /* ViMicro Venus - Minoru3D */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x0ac8, - .idProduct = 0x3420, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, - /* Ophir Optronics - SPCAM 620U */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x0bd3, - .idProduct = 0x0555, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX }, - /* MT6227 */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x0e8d, - .idProduct = 0x0004, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX - | UVC_QUIRK_PROBE_DEF }, - /* IMC Networks (Medion Akoya) */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x13d3, - .idProduct = 0x5103, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_STREAM_NO_FID }, - /* JMicron USB2.0 XGA WebCam */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x152d, - .idProduct = 0x0310, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX }, - /* Syntek (HP Spartan) */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x174f, - .idProduct = 0x5212, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_STREAM_NO_FID }, - /* Syntek (Samsung Q310) */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x174f, - .idProduct = 0x5931, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_STREAM_NO_FID }, - /* Syntek (Packard Bell EasyNote MX52 */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x174f, - .idProduct = 0x8a12, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_STREAM_NO_FID }, - /* Syntek (Asus F9SG) */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x174f, - .idProduct = 0x8a31, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_STREAM_NO_FID }, - /* Syntek (Asus U3S) */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x174f, - .idProduct = 0x8a33, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_STREAM_NO_FID }, - /* Syntek (JAOtech Smart Terminal) */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x174f, - .idProduct = 0x8a34, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_STREAM_NO_FID }, - /* Miricle 307K */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x17dc, - .idProduct = 0x0202, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_STREAM_NO_FID }, - /* Lenovo Thinkpad SL400/SL500 */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x17ef, - .idProduct = 0x480b, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_STREAM_NO_FID }, - /* Aveo Technology USB 2.0 Camera */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x1871, - .idProduct = 0x0306, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX - | UVC_QUIRK_PROBE_EXTRAFIELDS }, - /* Ecamm Pico iMage */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x18cd, - .idProduct = 0xcafe, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_EXTRAFIELDS }, - /* Manta MM-353 Plako */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x18ec, - .idProduct = 0x3188, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX }, - /* FSC WebCam V30S */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x18ec, - .idProduct = 0x3288, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX }, - /* Arkmicro unbranded */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x18ec, - .idProduct = 0x3290, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_DEF }, - /* The Imaging Source USB CCD cameras */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x199e, - .idProduct = 0x8102, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0 }, - /* Bodelin ProScopeHR */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_DEV_HI - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x19ab, - .idProduct = 0x1000, - .bcdDevice_hi = 0x0126, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_STATUS_INTERVAL }, - /* MSI StarCam 370i */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x1b3b, - .idProduct = 0x2951, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX }, - /* SiGma Micro USB Web Camera */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x1c4f, - .idProduct = 0x3000, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_MINMAX - | UVC_QUIRK_IGNORE_SELECTOR_UNIT }, - /* Generic USB Video Class */ - { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, - {} -}; - -MODULE_DEVICE_TABLE(usb, uvc_ids); - -struct uvc_driver uvc_driver = { - .driver = { - .name = "uvcvideo", - .probe = uvc_probe, - .disconnect = uvc_disconnect, - .suspend = uvc_suspend, - .resume = uvc_resume, - .reset_resume = uvc_reset_resume, - .id_table = uvc_ids, - .supports_autosuspend = 1, - }, -}; - -static int __init uvc_init(void) -{ - int ret; - - uvc_debugfs_init(); - - ret = usb_register(&uvc_driver.driver); - if (ret < 0) { - uvc_debugfs_cleanup(); - return ret; - } - - printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n"); - return 0; -} - -static void __exit uvc_cleanup(void) -{ - usb_deregister(&uvc_driver.driver); - uvc_debugfs_cleanup(); -} - -module_init(uvc_init); -module_exit(uvc_cleanup); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRIVER_VERSION); - diff --git a/drivers/media/video/uvc/uvc_entity.c b/drivers/media/video/uvc/uvc_entity.c deleted file mode 100644 index 29e239911d0e..000000000000 --- a/drivers/media/video/uvc/uvc_entity.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * uvc_entity.c -- USB Video Class driver - * - * Copyright (C) 2005-2011 - * Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * 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. - * - */ - -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/videodev2.h> - -#include <media/v4l2-common.h> - -#include "uvcvideo.h" - -/* ------------------------------------------------------------------------ - * Video subdevices registration and unregistration - */ - -static int uvc_mc_register_entity(struct uvc_video_chain *chain, - struct uvc_entity *entity) -{ - const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE; - struct media_entity *sink; - unsigned int i; - int ret; - - sink = (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING) - ? (entity->vdev ? &entity->vdev->entity : NULL) - : &entity->subdev.entity; - if (sink == NULL) - return 0; - - for (i = 0; i < entity->num_pads; ++i) { - struct media_entity *source; - struct uvc_entity *remote; - u8 remote_pad; - - if (!(entity->pads[i].flags & MEDIA_PAD_FL_SINK)) - continue; - - remote = uvc_entity_by_id(chain->dev, entity->baSourceID[i]); - if (remote == NULL) - return -EINVAL; - - source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING) - ? (remote->vdev ? &remote->vdev->entity : NULL) - : &remote->subdev.entity; - if (source == NULL) - continue; - - remote_pad = remote->num_pads - 1; - ret = media_entity_create_link(source, remote_pad, - sink, i, flags); - if (ret < 0) - return ret; - } - - if (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING) - return 0; - - return v4l2_device_register_subdev(&chain->dev->vdev, &entity->subdev); -} - -static struct v4l2_subdev_ops uvc_subdev_ops = { -}; - -void uvc_mc_cleanup_entity(struct uvc_entity *entity) -{ - if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) - media_entity_cleanup(&entity->subdev.entity); - else if (entity->vdev != NULL) - media_entity_cleanup(&entity->vdev->entity); -} - -static int uvc_mc_init_entity(struct uvc_entity *entity) -{ - int ret; - - if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) { - v4l2_subdev_init(&entity->subdev, &uvc_subdev_ops); - strlcpy(entity->subdev.name, entity->name, - sizeof(entity->subdev.name)); - - ret = media_entity_init(&entity->subdev.entity, - entity->num_pads, entity->pads, 0); - } else if (entity->vdev != NULL) { - ret = media_entity_init(&entity->vdev->entity, - entity->num_pads, entity->pads, 0); - } else - ret = 0; - - return ret; -} - -int uvc_mc_register_entities(struct uvc_video_chain *chain) -{ - struct uvc_entity *entity; - int ret; - - list_for_each_entry(entity, &chain->entities, chain) { - ret = uvc_mc_init_entity(entity); - if (ret < 0) { - uvc_printk(KERN_INFO, "Failed to initialize entity for " - "entity %u\n", entity->id); - return ret; - } - } - - list_for_each_entry(entity, &chain->entities, chain) { - ret = uvc_mc_register_entity(chain, entity); - if (ret < 0) { - uvc_printk(KERN_INFO, "Failed to register entity for " - "entity %u\n", entity->id); - return ret; - } - } - - return 0; -} diff --git a/drivers/media/video/uvc/uvc_isight.c b/drivers/media/video/uvc/uvc_isight.c deleted file mode 100644 index 8510e7259e76..000000000000 --- a/drivers/media/video/uvc/uvc_isight.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * uvc_isight.c -- USB Video Class driver - iSight support - * - * Copyright (C) 2006-2007 - * Ivan N. Zlatev <contact@i-nz.net> - * Copyright (C) 2008-2009 - * Laurent Pinchart <laurent.pinchart@ideasonboard.com> - * - * 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. - * - */ - -#include <linux/usb.h> -#include <linux/kernel.h> -#include <linux/mm.h> - -#include "uvcvideo.h" - -/* Built-in iSight webcams implements most of UVC 1.0 except a - * different packet format. Instead of sending a header at the - * beginning of each isochronous transfer payload, the webcam sends a - * single header per image (on its own in a packet), followed by - * packets containing data only. - * - * Offset Size (bytes) Description - * ------------------------------------------------------------------ - * 0x00 1 Header length - * 0x01 1 Flags (UVC-compliant) - * 0x02 4 Always equal to '11223344' - * 0x06 8 Always equal to 'deadbeefdeadface' - * 0x0e 16 Unknown - * - * The header can be prefixed by an optional, unknown-purpose byte. - */ - -static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf, - const __u8 *data, unsigned int len) -{ - static const __u8 hdr[] = { - 0x11, 0x22, 0x33, 0x44, - 0xde, 0xad, 0xbe, 0xef, - 0xde, 0xad, 0xfa, 0xce - }; - - unsigned int maxlen, nbytes; - __u8 *mem; - int is_header = 0; - - if (buf == NULL) - return 0; - - if ((len >= 14 && memcmp(&data[2], hdr, 12) == 0) || - (len >= 15 && memcmp(&data[3], hdr, 12) == 0)) { - uvc_trace(UVC_TRACE_FRAME, "iSight header found\n"); - is_header = 1; - } - - /* Synchronize to the input stream by waiting for a header packet. */ - if (buf->state != UVC_BUF_STATE_ACTIVE) { - if (!is_header) { - uvc_trace(UVC_TRACE_FRAME, "Dropping packet (out of " - "sync).\n"); - return 0; - } - - buf->state = UVC_BUF_STATE_ACTIVE; - } - - /* Mark the buffer as done if we're at the beginning of a new frame. - * - * Empty buffers (bytesused == 0) don't trigger end of frame detection - * as it doesn't make sense to return an empty buffer. - */ - if (is_header && buf->bytesused != 0) { - buf->state = UVC_BUF_STATE_DONE; - return -EAGAIN; - } - - /* Copy the video data to the buffer. Skip header packets, as they - * contain no data. - */ - if (!is_header) { - maxlen = buf->length - buf->bytesused; - mem = buf->mem + buf->bytesused; - nbytes = min(len, maxlen); - memcpy(mem, data, nbytes); - buf->bytesused += nbytes; - - if (len > maxlen || buf->bytesused == buf->length) { - uvc_trace(UVC_TRACE_FRAME, "Frame complete " - "(overflow).\n"); - buf->state = UVC_BUF_STATE_DONE; - } - } - - return 0; -} - -void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream, - struct uvc_buffer *buf) -{ - int ret, i; - - for (i = 0; i < urb->number_of_packets; ++i) { - if (urb->iso_frame_desc[i].status < 0) { - uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame " - "lost (%d).\n", - urb->iso_frame_desc[i].status); - } - - /* Decode the payload packet. - * uvc_video_decode is entered twice when a frame transition - * has been detected because the end of frame can only be - * reliably detected when the first packet of the new frame - * is processed. The first pass detects the transition and - * closes the previous frame's buffer, the second pass - * processes the data of the first payload of the new frame. - */ - do { - ret = isight_decode(&stream->queue, buf, - urb->transfer_buffer + - urb->iso_frame_desc[i].offset, - urb->iso_frame_desc[i].actual_length); - - if (buf == NULL) - break; - - if (buf->state == UVC_BUF_STATE_DONE || - buf->state == UVC_BUF_STATE_ERROR) - buf = uvc_queue_next_buffer(&stream->queue, - buf); - } while (ret == -EAGAIN); - } -} diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c deleted file mode 100644 index 9288fbd5001b..000000000000 --- a/drivers/media/video/uvc/uvc_queue.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * uvc_queue.c -- USB Video Class driver - Buffers management - * - * Copyright (C) 2005-2010 - * Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * 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. - * - */ - -#include <linux/atomic.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/usb.h> -#include <linux/videodev2.h> -#include <linux/vmalloc.h> -#include <linux/wait.h> -#include <media/videobuf2-vmalloc.h> - -#include "uvcvideo.h" - -/* ------------------------------------------------------------------------ - * Video buffers queue management. - * - * Video queues is initialized by uvc_queue_init(). The function performs - * basic initialization of the uvc_video_queue struct and never fails. - * - * Video buffers are managed by videobuf2. The driver uses a mutex to protect - * the videobuf2 queue operations by serializing calls to videobuf2 and a - * spinlock to protect the IRQ queue that holds the buffers to be processed by - * the driver. - */ - -/* ----------------------------------------------------------------------------- - * videobuf2 queue operations - */ - -static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, - unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], void *alloc_ctxs[]) -{ - struct uvc_video_queue *queue = vb2_get_drv_priv(vq); - struct uvc_streaming *stream = - container_of(queue, struct uvc_streaming, queue); - - if (*nbuffers > UVC_MAX_VIDEO_BUFFERS) - *nbuffers = UVC_MAX_VIDEO_BUFFERS; - - *nplanes = 1; - - sizes[0] = stream->ctrl.dwMaxVideoFrameSize; - - return 0; -} - -static int uvc_buffer_prepare(struct vb2_buffer *vb) -{ - struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); - struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf); - - if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT && - vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) { - uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n"); - return -EINVAL; - } - - if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED)) - return -ENODEV; - - buf->state = UVC_BUF_STATE_QUEUED; - buf->error = 0; - buf->mem = vb2_plane_vaddr(vb, 0); - buf->length = vb2_plane_size(vb, 0); - if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - buf->bytesused = 0; - else - buf->bytesused = vb2_get_plane_payload(vb, 0); - - return 0; -} - -static void uvc_buffer_queue(struct vb2_buffer *vb) -{ - struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); - struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf); - unsigned long flags; - - spin_lock_irqsave(&queue->irqlock, flags); - if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) { - list_add_tail(&buf->queue, &queue->irqqueue); - } else { - /* If the device is disconnected return the buffer to userspace - * directly. The next QBUF call will fail with -ENODEV. - */ - buf->state = UVC_BUF_STATE_ERROR; - vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR); - } - - spin_unlock_irqrestore(&queue->irqlock, flags); -} - -static int uvc_buffer_finish(struct vb2_buffer *vb) -{ - struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); - struct uvc_streaming *stream = - container_of(queue, struct uvc_streaming, queue); - struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf); - - uvc_video_clock_update(stream, &vb->v4l2_buf, buf); - return 0; -} - -static struct vb2_ops uvc_queue_qops = { - .queue_setup = uvc_queue_setup, - .buf_prepare = uvc_buffer_prepare, - .buf_queue = uvc_buffer_queue, - .buf_finish = uvc_buffer_finish, -}; - -void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, - int drop_corrupted) -{ - queue->queue.type = type; - queue->queue.io_modes = VB2_MMAP | VB2_USERPTR; - queue->queue.drv_priv = queue; - queue->queue.buf_struct_size = sizeof(struct uvc_buffer); - queue->queue.ops = &uvc_queue_qops; - queue->queue.mem_ops = &vb2_vmalloc_memops; - vb2_queue_init(&queue->queue); - - mutex_init(&queue->mutex); - spin_lock_init(&queue->irqlock); - INIT_LIST_HEAD(&queue->irqqueue); - queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0; -} - -/* ----------------------------------------------------------------------------- - * V4L2 queue operations - */ - -int uvc_alloc_buffers(struct uvc_video_queue *queue, - struct v4l2_requestbuffers *rb) -{ - int ret; - - mutex_lock(&queue->mutex); - ret = vb2_reqbufs(&queue->queue, rb); - mutex_unlock(&queue->mutex); - - return ret ? ret : rb->count; -} - -void uvc_free_buffers(struct uvc_video_queue *queue) -{ - mutex_lock(&queue->mutex); - vb2_queue_release(&queue->queue); - mutex_unlock(&queue->mutex); -} - -int uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) -{ - int ret; - - mutex_lock(&queue->mutex); - ret = vb2_querybuf(&queue->queue, buf); - mutex_unlock(&queue->mutex); - - return ret; -} - -int uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) -{ - int ret; - - mutex_lock(&queue->mutex); - ret = vb2_qbuf(&queue->queue, buf); - mutex_unlock(&queue->mutex); - - return ret; -} - -int uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf, - int nonblocking) -{ - int ret; - - mutex_lock(&queue->mutex); - ret = vb2_dqbuf(&queue->queue, buf, nonblocking); - mutex_unlock(&queue->mutex); - - return ret; -} - -int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) -{ - int ret; - - mutex_lock(&queue->mutex); - ret = vb2_mmap(&queue->queue, vma); - mutex_unlock(&queue->mutex); - - return ret; -} - -#ifndef CONFIG_MMU -unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, - unsigned long pgoff) -{ - unsigned long ret; - - mutex_lock(&queue->mutex); - ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0); - mutex_unlock(&queue->mutex); - return ret; -} -#endif - -unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, - poll_table *wait) -{ - unsigned int ret; - - mutex_lock(&queue->mutex); - ret = vb2_poll(&queue->queue, file, wait); - mutex_unlock(&queue->mutex); - - return ret; -} - -/* ----------------------------------------------------------------------------- - * - */ - -/* - * Check if buffers have been allocated. - */ -int uvc_queue_allocated(struct uvc_video_queue *queue) -{ - int allocated; - - mutex_lock(&queue->mutex); - allocated = vb2_is_busy(&queue->queue); - mutex_unlock(&queue->mutex); - - return allocated; -} - -/* - * Enable or disable the video buffers queue. - * - * The queue must be enabled before starting video acquisition and must be - * disabled after stopping it. This ensures that the video buffers queue - * state can be properly initialized before buffers are accessed from the - * interrupt handler. - * - * Enabling the video queue returns -EBUSY if the queue is already enabled. - * - * Disabling the video queue cancels the queue and removes all buffers from - * the main queue. - * - * This function can't be called from interrupt context. Use - * uvc_queue_cancel() instead. - */ -int uvc_queue_enable(struct uvc_video_queue *queue, int enable) -{ - unsigned long flags; - int ret; - - mutex_lock(&queue->mutex); - if (enable) { - ret = vb2_streamon(&queue->queue, queue->queue.type); - if (ret < 0) - goto done; - - queue->buf_used = 0; - } else { - ret = vb2_streamoff(&queue->queue, queue->queue.type); - if (ret < 0) - goto done; - - spin_lock_irqsave(&queue->irqlock, flags); - INIT_LIST_HEAD(&queue->irqqueue); - spin_unlock_irqrestore(&queue->irqlock, flags); - } - -done: - mutex_unlock(&queue->mutex); - return ret; -} - -/* - * Cancel the video buffers queue. - * - * Cancelling the queue marks all buffers on the irq queue as erroneous, - * wakes them up and removes them from the queue. - * - * If the disconnect parameter is set, further calls to uvc_queue_buffer will - * fail with -ENODEV. - * - * This function acquires the irq spinlock and can be called from interrupt - * context. - */ -void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect) -{ - struct uvc_buffer *buf; - unsigned long flags; - - spin_lock_irqsave(&queue->irqlock, flags); - while (!list_empty(&queue->irqqueue)) { - buf = list_first_entry(&queue->irqqueue, struct uvc_buffer, - queue); - list_del(&buf->queue); - buf->state = UVC_BUF_STATE_ERROR; - vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR); - } - /* This must be protected by the irqlock spinlock to avoid race - * conditions between uvc_buffer_queue and the disconnection event that - * could result in an interruptible wait in uvc_dequeue_buffer. Do not - * blindly replace this logic by checking for the UVC_QUEUE_DISCONNECTED - * state outside the queue code. - */ - if (disconnect) - queue->flags |= UVC_QUEUE_DISCONNECTED; - spin_unlock_irqrestore(&queue->irqlock, flags); -} - -struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, - struct uvc_buffer *buf) -{ - struct uvc_buffer *nextbuf; - unsigned long flags; - - if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) { - buf->error = 0; - buf->state = UVC_BUF_STATE_QUEUED; - vb2_set_plane_payload(&buf->buf, 0, 0); - return buf; - } - - spin_lock_irqsave(&queue->irqlock, flags); - list_del(&buf->queue); - if (!list_empty(&queue->irqqueue)) - nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, - queue); - else - nextbuf = NULL; - spin_unlock_irqrestore(&queue->irqlock, flags); - - buf->state = buf->error ? VB2_BUF_STATE_ERROR : UVC_BUF_STATE_DONE; - vb2_set_plane_payload(&buf->buf, 0, buf->bytesused); - vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE); - - return nextbuf; -} diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c deleted file mode 100644 index b7492775e6ae..000000000000 --- a/drivers/media/video/uvc/uvc_status.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * uvc_status.c -- USB Video Class driver - Status endpoint - * - * Copyright (C) 2005-2009 - * Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * 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. - * - */ - -#include <linux/kernel.h> -#include <linux/input.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/usb/input.h> - -#include "uvcvideo.h" - -/* -------------------------------------------------------------------------- - * Input device - */ -#ifdef CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV -static int uvc_input_init(struct uvc_device *dev) -{ - struct input_dev *input; - int ret; - - input = input_allocate_device(); - if (input == NULL) - return -ENOMEM; - - usb_make_path(dev->udev, dev->input_phys, sizeof(dev->input_phys)); - strlcat(dev->input_phys, "/button", sizeof(dev->input_phys)); - - input->name = dev->name; - input->phys = dev->input_phys; - usb_to_input_id(dev->udev, &input->id); - input->dev.parent = &dev->intf->dev; - - __set_bit(EV_KEY, input->evbit); - __set_bit(KEY_CAMERA, input->keybit); - - if ((ret = input_register_device(input)) < 0) - goto error; - - dev->input = input; - return 0; - -error: - input_free_device(input); - return ret; -} - -static void uvc_input_cleanup(struct uvc_device *dev) -{ - if (dev->input) - input_unregister_device(dev->input); -} - -static void uvc_input_report_key(struct uvc_device *dev, unsigned int code, - int value) -{ - if (dev->input) { - input_report_key(dev->input, code, value); - input_sync(dev->input); - } -} - -#else -#define uvc_input_init(dev) -#define uvc_input_cleanup(dev) -#define uvc_input_report_key(dev, code, value) -#endif /* CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV */ - -/* -------------------------------------------------------------------------- - * Status interrupt endpoint - */ -static void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len) -{ - if (len < 3) { - uvc_trace(UVC_TRACE_STATUS, "Invalid streaming status event " - "received.\n"); - return; - } - - if (data[2] == 0) { - if (len < 4) - return; - uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n", - data[1], data[3] ? "pressed" : "released", len); - uvc_input_report_key(dev, KEY_CAMERA, data[3]); - } else { - uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x " - "len %d.\n", data[1], data[2], data[3], len); - } -} - -static void uvc_event_control(struct uvc_device *dev, __u8 *data, int len) -{ - char *attrs[3] = { "value", "info", "failure" }; - - if (len < 6 || data[2] != 0 || data[4] > 2) { - uvc_trace(UVC_TRACE_STATUS, "Invalid control status event " - "received.\n"); - return; - } - - uvc_trace(UVC_TRACE_STATUS, "Control %u/%u %s change len %d.\n", - data[1], data[3], attrs[data[4]], len); -} - -static void uvc_status_complete(struct urb *urb) -{ - struct uvc_device *dev = urb->context; - int len, ret; - - switch (urb->status) { - case 0: - break; - - case -ENOENT: /* usb_kill_urb() called. */ - case -ECONNRESET: /* usb_unlink_urb() called. */ - case -ESHUTDOWN: /* The endpoint is being disabled. */ - case -EPROTO: /* Device is disconnected (reported by some - * host controller). */ - return; - - default: - uvc_printk(KERN_WARNING, "Non-zero status (%d) in status " - "completion handler.\n", urb->status); - return; - } - - len = urb->actual_length; - if (len > 0) { - switch (dev->status[0] & 0x0f) { - case UVC_STATUS_TYPE_CONTROL: - uvc_event_control(dev, dev->status, len); - break; - - case UVC_STATUS_TYPE_STREAMING: - uvc_event_streaming(dev, dev->status, len); - break; - - default: - uvc_trace(UVC_TRACE_STATUS, "Unknown status event " - "type %u.\n", dev->status[0]); - break; - } - } - - /* Resubmit the URB. */ - urb->interval = dev->int_ep->desc.bInterval; - if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { - uvc_printk(KERN_ERR, "Failed to resubmit status URB (%d).\n", - ret); - } -} - -int uvc_status_init(struct uvc_device *dev) -{ - struct usb_host_endpoint *ep = dev->int_ep; - unsigned int pipe; - int interval; - - if (ep == NULL) - return 0; - - uvc_input_init(dev); - - dev->status = kzalloc(UVC_MAX_STATUS_SIZE, GFP_KERNEL); - if (dev->status == NULL) - return -ENOMEM; - - dev->int_urb = usb_alloc_urb(0, GFP_KERNEL); - if (dev->int_urb == NULL) { - kfree(dev->status); - return -ENOMEM; - } - - pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress); - - /* For high-speed interrupt endpoints, the bInterval value is used as - * an exponent of two. Some developers forgot about it. - */ - interval = ep->desc.bInterval; - if (interval > 16 && dev->udev->speed == USB_SPEED_HIGH && - (dev->quirks & UVC_QUIRK_STATUS_INTERVAL)) - interval = fls(interval) - 1; - - usb_fill_int_urb(dev->int_urb, dev->udev, pipe, - dev->status, UVC_MAX_STATUS_SIZE, uvc_status_complete, - dev, interval); - - return 0; -} - -void uvc_status_cleanup(struct uvc_device *dev) -{ - usb_kill_urb(dev->int_urb); - usb_free_urb(dev->int_urb); - kfree(dev->status); - uvc_input_cleanup(dev); -} - -int uvc_status_start(struct uvc_device *dev) -{ - if (dev->int_urb == NULL) - return 0; - - return usb_submit_urb(dev->int_urb, GFP_KERNEL); -} - -void uvc_status_stop(struct uvc_device *dev) -{ - usb_kill_urb(dev->int_urb); -} - -int uvc_status_suspend(struct uvc_device *dev) -{ - if (atomic_read(&dev->users)) - usb_kill_urb(dev->int_urb); - - return 0; -} - -int uvc_status_resume(struct uvc_device *dev) -{ - if (dev->int_urb == NULL || atomic_read(&dev->users) == 0) - return 0; - - return usb_submit_urb(dev->int_urb, GFP_NOIO); -} - diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c deleted file mode 100644 index f00db3060e0e..000000000000 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ /dev/null @@ -1,1317 +0,0 @@ -/* - * uvc_v4l2.c -- USB Video Class driver - V4L2 API - * - * Copyright (C) 2005-2010 - * Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * 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. - * - */ - -#include <linux/compat.h> -#include <linux/kernel.h> -#include <linux/version.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/videodev2.h> -#include <linux/vmalloc.h> -#include <linux/mm.h> -#include <linux/wait.h> -#include <linux/atomic.h> - -#include <media/v4l2-common.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-event.h> -#include <media/v4l2-ioctl.h> - -#include "uvcvideo.h" - -/* ------------------------------------------------------------------------ - * UVC ioctls - */ -static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain, - struct uvc_xu_control_mapping *xmap) -{ - struct uvc_control_mapping *map; - unsigned int size; - int ret; - - map = kzalloc(sizeof *map, GFP_KERNEL); - if (map == NULL) - return -ENOMEM; - - map->id = xmap->id; - memcpy(map->name, xmap->name, sizeof map->name); - memcpy(map->entity, xmap->entity, sizeof map->entity); - map->selector = xmap->selector; - map->size = xmap->size; - map->offset = xmap->offset; - map->v4l2_type = xmap->v4l2_type; - map->data_type = xmap->data_type; - - switch (xmap->v4l2_type) { - case V4L2_CTRL_TYPE_INTEGER: - case V4L2_CTRL_TYPE_BOOLEAN: - case V4L2_CTRL_TYPE_BUTTON: - break; - - case V4L2_CTRL_TYPE_MENU: - /* Prevent excessive memory consumption, as well as integer - * overflows. - */ - if (xmap->menu_count == 0 || - xmap->menu_count > UVC_MAX_CONTROL_MENU_ENTRIES) { - ret = -EINVAL; - goto done; - } - - size = xmap->menu_count * sizeof(*map->menu_info); - map->menu_info = kmalloc(size, GFP_KERNEL); - if (map->menu_info == NULL) { - ret = -ENOMEM; - goto done; - } - - if (copy_from_user(map->menu_info, xmap->menu_info, size)) { - ret = -EFAULT; - goto done; - } - - map->menu_count = xmap->menu_count; - break; - - default: - uvc_trace(UVC_TRACE_CONTROL, "Unsupported V4L2 control type " - "%u.\n", xmap->v4l2_type); - ret = -ENOTTY; - goto done; - } - - ret = uvc_ctrl_add_mapping(chain, map); - -done: - kfree(map->menu_info); - kfree(map); - - return ret; -} - -/* ------------------------------------------------------------------------ - * V4L2 interface - */ - -/* - * Find the frame interval closest to the requested frame interval for the - * given frame format and size. This should be done by the device as part of - * the Video Probe and Commit negotiation, but some hardware don't implement - * that feature. - */ -static __u32 uvc_try_frame_interval(struct uvc_frame *frame, __u32 interval) -{ - unsigned int i; - - if (frame->bFrameIntervalType) { - __u32 best = -1, dist; - - for (i = 0; i < frame->bFrameIntervalType; ++i) { - dist = interval > frame->dwFrameInterval[i] - ? interval - frame->dwFrameInterval[i] - : frame->dwFrameInterval[i] - interval; - - if (dist > best) - break; - - best = dist; - } - - interval = frame->dwFrameInterval[i-1]; - } else { - const __u32 min = frame->dwFrameInterval[0]; - const __u32 max = frame->dwFrameInterval[1]; - const __u32 step = frame->dwFrameInterval[2]; - - interval = min + (interval - min + step/2) / step * step; - if (interval > max) - interval = max; - } - - return interval; -} - -static int uvc_v4l2_try_format(struct uvc_streaming *stream, - struct v4l2_format *fmt, struct uvc_streaming_control *probe, - struct uvc_format **uvc_format, struct uvc_frame **uvc_frame) -{ - struct uvc_format *format = NULL; - struct uvc_frame *frame = NULL; - __u16 rw, rh; - unsigned int d, maxd; - unsigned int i; - __u32 interval; - int ret = 0; - __u8 *fcc; - - if (fmt->type != stream->type) - return -EINVAL; - - fcc = (__u8 *)&fmt->fmt.pix.pixelformat; - uvc_trace(UVC_TRACE_FORMAT, "Trying format 0x%08x (%c%c%c%c): %ux%u.\n", - fmt->fmt.pix.pixelformat, - fcc[0], fcc[1], fcc[2], fcc[3], - fmt->fmt.pix.width, fmt->fmt.pix.height); - - /* Check if the hardware supports the requested format. */ - for (i = 0; i < stream->nformats; ++i) { - format = &stream->format[i]; - if (format->fcc == fmt->fmt.pix.pixelformat) - break; - } - - if (format == NULL || format->fcc != fmt->fmt.pix.pixelformat) { - uvc_trace(UVC_TRACE_FORMAT, "Unsupported format 0x%08x.\n", - fmt->fmt.pix.pixelformat); - return -EINVAL; - } - - /* Find the closest image size. The distance between image sizes is - * the size in pixels of the non-overlapping regions between the - * requested size and the frame-specified size. - */ - rw = fmt->fmt.pix.width; - rh = fmt->fmt.pix.height; - maxd = (unsigned int)-1; - - for (i = 0; i < format->nframes; ++i) { - __u16 w = format->frame[i].wWidth; - __u16 h = format->frame[i].wHeight; - - d = min(w, rw) * min(h, rh); - d = w*h + rw*rh - 2*d; - if (d < maxd) { - maxd = d; - frame = &format->frame[i]; - } - - if (maxd == 0) - break; - } - - if (frame == NULL) { - uvc_trace(UVC_TRACE_FORMAT, "Unsupported size %ux%u.\n", - fmt->fmt.pix.width, fmt->fmt.pix.height); - return -EINVAL; - } - - /* Use the default frame interval. */ - interval = frame->dwDefaultFrameInterval; - uvc_trace(UVC_TRACE_FORMAT, "Using default frame interval %u.%u us " - "(%u.%u fps).\n", interval/10, interval%10, 10000000/interval, - (100000000/interval)%10); - - /* Set the format index, frame index and frame interval. */ - memset(probe, 0, sizeof *probe); - probe->bmHint = 1; /* dwFrameInterval */ - probe->bFormatIndex = format->index; - probe->bFrameIndex = frame->bFrameIndex; - probe->dwFrameInterval = uvc_try_frame_interval(frame, interval); - /* Some webcams stall the probe control set request when the - * dwMaxVideoFrameSize field is set to zero. The UVC specification - * clearly states that the field is read-only from the host, so this - * is a webcam bug. Set dwMaxVideoFrameSize to the value reported by - * the webcam to work around the problem. - * - * The workaround could probably be enabled for all webcams, so the - * quirk can be removed if needed. It's currently useful to detect - * webcam bugs and fix them before they hit the market (providing - * developers test their webcams with the Linux driver as well as with - * the Windows driver). - */ - mutex_lock(&stream->mutex); - if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS) - probe->dwMaxVideoFrameSize = - stream->ctrl.dwMaxVideoFrameSize; - - /* Probe the device. */ - ret = uvc_probe_video(stream, probe); - mutex_unlock(&stream->mutex); - if (ret < 0) - goto done; - - fmt->fmt.pix.width = frame->wWidth; - fmt->fmt.pix.height = frame->wHeight; - fmt->fmt.pix.field = V4L2_FIELD_NONE; - fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8; - fmt->fmt.pix.sizeimage = probe->dwMaxVideoFrameSize; - fmt->fmt.pix.colorspace = format->colorspace; - fmt->fmt.pix.priv = 0; - - if (uvc_format != NULL) - *uvc_format = format; - if (uvc_frame != NULL) - *uvc_frame = frame; - -done: - return ret; -} - -static int uvc_v4l2_get_format(struct uvc_streaming *stream, - struct v4l2_format *fmt) -{ - struct uvc_format *format; - struct uvc_frame *frame; - int ret = 0; - - if (fmt->type != stream->type) - return -EINVAL; - - mutex_lock(&stream->mutex); - format = stream->cur_format; - frame = stream->cur_frame; - - if (format == NULL || frame == NULL) { - ret = -EINVAL; - goto done; - } - - fmt->fmt.pix.pixelformat = format->fcc; - fmt->fmt.pix.width = frame->wWidth; - fmt->fmt.pix.height = frame->wHeight; - fmt->fmt.pix.field = V4L2_FIELD_NONE; - fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8; - fmt->fmt.pix.sizeimage = stream->ctrl.dwMaxVideoFrameSize; - fmt->fmt.pix.colorspace = format->colorspace; - fmt->fmt.pix.priv = 0; - -done: - mutex_unlock(&stream->mutex); - return ret; -} - -static int uvc_v4l2_set_format(struct uvc_streaming *stream, - struct v4l2_format *fmt) -{ - struct uvc_streaming_control probe; - struct uvc_format *format; - struct uvc_frame *frame; - int ret; - - if (fmt->type != stream->type) - return -EINVAL; - - ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame); - if (ret < 0) - return ret; - - mutex_lock(&stream->mutex); - - if (uvc_queue_allocated(&stream->queue)) { - ret = -EBUSY; - goto done; - } - - memcpy(&stream->ctrl, &probe, sizeof probe); - stream->cur_format = format; - stream->cur_frame = frame; - -done: - mutex_unlock(&stream->mutex); - return ret; -} - -static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, - struct v4l2_streamparm *parm) -{ - uint32_t numerator, denominator; - - if (parm->type != stream->type) - return -EINVAL; - - mutex_lock(&stream->mutex); - numerator = stream->ctrl.dwFrameInterval; - mutex_unlock(&stream->mutex); - - denominator = 10000000; - uvc_simplify_fraction(&numerator, &denominator, 8, 333); - - memset(parm, 0, sizeof *parm); - parm->type = stream->type; - - if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; - parm->parm.capture.capturemode = 0; - parm->parm.capture.timeperframe.numerator = numerator; - parm->parm.capture.timeperframe.denominator = denominator; - parm->parm.capture.extendedmode = 0; - parm->parm.capture.readbuffers = 0; - } else { - parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME; - parm->parm.output.outputmode = 0; - parm->parm.output.timeperframe.numerator = numerator; - parm->parm.output.timeperframe.denominator = denominator; - } - - return 0; -} - -static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, - struct v4l2_streamparm *parm) -{ - struct uvc_streaming_control probe; - struct v4l2_fract timeperframe; - uint32_t interval; - int ret; - - if (parm->type != stream->type) - return -EINVAL; - - if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - timeperframe = parm->parm.capture.timeperframe; - else - timeperframe = parm->parm.output.timeperframe; - - interval = uvc_fraction_to_interval(timeperframe.numerator, - timeperframe.denominator); - uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n", - timeperframe.numerator, timeperframe.denominator, interval); - - mutex_lock(&stream->mutex); - - if (uvc_queue_streaming(&stream->queue)) { - mutex_unlock(&stream->mutex); - return -EBUSY; - } - - memcpy(&probe, &stream->ctrl, sizeof probe); - probe.dwFrameInterval = - uvc_try_frame_interval(stream->cur_frame, interval); - - /* Probe the device with the new settings. */ - ret = uvc_probe_video(stream, &probe); - if (ret < 0) { - mutex_unlock(&stream->mutex); - return ret; - } - - memcpy(&stream->ctrl, &probe, sizeof probe); - mutex_unlock(&stream->mutex); - - /* Return the actual frame period. */ - timeperframe.numerator = probe.dwFrameInterval; - timeperframe.denominator = 10000000; - uvc_simplify_fraction(&timeperframe.numerator, - &timeperframe.denominator, 8, 333); - - if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - parm->parm.capture.timeperframe = timeperframe; - else - parm->parm.output.timeperframe = timeperframe; - - return 0; -} - -/* ------------------------------------------------------------------------ - * Privilege management - */ - -/* - * Privilege management is the multiple-open implementation basis. The current - * implementation is completely transparent for the end-user and doesn't - * require explicit use of the VIDIOC_G_PRIORITY and VIDIOC_S_PRIORITY ioctls. - * Those ioctls enable finer control on the device (by making possible for a - * user to request exclusive access to a device), but are not mature yet. - * Switching to the V4L2 priority mechanism might be considered in the future - * if this situation changes. - * - * Each open instance of a UVC device can either be in a privileged or - * unprivileged state. Only a single instance can be in a privileged state at - * a given time. Trying to perform an operation that requires privileges will - * automatically acquire the required privileges if possible, or return -EBUSY - * otherwise. Privileges are dismissed when closing the instance or when - * freeing the video buffers using VIDIOC_REQBUFS. - * - * Operations that require privileges are: - * - * - VIDIOC_S_INPUT - * - VIDIOC_S_PARM - * - VIDIOC_S_FMT - * - VIDIOC_REQBUFS - */ -static int uvc_acquire_privileges(struct uvc_fh *handle) -{ - /* Always succeed if the handle is already privileged. */ - if (handle->state == UVC_HANDLE_ACTIVE) - return 0; - - /* Check if the device already has a privileged handle. */ - if (atomic_inc_return(&handle->stream->active) != 1) { - atomic_dec(&handle->stream->active); - return -EBUSY; - } - - handle->state = UVC_HANDLE_ACTIVE; - return 0; -} - -static void uvc_dismiss_privileges(struct uvc_fh *handle) -{ - if (handle->state == UVC_HANDLE_ACTIVE) - atomic_dec(&handle->stream->active); - - handle->state = UVC_HANDLE_PASSIVE; -} - -static int uvc_has_privileges(struct uvc_fh *handle) -{ - return handle->state == UVC_HANDLE_ACTIVE; -} - -/* ------------------------------------------------------------------------ - * V4L2 file operations - */ - -static int uvc_v4l2_open(struct file *file) -{ - struct uvc_streaming *stream; - struct uvc_fh *handle; - int ret = 0; - - uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n"); - stream = video_drvdata(file); - - if (stream->dev->state & UVC_DEV_DISCONNECTED) - return -ENODEV; - - ret = usb_autopm_get_interface(stream->dev->intf); - if (ret < 0) - return ret; - - /* Create the device handle. */ - handle = kzalloc(sizeof *handle, GFP_KERNEL); - if (handle == NULL) { - usb_autopm_put_interface(stream->dev->intf); - return -ENOMEM; - } - - if (atomic_inc_return(&stream->dev->users) == 1) { - ret = uvc_status_start(stream->dev); - if (ret < 0) { - usb_autopm_put_interface(stream->dev->intf); - atomic_dec(&stream->dev->users); - kfree(handle); - return ret; - } - } - - v4l2_fh_init(&handle->vfh, stream->vdev); - v4l2_fh_add(&handle->vfh); - handle->chain = stream->chain; - handle->stream = stream; - handle->state = UVC_HANDLE_PASSIVE; - file->private_data = handle; - - return 0; -} - -static int uvc_v4l2_release(struct file *file) -{ - struct uvc_fh *handle = file->private_data; - struct uvc_streaming *stream = handle->stream; - - uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n"); - - /* Only free resources if this is a privileged handle. */ - if (uvc_has_privileges(handle)) { - uvc_video_enable(stream, 0); - uvc_free_buffers(&stream->queue); - } - - /* Release the file handle. */ - uvc_dismiss_privileges(handle); - v4l2_fh_del(&handle->vfh); - v4l2_fh_exit(&handle->vfh); - kfree(handle); - file->private_data = NULL; - - if (atomic_dec_return(&stream->dev->users) == 0) - uvc_status_stop(stream->dev); - - usb_autopm_put_interface(stream->dev->intf); - return 0; -} - -static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) -{ - struct video_device *vdev = video_devdata(file); - struct uvc_fh *handle = file->private_data; - struct uvc_video_chain *chain = handle->chain; - struct uvc_streaming *stream = handle->stream; - long ret = 0; - - switch (cmd) { - /* Query capabilities */ - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *cap = arg; - - memset(cap, 0, sizeof *cap); - strlcpy(cap->driver, "uvcvideo", sizeof cap->driver); - strlcpy(cap->card, vdev->name, sizeof cap->card); - usb_make_path(stream->dev->udev, - cap->bus_info, sizeof(cap->bus_info)); - cap->version = LINUX_VERSION_CODE; - if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE - | V4L2_CAP_STREAMING; - else - cap->capabilities = V4L2_CAP_VIDEO_OUTPUT - | V4L2_CAP_STREAMING; - break; - } - - /* Get, Set & Query control */ - case VIDIOC_QUERYCTRL: - return uvc_query_v4l2_ctrl(chain, arg); - - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; - struct v4l2_ext_control xctrl; - - memset(&xctrl, 0, sizeof xctrl); - xctrl.id = ctrl->id; - - ret = uvc_ctrl_begin(chain); - if (ret < 0) - return ret; - - ret = uvc_ctrl_get(chain, &xctrl); - uvc_ctrl_rollback(handle); - if (ret >= 0) - ctrl->value = xctrl.value; - break; - } - - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; - struct v4l2_ext_control xctrl; - - memset(&xctrl, 0, sizeof xctrl); - xctrl.id = ctrl->id; - xctrl.value = ctrl->value; - - ret = uvc_ctrl_begin(chain); - if (ret < 0) - return ret; - - ret = uvc_ctrl_set(chain, &xctrl); - if (ret < 0) { - uvc_ctrl_rollback(handle); - return ret; - } - ret = uvc_ctrl_commit(handle, &xctrl, 1); - if (ret == 0) - ctrl->value = xctrl.value; - break; - } - - case VIDIOC_QUERYMENU: - return uvc_query_v4l2_menu(chain, arg); - - case VIDIOC_G_EXT_CTRLS: - { - struct v4l2_ext_controls *ctrls = arg; - struct v4l2_ext_control *ctrl = ctrls->controls; - unsigned int i; - - ret = uvc_ctrl_begin(chain); - if (ret < 0) - return ret; - - for (i = 0; i < ctrls->count; ++ctrl, ++i) { - ret = uvc_ctrl_get(chain, ctrl); - if (ret < 0) { - uvc_ctrl_rollback(handle); - ctrls->error_idx = i; - return ret; - } - } - ctrls->error_idx = 0; - ret = uvc_ctrl_rollback(handle); - break; - } - - case VIDIOC_S_EXT_CTRLS: - case VIDIOC_TRY_EXT_CTRLS: - { - struct v4l2_ext_controls *ctrls = arg; - struct v4l2_ext_control *ctrl = ctrls->controls; - unsigned int i; - - ret = uvc_ctrl_begin(chain); - if (ret < 0) - return ret; - - for (i = 0; i < ctrls->count; ++ctrl, ++i) { - ret = uvc_ctrl_set(chain, ctrl); - if (ret < 0) { - uvc_ctrl_rollback(handle); - ctrls->error_idx = i; - return ret; - } - } - - ctrls->error_idx = 0; - - if (cmd == VIDIOC_S_EXT_CTRLS) - ret = uvc_ctrl_commit(handle, - ctrls->controls, ctrls->count); - else - ret = uvc_ctrl_rollback(handle); - break; - } - - /* Get, Set & Enum input */ - case VIDIOC_ENUMINPUT: - { - const struct uvc_entity *selector = chain->selector; - struct v4l2_input *input = arg; - struct uvc_entity *iterm = NULL; - u32 index = input->index; - int pin = 0; - - if (selector == NULL || - (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { - if (index != 0) - return -EINVAL; - list_for_each_entry(iterm, &chain->entities, chain) { - if (UVC_ENTITY_IS_ITERM(iterm)) - break; - } - pin = iterm->id; - } else if (index < selector->bNrInPins) { - pin = selector->baSourceID[index]; - list_for_each_entry(iterm, &chain->entities, chain) { - if (!UVC_ENTITY_IS_ITERM(iterm)) - continue; - if (iterm->id == pin) - break; - } - } - - if (iterm == NULL || iterm->id != pin) - return -EINVAL; - - memset(input, 0, sizeof *input); - input->index = index; - strlcpy(input->name, iterm->name, sizeof input->name); - if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA) - input->type = V4L2_INPUT_TYPE_CAMERA; - break; - } - - case VIDIOC_G_INPUT: - { - u8 input; - - if (chain->selector == NULL || - (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { - *(int *)arg = 0; - break; - } - - ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, - chain->selector->id, chain->dev->intfnum, - UVC_SU_INPUT_SELECT_CONTROL, &input, 1); - if (ret < 0) - return ret; - - *(int *)arg = input - 1; - break; - } - - case VIDIOC_S_INPUT: - { - u32 input = *(u32 *)arg + 1; - - if ((ret = uvc_acquire_privileges(handle)) < 0) - return ret; - - if (chain->selector == NULL || - (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { - if (input != 1) - return -EINVAL; - break; - } - - if (input == 0 || input > chain->selector->bNrInPins) - return -EINVAL; - - return uvc_query_ctrl(chain->dev, UVC_SET_CUR, - chain->selector->id, chain->dev->intfnum, - UVC_SU_INPUT_SELECT_CONTROL, &input, 1); - } - - /* Try, Get, Set & Enum format */ - case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc *fmt = arg; - struct uvc_format *format; - enum v4l2_buf_type type = fmt->type; - __u32 index = fmt->index; - - if (fmt->type != stream->type || - fmt->index >= stream->nformats) - return -EINVAL; - - memset(fmt, 0, sizeof(*fmt)); - fmt->index = index; - fmt->type = type; - - format = &stream->format[fmt->index]; - fmt->flags = 0; - if (format->flags & UVC_FMT_FLAG_COMPRESSED) - fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; - strlcpy(fmt->description, format->name, - sizeof fmt->description); - fmt->description[sizeof fmt->description - 1] = 0; - fmt->pixelformat = format->fcc; - break; - } - - case VIDIOC_TRY_FMT: - { - struct uvc_streaming_control probe; - - return uvc_v4l2_try_format(stream, arg, &probe, NULL, NULL); - } - - case VIDIOC_S_FMT: - if ((ret = uvc_acquire_privileges(handle)) < 0) - return ret; - - return uvc_v4l2_set_format(stream, arg); - - case VIDIOC_G_FMT: - return uvc_v4l2_get_format(stream, arg); - - /* Frame size enumeration */ - case VIDIOC_ENUM_FRAMESIZES: - { - struct v4l2_frmsizeenum *fsize = arg; - struct uvc_format *format = NULL; - struct uvc_frame *frame; - int i; - - /* Look for the given pixel format */ - for (i = 0; i < stream->nformats; i++) { - if (stream->format[i].fcc == - fsize->pixel_format) { - format = &stream->format[i]; - break; - } - } - if (format == NULL) - return -EINVAL; - - if (fsize->index >= format->nframes) - return -EINVAL; - - frame = &format->frame[fsize->index]; - fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; - fsize->discrete.width = frame->wWidth; - fsize->discrete.height = frame->wHeight; - break; - } - - /* Frame interval enumeration */ - case VIDIOC_ENUM_FRAMEINTERVALS: - { - struct v4l2_frmivalenum *fival = arg; - struct uvc_format *format = NULL; - struct uvc_frame *frame = NULL; - int i; - - /* Look for the given pixel format and frame size */ - for (i = 0; i < stream->nformats; i++) { - if (stream->format[i].fcc == - fival->pixel_format) { - format = &stream->format[i]; - break; - } - } - if (format == NULL) - return -EINVAL; - - for (i = 0; i < format->nframes; i++) { - if (format->frame[i].wWidth == fival->width && - format->frame[i].wHeight == fival->height) { - frame = &format->frame[i]; - break; - } - } - if (frame == NULL) - return -EINVAL; - - if (frame->bFrameIntervalType) { - if (fival->index >= frame->bFrameIntervalType) - return -EINVAL; - - fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; - fival->discrete.numerator = - frame->dwFrameInterval[fival->index]; - fival->discrete.denominator = 10000000; - uvc_simplify_fraction(&fival->discrete.numerator, - &fival->discrete.denominator, 8, 333); - } else { - fival->type = V4L2_FRMIVAL_TYPE_STEPWISE; - fival->stepwise.min.numerator = - frame->dwFrameInterval[0]; - fival->stepwise.min.denominator = 10000000; - fival->stepwise.max.numerator = - frame->dwFrameInterval[1]; - fival->stepwise.max.denominator = 10000000; - fival->stepwise.step.numerator = - frame->dwFrameInterval[2]; - fival->stepwise.step.denominator = 10000000; - uvc_simplify_fraction(&fival->stepwise.min.numerator, - &fival->stepwise.min.denominator, 8, 333); - uvc_simplify_fraction(&fival->stepwise.max.numerator, - &fival->stepwise.max.denominator, 8, 333); - uvc_simplify_fraction(&fival->stepwise.step.numerator, - &fival->stepwise.step.denominator, 8, 333); - } - break; - } - - /* Get & Set streaming parameters */ - case VIDIOC_G_PARM: - return uvc_v4l2_get_streamparm(stream, arg); - - case VIDIOC_S_PARM: - if ((ret = uvc_acquire_privileges(handle)) < 0) - return ret; - - return uvc_v4l2_set_streamparm(stream, arg); - - /* Cropping and scaling */ - case VIDIOC_CROPCAP: - { - struct v4l2_cropcap *ccap = arg; - - if (ccap->type != stream->type) - return -EINVAL; - - ccap->bounds.left = 0; - ccap->bounds.top = 0; - - mutex_lock(&stream->mutex); - ccap->bounds.width = stream->cur_frame->wWidth; - ccap->bounds.height = stream->cur_frame->wHeight; - mutex_unlock(&stream->mutex); - - ccap->defrect = ccap->bounds; - - ccap->pixelaspect.numerator = 1; - ccap->pixelaspect.denominator = 1; - break; - } - - case VIDIOC_G_CROP: - case VIDIOC_S_CROP: - return -EINVAL; - - /* Buffers & streaming */ - case VIDIOC_REQBUFS: - if ((ret = uvc_acquire_privileges(handle)) < 0) - return ret; - - mutex_lock(&stream->mutex); - ret = uvc_alloc_buffers(&stream->queue, arg); - mutex_unlock(&stream->mutex); - if (ret < 0) - return ret; - - if (ret == 0) - uvc_dismiss_privileges(handle); - - ret = 0; - break; - - case VIDIOC_QUERYBUF: - { - struct v4l2_buffer *buf = arg; - - if (!uvc_has_privileges(handle)) - return -EBUSY; - - return uvc_query_buffer(&stream->queue, buf); - } - - case VIDIOC_QBUF: - if (!uvc_has_privileges(handle)) - return -EBUSY; - - return uvc_queue_buffer(&stream->queue, arg); - - case VIDIOC_DQBUF: - if (!uvc_has_privileges(handle)) - return -EBUSY; - - return uvc_dequeue_buffer(&stream->queue, arg, - file->f_flags & O_NONBLOCK); - - case VIDIOC_STREAMON: - { - int *type = arg; - - if (*type != stream->type) - return -EINVAL; - - if (!uvc_has_privileges(handle)) - return -EBUSY; - - mutex_lock(&stream->mutex); - ret = uvc_video_enable(stream, 1); - mutex_unlock(&stream->mutex); - if (ret < 0) - return ret; - break; - } - - case VIDIOC_STREAMOFF: - { - int *type = arg; - - if (*type != stream->type) - return -EINVAL; - - if (!uvc_has_privileges(handle)) - return -EBUSY; - - return uvc_video_enable(stream, 0); - } - - case VIDIOC_SUBSCRIBE_EVENT: - { - struct v4l2_event_subscription *sub = arg; - - switch (sub->type) { - case V4L2_EVENT_CTRL: - return v4l2_event_subscribe(&handle->vfh, sub, 0, - &uvc_ctrl_sub_ev_ops); - default: - return -EINVAL; - } - } - - case VIDIOC_UNSUBSCRIBE_EVENT: - return v4l2_event_unsubscribe(&handle->vfh, arg); - - case VIDIOC_DQEVENT: - return v4l2_event_dequeue(&handle->vfh, arg, - file->f_flags & O_NONBLOCK); - - /* Analog video standards make no sense for digital cameras. */ - case VIDIOC_ENUMSTD: - case VIDIOC_QUERYSTD: - case VIDIOC_G_STD: - case VIDIOC_S_STD: - - case VIDIOC_OVERLAY: - - case VIDIOC_ENUMAUDIO: - case VIDIOC_ENUMAUDOUT: - - case VIDIOC_ENUMOUTPUT: - uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd); - return -EINVAL; - - case UVCIOC_CTRL_MAP: - return uvc_ioctl_ctrl_map(chain, arg); - - case UVCIOC_CTRL_QUERY: - return uvc_xu_ctrl_query(chain, arg); - - default: - uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd); - return -ENOTTY; - } - - return ret; -} - -static long uvc_v4l2_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - if (uvc_trace_param & UVC_TRACE_IOCTL) { - uvc_printk(KERN_DEBUG, "uvc_v4l2_ioctl("); - v4l_printk_ioctl(NULL, cmd); - printk(")\n"); - } - - return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl); -} - -#ifdef CONFIG_COMPAT -struct uvc_xu_control_mapping32 { - __u32 id; - __u8 name[32]; - __u8 entity[16]; - __u8 selector; - - __u8 size; - __u8 offset; - __u32 v4l2_type; - __u32 data_type; - - compat_caddr_t menu_info; - __u32 menu_count; - - __u32 reserved[4]; -}; - -static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp, - const struct uvc_xu_control_mapping32 __user *up) -{ - struct uvc_menu_info __user *umenus; - struct uvc_menu_info __user *kmenus; - compat_caddr_t p; - - if (!access_ok(VERIFY_READ, up, sizeof(*up)) || - __copy_from_user(kp, up, offsetof(typeof(*up), menu_info)) || - __get_user(kp->menu_count, &up->menu_count)) - return -EFAULT; - - memset(kp->reserved, 0, sizeof(kp->reserved)); - - if (kp->menu_count == 0) { - kp->menu_info = NULL; - return 0; - } - - if (__get_user(p, &up->menu_info)) - return -EFAULT; - umenus = compat_ptr(p); - if (!access_ok(VERIFY_READ, umenus, kp->menu_count * sizeof(*umenus))) - return -EFAULT; - - kmenus = compat_alloc_user_space(kp->menu_count * sizeof(*kmenus)); - if (kmenus == NULL) - return -EFAULT; - kp->menu_info = kmenus; - - if (copy_in_user(kmenus, umenus, kp->menu_count * sizeof(*umenus))) - return -EFAULT; - - return 0; -} - -static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp, - struct uvc_xu_control_mapping32 __user *up) -{ - struct uvc_menu_info __user *umenus; - struct uvc_menu_info __user *kmenus = kp->menu_info; - compat_caddr_t p; - - if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || - __copy_to_user(up, kp, offsetof(typeof(*up), menu_info)) || - __put_user(kp->menu_count, &up->menu_count)) - return -EFAULT; - - if (__clear_user(up->reserved, sizeof(up->reserved))) - return -EFAULT; - - if (kp->menu_count == 0) - return 0; - - if (get_user(p, &up->menu_info)) - return -EFAULT; - umenus = compat_ptr(p); - - if (copy_in_user(umenus, kmenus, kp->menu_count * sizeof(*umenus))) - return -EFAULT; - - return 0; -} - -struct uvc_xu_control_query32 { - __u8 unit; - __u8 selector; - __u8 query; - __u16 size; - compat_caddr_t data; -}; - -static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp, - const struct uvc_xu_control_query32 __user *up) -{ - u8 __user *udata; - u8 __user *kdata; - compat_caddr_t p; - - if (!access_ok(VERIFY_READ, up, sizeof(*up)) || - __copy_from_user(kp, up, offsetof(typeof(*up), data))) - return -EFAULT; - - if (kp->size == 0) { - kp->data = NULL; - return 0; - } - - if (__get_user(p, &up->data)) - return -EFAULT; - udata = compat_ptr(p); - if (!access_ok(VERIFY_READ, udata, kp->size)) - return -EFAULT; - - kdata = compat_alloc_user_space(kp->size); - if (kdata == NULL) - return -EFAULT; - kp->data = kdata; - - if (copy_in_user(kdata, udata, kp->size)) - return -EFAULT; - - return 0; -} - -static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp, - struct uvc_xu_control_query32 __user *up) -{ - u8 __user *udata; - u8 __user *kdata = kp->data; - compat_caddr_t p; - - if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || - __copy_to_user(up, kp, offsetof(typeof(*up), data))) - return -EFAULT; - - if (kp->size == 0) - return 0; - - if (get_user(p, &up->data)) - return -EFAULT; - udata = compat_ptr(p); - if (!access_ok(VERIFY_READ, udata, kp->size)) - return -EFAULT; - - if (copy_in_user(udata, kdata, kp->size)) - return -EFAULT; - - return 0; -} - -#define UVCIOC_CTRL_MAP32 _IOWR('u', 0x20, struct uvc_xu_control_mapping32) -#define UVCIOC_CTRL_QUERY32 _IOWR('u', 0x21, struct uvc_xu_control_query32) - -static long uvc_v4l2_compat_ioctl32(struct file *file, - unsigned int cmd, unsigned long arg) -{ - union { - struct uvc_xu_control_mapping xmap; - struct uvc_xu_control_query xqry; - } karg; - void __user *up = compat_ptr(arg); - mm_segment_t old_fs; - long ret; - - switch (cmd) { - case UVCIOC_CTRL_MAP32: - cmd = UVCIOC_CTRL_MAP; - ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up); - break; - - case UVCIOC_CTRL_QUERY32: - cmd = UVCIOC_CTRL_QUERY; - ret = uvc_v4l2_get_xu_query(&karg.xqry, up); - break; - - default: - return -ENOIOCTLCMD; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = uvc_v4l2_ioctl(file, cmd, (unsigned long)&karg); - set_fs(old_fs); - - if (ret < 0) - return ret; - - switch (cmd) { - case UVCIOC_CTRL_MAP: - ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up); - break; - - case UVCIOC_CTRL_QUERY: - ret = uvc_v4l2_put_xu_query(&karg.xqry, up); - break; - } - - return ret; -} -#endif - -static ssize_t uvc_v4l2_read(struct file *file, char __user *data, - size_t count, loff_t *ppos) -{ - uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_read: not implemented.\n"); - return -EINVAL; -} - -static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct uvc_fh *handle = file->private_data; - struct uvc_streaming *stream = handle->stream; - - uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n"); - - return uvc_queue_mmap(&stream->queue, vma); -} - -static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) -{ - struct uvc_fh *handle = file->private_data; - struct uvc_streaming *stream = handle->stream; - - uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n"); - - return uvc_queue_poll(&stream->queue, file, wait); -} - -#ifndef CONFIG_MMU -static unsigned long uvc_v4l2_get_unmapped_area(struct file *file, - unsigned long addr, unsigned long len, unsigned long pgoff, - unsigned long flags) -{ - struct uvc_fh *handle = file->private_data; - struct uvc_streaming *stream = handle->stream; - - uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_get_unmapped_area\n"); - - return uvc_queue_get_unmapped_area(&stream->queue, pgoff); -} -#endif - -const struct v4l2_file_operations uvc_fops = { - .owner = THIS_MODULE, - .open = uvc_v4l2_open, - .release = uvc_v4l2_release, - .unlocked_ioctl = uvc_v4l2_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl32 = uvc_v4l2_compat_ioctl32, -#endif - .read = uvc_v4l2_read, - .mmap = uvc_v4l2_mmap, - .poll = uvc_v4l2_poll, -#ifndef CONFIG_MMU - .get_unmapped_area = uvc_v4l2_get_unmapped_area, -#endif -}; - diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c deleted file mode 100644 index 1c15b4227bdb..000000000000 --- a/drivers/media/video/uvc/uvc_video.c +++ /dev/null @@ -1,1879 +0,0 @@ -/* - * uvc_video.c -- USB Video Class driver - Video handling - * - * Copyright (C) 2005-2010 - * Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * 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. - * - */ - -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/videodev2.h> -#include <linux/vmalloc.h> -#include <linux/wait.h> -#include <linux/atomic.h> -#include <asm/unaligned.h> - -#include <media/v4l2-common.h> - -#include "uvcvideo.h" - -/* ------------------------------------------------------------------------ - * UVC Controls - */ - -static int __uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, - __u8 intfnum, __u8 cs, void *data, __u16 size, - int timeout) -{ - __u8 type = USB_TYPE_CLASS | USB_RECIP_INTERFACE; - unsigned int pipe; - - pipe = (query & 0x80) ? usb_rcvctrlpipe(dev->udev, 0) - : usb_sndctrlpipe(dev->udev, 0); - type |= (query & 0x80) ? USB_DIR_IN : USB_DIR_OUT; - - return usb_control_msg(dev->udev, pipe, query, type, cs << 8, - unit << 8 | intfnum, data, size, timeout); -} - -static const char *uvc_query_name(__u8 query) -{ - switch (query) { - case UVC_SET_CUR: - return "SET_CUR"; - case UVC_GET_CUR: - return "GET_CUR"; - case UVC_GET_MIN: - return "GET_MIN"; - case UVC_GET_MAX: - return "GET_MAX"; - case UVC_GET_RES: - return "GET_RES"; - case UVC_GET_LEN: - return "GET_LEN"; - case UVC_GET_INFO: - return "GET_INFO"; - case UVC_GET_DEF: - return "GET_DEF"; - default: - return "<invalid>"; - } -} - -int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, - __u8 intfnum, __u8 cs, void *data, __u16 size) -{ - int ret; - - ret = __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size, - UVC_CTRL_CONTROL_TIMEOUT); - if (ret != size) { - uvc_printk(KERN_ERR, "Failed to query (%s) UVC control %u on " - "unit %u: %d (exp. %u).\n", uvc_query_name(query), cs, - unit, ret, size); - return -EIO; - } - - return 0; -} - -static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, - struct uvc_streaming_control *ctrl) -{ - struct uvc_format *format = NULL; - struct uvc_frame *frame = NULL; - unsigned int i; - - for (i = 0; i < stream->nformats; ++i) { - if (stream->format[i].index == ctrl->bFormatIndex) { - format = &stream->format[i]; - break; - } - } - - if (format == NULL) - return; - - for (i = 0; i < format->nframes; ++i) { - if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) { - frame = &format->frame[i]; - break; - } - } - - if (frame == NULL) - return; - - if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) || - (ctrl->dwMaxVideoFrameSize == 0 && - stream->dev->uvc_version < 0x0110)) - ctrl->dwMaxVideoFrameSize = - frame->dwMaxVideoFrameBufferSize; - - if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) && - stream->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH && - stream->intf->num_altsetting > 1) { - u32 interval; - u32 bandwidth; - - interval = (ctrl->dwFrameInterval > 100000) - ? ctrl->dwFrameInterval - : frame->dwFrameInterval[0]; - - /* Compute a bandwidth estimation by multiplying the frame - * size by the number of video frames per second, divide the - * result by the number of USB frames (or micro-frames for - * high-speed devices) per second and add the UVC header size - * (assumed to be 12 bytes long). - */ - bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp; - bandwidth *= 10000000 / interval + 1; - bandwidth /= 1000; - if (stream->dev->udev->speed == USB_SPEED_HIGH) - bandwidth /= 8; - bandwidth += 12; - - /* The bandwidth estimate is too low for many cameras. Don't use - * maximum packet sizes lower than 1024 bytes to try and work - * around the problem. According to measurements done on two - * different camera models, the value is high enough to get most - * resolutions working while not preventing two simultaneous - * VGA streams at 15 fps. - */ - bandwidth = max_t(u32, bandwidth, 1024); - - ctrl->dwMaxPayloadTransferSize = bandwidth; - } -} - -static int uvc_get_video_ctrl(struct uvc_streaming *stream, - struct uvc_streaming_control *ctrl, int probe, __u8 query) -{ - __u8 *data; - __u16 size; - int ret; - - size = stream->dev->uvc_version >= 0x0110 ? 34 : 26; - if ((stream->dev->quirks & UVC_QUIRK_PROBE_DEF) && - query == UVC_GET_DEF) - return -EIO; - - data = kmalloc(size, GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - ret = __uvc_query_ctrl(stream->dev, query, 0, stream->intfnum, - probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, - size, uvc_timeout_param); - - if ((query == UVC_GET_MIN || query == UVC_GET_MAX) && ret == 2) { - /* Some cameras, mostly based on Bison Electronics chipsets, - * answer a GET_MIN or GET_MAX request with the wCompQuality - * field only. - */ - uvc_warn_once(stream->dev, UVC_WARN_MINMAX, "UVC non " - "compliance - GET_MIN/MAX(PROBE) incorrectly " - "supported. Enabling workaround.\n"); - memset(ctrl, 0, sizeof *ctrl); - ctrl->wCompQuality = le16_to_cpup((__le16 *)data); - ret = 0; - goto out; - } else if (query == UVC_GET_DEF && probe == 1 && ret != size) { - /* Many cameras don't support the GET_DEF request on their - * video probe control. Warn once and return, the caller will - * fall back to GET_CUR. - */ - uvc_warn_once(stream->dev, UVC_WARN_PROBE_DEF, "UVC non " - "compliance - GET_DEF(PROBE) not supported. " - "Enabling workaround.\n"); - ret = -EIO; - goto out; - } else if (ret != size) { - uvc_printk(KERN_ERR, "Failed to query (%u) UVC %s control : " - "%d (exp. %u).\n", query, probe ? "probe" : "commit", - ret, size); - ret = -EIO; - goto out; - } - - ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]); - ctrl->bFormatIndex = data[2]; - ctrl->bFrameIndex = data[3]; - ctrl->dwFrameInterval = le32_to_cpup((__le32 *)&data[4]); - ctrl->wKeyFrameRate = le16_to_cpup((__le16 *)&data[8]); - ctrl->wPFrameRate = le16_to_cpup((__le16 *)&data[10]); - ctrl->wCompQuality = le16_to_cpup((__le16 *)&data[12]); - ctrl->wCompWindowSize = le16_to_cpup((__le16 *)&data[14]); - ctrl->wDelay = le16_to_cpup((__le16 *)&data[16]); - ctrl->dwMaxVideoFrameSize = get_unaligned_le32(&data[18]); - ctrl->dwMaxPayloadTransferSize = get_unaligned_le32(&data[22]); - - if (size == 34) { - ctrl->dwClockFrequency = get_unaligned_le32(&data[26]); - ctrl->bmFramingInfo = data[30]; - ctrl->bPreferedVersion = data[31]; - ctrl->bMinVersion = data[32]; - ctrl->bMaxVersion = data[33]; - } else { - ctrl->dwClockFrequency = stream->dev->clock_frequency; - ctrl->bmFramingInfo = 0; - ctrl->bPreferedVersion = 0; - ctrl->bMinVersion = 0; - ctrl->bMaxVersion = 0; - } - - /* Some broken devices return null or wrong dwMaxVideoFrameSize and - * dwMaxPayloadTransferSize fields. Try to get the value from the - * format and frame descriptors. - */ - uvc_fixup_video_ctrl(stream, ctrl); - ret = 0; - -out: - kfree(data); - return ret; -} - -static int uvc_set_video_ctrl(struct uvc_streaming *stream, - struct uvc_streaming_control *ctrl, int probe) -{ - __u8 *data; - __u16 size; - int ret; - - size = stream->dev->uvc_version >= 0x0110 ? 34 : 26; - data = kzalloc(size, GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - *(__le16 *)&data[0] = cpu_to_le16(ctrl->bmHint); - data[2] = ctrl->bFormatIndex; - data[3] = ctrl->bFrameIndex; - *(__le32 *)&data[4] = cpu_to_le32(ctrl->dwFrameInterval); - *(__le16 *)&data[8] = cpu_to_le16(ctrl->wKeyFrameRate); - *(__le16 *)&data[10] = cpu_to_le16(ctrl->wPFrameRate); - *(__le16 *)&data[12] = cpu_to_le16(ctrl->wCompQuality); - *(__le16 *)&data[14] = cpu_to_le16(ctrl->wCompWindowSize); - *(__le16 *)&data[16] = cpu_to_le16(ctrl->wDelay); - put_unaligned_le32(ctrl->dwMaxVideoFrameSize, &data[18]); - put_unaligned_le32(ctrl->dwMaxPayloadTransferSize, &data[22]); - - if (size == 34) { - put_unaligned_le32(ctrl->dwClockFrequency, &data[26]); - data[30] = ctrl->bmFramingInfo; - data[31] = ctrl->bPreferedVersion; - data[32] = ctrl->bMinVersion; - data[33] = ctrl->bMaxVersion; - } - - ret = __uvc_query_ctrl(stream->dev, UVC_SET_CUR, 0, stream->intfnum, - probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, - size, uvc_timeout_param); - if (ret != size) { - uvc_printk(KERN_ERR, "Failed to set UVC %s control : " - "%d (exp. %u).\n", probe ? "probe" : "commit", - ret, size); - ret = -EIO; - } - - kfree(data); - return ret; -} - -int uvc_probe_video(struct uvc_streaming *stream, - struct uvc_streaming_control *probe) -{ - struct uvc_streaming_control probe_min, probe_max; - __u16 bandwidth; - unsigned int i; - int ret; - - /* Perform probing. The device should adjust the requested values - * according to its capabilities. However, some devices, namely the - * first generation UVC Logitech webcams, don't implement the Video - * Probe control properly, and just return the needed bandwidth. For - * that reason, if the needed bandwidth exceeds the maximum available - * bandwidth, try to lower the quality. - */ - ret = uvc_set_video_ctrl(stream, probe, 1); - if (ret < 0) - goto done; - - /* Get the minimum and maximum values for compression settings. */ - if (!(stream->dev->quirks & UVC_QUIRK_PROBE_MINMAX)) { - ret = uvc_get_video_ctrl(stream, &probe_min, 1, UVC_GET_MIN); - if (ret < 0) - goto done; - ret = uvc_get_video_ctrl(stream, &probe_max, 1, UVC_GET_MAX); - if (ret < 0) - goto done; - - probe->wCompQuality = probe_max.wCompQuality; - } - - for (i = 0; i < 2; ++i) { - ret = uvc_set_video_ctrl(stream, probe, 1); - if (ret < 0) - goto done; - ret = uvc_get_video_ctrl(stream, probe, 1, UVC_GET_CUR); - if (ret < 0) - goto done; - - if (stream->intf->num_altsetting == 1) - break; - - bandwidth = probe->dwMaxPayloadTransferSize; - if (bandwidth <= stream->maxpsize) - break; - - if (stream->dev->quirks & UVC_QUIRK_PROBE_MINMAX) { - ret = -ENOSPC; - goto done; - } - - /* TODO: negotiate compression parameters */ - probe->wKeyFrameRate = probe_min.wKeyFrameRate; - probe->wPFrameRate = probe_min.wPFrameRate; - probe->wCompQuality = probe_max.wCompQuality; - probe->wCompWindowSize = probe_min.wCompWindowSize; - } - -done: - return ret; -} - -static int uvc_commit_video(struct uvc_streaming *stream, - struct uvc_streaming_control *probe) -{ - return uvc_set_video_ctrl(stream, probe, 0); -} - -/* ----------------------------------------------------------------------------- - * Clocks and timestamps - */ - -static void -uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf, - const __u8 *data, int len) -{ - struct uvc_clock_sample *sample; - unsigned int header_size; - bool has_pts = false; - bool has_scr = false; - unsigned long flags; - struct timespec ts; - u16 host_sof; - u16 dev_sof; - - switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) { - case UVC_STREAM_PTS | UVC_STREAM_SCR: - header_size = 12; - has_pts = true; - has_scr = true; - break; - case UVC_STREAM_PTS: - header_size = 6; - has_pts = true; - break; - case UVC_STREAM_SCR: - header_size = 8; - has_scr = true; - break; - default: - header_size = 2; - break; - } - - /* Check for invalid headers. */ - if (len < header_size) - return; - - /* Extract the timestamps: - * - * - store the frame PTS in the buffer structure - * - if the SCR field is present, retrieve the host SOF counter and - * kernel timestamps and store them with the SCR STC and SOF fields - * in the ring buffer - */ - if (has_pts && buf != NULL) - buf->pts = get_unaligned_le32(&data[2]); - - if (!has_scr) - return; - - /* To limit the amount of data, drop SCRs with an SOF identical to the - * previous one. - */ - dev_sof = get_unaligned_le16(&data[header_size - 2]); - if (dev_sof == stream->clock.last_sof) - return; - - stream->clock.last_sof = dev_sof; - - host_sof = usb_get_current_frame_number(stream->dev->udev); - ktime_get_ts(&ts); - - /* The UVC specification allows device implementations that can't obtain - * the USB frame number to keep their own frame counters as long as they - * match the size and frequency of the frame number associated with USB - * SOF tokens. The SOF values sent by such devices differ from the USB - * SOF tokens by a fixed offset that needs to be estimated and accounted - * for to make timestamp recovery as accurate as possible. - * - * The offset is estimated the first time a device SOF value is received - * as the difference between the host and device SOF values. As the two - * SOF values can differ slightly due to transmission delays, consider - * that the offset is null if the difference is not higher than 10 ms - * (negative differences can not happen and are thus considered as an - * offset). The video commit control wDelay field should be used to - * compute a dynamic threshold instead of using a fixed 10 ms value, but - * devices don't report reliable wDelay values. - * - * See uvc_video_clock_host_sof() for an explanation regarding why only - * the 8 LSBs of the delta are kept. - */ - if (stream->clock.sof_offset == (u16)-1) { - u16 delta_sof = (host_sof - dev_sof) & 255; - if (delta_sof >= 10) - stream->clock.sof_offset = delta_sof; - else - stream->clock.sof_offset = 0; - } - - dev_sof = (dev_sof + stream->clock.sof_offset) & 2047; - - spin_lock_irqsave(&stream->clock.lock, flags); - - sample = &stream->clock.samples[stream->clock.head]; - sample->dev_stc = get_unaligned_le32(&data[header_size - 6]); - sample->dev_sof = dev_sof; - sample->host_sof = host_sof; - sample->host_ts = ts; - - /* Update the sliding window head and count. */ - stream->clock.head = (stream->clock.head + 1) % stream->clock.size; - - if (stream->clock.count < stream->clock.size) - stream->clock.count++; - - spin_unlock_irqrestore(&stream->clock.lock, flags); -} - -static void uvc_video_clock_reset(struct uvc_streaming *stream) -{ - struct uvc_clock *clock = &stream->clock; - - clock->head = 0; - clock->count = 0; - clock->last_sof = -1; - clock->sof_offset = -1; -} - -static int uvc_video_clock_init(struct uvc_streaming *stream) -{ - struct uvc_clock *clock = &stream->clock; - - spin_lock_init(&clock->lock); - clock->size = 32; - - clock->samples = kmalloc(clock->size * sizeof(*clock->samples), - GFP_KERNEL); - if (clock->samples == NULL) - return -ENOMEM; - - uvc_video_clock_reset(stream); - - return 0; -} - -static void uvc_video_clock_cleanup(struct uvc_streaming *stream) -{ - kfree(stream->clock.samples); - stream->clock.samples = NULL; -} - -/* - * uvc_video_clock_host_sof - Return the host SOF value for a clock sample - * - * Host SOF counters reported by usb_get_current_frame_number() usually don't - * cover the whole 11-bits SOF range (0-2047) but are limited to the HCI frame - * schedule window. They can be limited to 8, 9 or 10 bits depending on the host - * controller and its configuration. - * - * We thus need to recover the SOF value corresponding to the host frame number. - * As the device and host frame numbers are sampled in a short interval, the - * difference between their values should be equal to a small delta plus an - * integer multiple of 256 caused by the host frame number limited precision. - * - * To obtain the recovered host SOF value, compute the small delta by masking - * the high bits of the host frame counter and device SOF difference and add it - * to the device SOF value. - */ -static u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample) -{ - /* The delta value can be negative. */ - s8 delta_sof; - - delta_sof = (sample->host_sof - sample->dev_sof) & 255; - - return (sample->dev_sof + delta_sof) & 2047; -} - -/* - * uvc_video_clock_update - Update the buffer timestamp - * - * This function converts the buffer PTS timestamp to the host clock domain by - * going through the USB SOF clock domain and stores the result in the V4L2 - * buffer timestamp field. - * - * The relationship between the device clock and the host clock isn't known. - * However, the device and the host share the common USB SOF clock which can be - * used to recover that relationship. - * - * The relationship between the device clock and the USB SOF clock is considered - * to be linear over the clock samples sliding window and is given by - * - * SOF = m * PTS + p - * - * Several methods to compute the slope (m) and intercept (p) can be used. As - * the clock drift should be small compared to the sliding window size, we - * assume that the line that goes through the points at both ends of the window - * is a good approximation. Naming those points P1 and P2, we get - * - * SOF = (SOF2 - SOF1) / (STC2 - STC1) * PTS - * + (SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1) - * - * or - * - * SOF = ((SOF2 - SOF1) * PTS + SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1) (1) - * - * to avoid loosing precision in the division. Similarly, the host timestamp is - * computed with - * - * TS = ((TS2 - TS1) * PTS + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1) (2) - * - * SOF values are coded on 11 bits by USB. We extend their precision with 16 - * decimal bits, leading to a 11.16 coding. - * - * TODO: To avoid surprises with device clock values, PTS/STC timestamps should - * be normalized using the nominal device clock frequency reported through the - * UVC descriptors. - * - * Both the PTS/STC and SOF counters roll over, after a fixed but device - * specific amount of time for PTS/STC and after 2048ms for SOF. As long as the - * sliding window size is smaller than the rollover period, differences computed - * on unsigned integers will produce the correct result. However, the p term in - * the linear relations will be miscomputed. - * - * To fix the issue, we subtract a constant from the PTS and STC values to bring - * PTS to half the 32 bit STC range. The sliding window STC values then fit into - * the 32 bit range without any rollover. - * - * Similarly, we add 2048 to the device SOF values to make sure that the SOF - * computed by (1) will never be smaller than 0. This offset is then compensated - * by adding 2048 to the SOF values used in (2). However, this doesn't prevent - * rollovers between (1) and (2): the SOF value computed by (1) can be slightly - * lower than 4096, and the host SOF counters can have rolled over to 2048. This - * case is handled by subtracting 2048 from the SOF value if it exceeds the host - * SOF value at the end of the sliding window. - * - * Finally we subtract a constant from the host timestamps to bring the first - * timestamp of the sliding window to 1s. - */ -void uvc_video_clock_update(struct uvc_streaming *stream, - struct v4l2_buffer *v4l2_buf, - struct uvc_buffer *buf) -{ - struct uvc_clock *clock = &stream->clock; - struct uvc_clock_sample *first; - struct uvc_clock_sample *last; - unsigned long flags; - struct timespec ts; - u32 delta_stc; - u32 y1, y2; - u32 x1, x2; - u32 mean; - u32 sof; - u32 div; - u32 rem; - u64 y; - - spin_lock_irqsave(&clock->lock, flags); - - if (clock->count < clock->size) - goto done; - - first = &clock->samples[clock->head]; - last = &clock->samples[(clock->head - 1) % clock->size]; - - /* First step, PTS to SOF conversion. */ - delta_stc = buf->pts - (1UL << 31); - x1 = first->dev_stc - delta_stc; - x2 = last->dev_stc - delta_stc; - if (x1 == x2) - goto done; - - y1 = (first->dev_sof + 2048) << 16; - y2 = (last->dev_sof + 2048) << 16; - if (y2 < y1) - y2 += 2048 << 16; - - y = (u64)(y2 - y1) * (1ULL << 31) + (u64)y1 * (u64)x2 - - (u64)y2 * (u64)x1; - y = div_u64(y, x2 - x1); - - sof = y; - - uvc_trace(UVC_TRACE_CLOCK, "%s: PTS %u y %llu.%06llu SOF %u.%06llu " - "(x1 %u x2 %u y1 %u y2 %u SOF offset %u)\n", - stream->dev->name, buf->pts, - y >> 16, div_u64((y & 0xffff) * 1000000, 65536), - sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536), - x1, x2, y1, y2, clock->sof_offset); - - /* Second step, SOF to host clock conversion. */ - x1 = (uvc_video_clock_host_sof(first) + 2048) << 16; - x2 = (uvc_video_clock_host_sof(last) + 2048) << 16; - if (x2 < x1) - x2 += 2048 << 16; - if (x1 == x2) - goto done; - - ts = timespec_sub(last->host_ts, first->host_ts); - y1 = NSEC_PER_SEC; - y2 = (ts.tv_sec + 1) * NSEC_PER_SEC + ts.tv_nsec; - - /* Interpolated and host SOF timestamps can wrap around at slightly - * different times. Handle this by adding or removing 2048 to or from - * the computed SOF value to keep it close to the SOF samples mean - * value. - */ - mean = (x1 + x2) / 2; - if (mean - (1024 << 16) > sof) - sof += 2048 << 16; - else if (sof > mean + (1024 << 16)) - sof -= 2048 << 16; - - y = (u64)(y2 - y1) * (u64)sof + (u64)y1 * (u64)x2 - - (u64)y2 * (u64)x1; - y = div_u64(y, x2 - x1); - - div = div_u64_rem(y, NSEC_PER_SEC, &rem); - ts.tv_sec = first->host_ts.tv_sec - 1 + div; - ts.tv_nsec = first->host_ts.tv_nsec + rem; - if (ts.tv_nsec >= NSEC_PER_SEC) { - ts.tv_sec++; - ts.tv_nsec -= NSEC_PER_SEC; - } - - uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %lu.%06lu " - "buf ts %lu.%06lu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %u)\n", - stream->dev->name, - sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536), - y, ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC, - v4l2_buf->timestamp.tv_sec, v4l2_buf->timestamp.tv_usec, - x1, first->host_sof, first->dev_sof, - x2, last->host_sof, last->dev_sof, y1, y2); - - /* Update the V4L2 buffer. */ - v4l2_buf->timestamp.tv_sec = ts.tv_sec; - v4l2_buf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC; - -done: - spin_unlock_irqrestore(&stream->clock.lock, flags); -} - -/* ------------------------------------------------------------------------ - * Stream statistics - */ - -static void uvc_video_stats_decode(struct uvc_streaming *stream, - const __u8 *data, int len) -{ - unsigned int header_size; - bool has_pts = false; - bool has_scr = false; - u16 uninitialized_var(scr_sof); - u32 uninitialized_var(scr_stc); - u32 uninitialized_var(pts); - - if (stream->stats.stream.nb_frames == 0 && - stream->stats.frame.nb_packets == 0) - ktime_get_ts(&stream->stats.stream.start_ts); - - switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) { - case UVC_STREAM_PTS | UVC_STREAM_SCR: - header_size = 12; - has_pts = true; - has_scr = true; - break; - case UVC_STREAM_PTS: - header_size = 6; - has_pts = true; - break; - case UVC_STREAM_SCR: - header_size = 8; - has_scr = true; - break; - default: - header_size = 2; - break; - } - - /* Check for invalid headers. */ - if (len < header_size || data[0] < header_size) { - stream->stats.frame.nb_invalid++; - return; - } - - /* Extract the timestamps. */ - if (has_pts) - pts = get_unaligned_le32(&data[2]); - - if (has_scr) { - scr_stc = get_unaligned_le32(&data[header_size - 6]); - scr_sof = get_unaligned_le16(&data[header_size - 2]); - } - - /* Is PTS constant through the whole frame ? */ - if (has_pts && stream->stats.frame.nb_pts) { - if (stream->stats.frame.pts != pts) { - stream->stats.frame.nb_pts_diffs++; - stream->stats.frame.last_pts_diff = - stream->stats.frame.nb_packets; - } - } - - if (has_pts) { - stream->stats.frame.nb_pts++; - stream->stats.frame.pts = pts; - } - - /* Do all frames have a PTS in their first non-empty packet, or before - * their first empty packet ? - */ - if (stream->stats.frame.size == 0) { - if (len > header_size) - stream->stats.frame.has_initial_pts = has_pts; - if (len == header_size && has_pts) - stream->stats.frame.has_early_pts = true; - } - - /* Do the SCR.STC and SCR.SOF fields vary through the frame ? */ - if (has_scr && stream->stats.frame.nb_scr) { - if (stream->stats.frame.scr_stc != scr_stc) - stream->stats.frame.nb_scr_diffs++; - } - - if (has_scr) { - /* Expand the SOF counter to 32 bits and store its value. */ - if (stream->stats.stream.nb_frames > 0 || - stream->stats.frame.nb_scr > 0) - stream->stats.stream.scr_sof_count += - (scr_sof - stream->stats.stream.scr_sof) % 2048; - stream->stats.stream.scr_sof = scr_sof; - - stream->stats.frame.nb_scr++; - stream->stats.frame.scr_stc = scr_stc; - stream->stats.frame.scr_sof = scr_sof; - - if (scr_sof < stream->stats.stream.min_sof) - stream->stats.stream.min_sof = scr_sof; - if (scr_sof > stream->stats.stream.max_sof) - stream->stats.stream.max_sof = scr_sof; - } - - /* Record the first non-empty packet number. */ - if (stream->stats.frame.size == 0 && len > header_size) - stream->stats.frame.first_data = stream->stats.frame.nb_packets; - - /* Update the frame size. */ - stream->stats.frame.size += len - header_size; - - /* Update the packets counters. */ - stream->stats.frame.nb_packets++; - if (len > header_size) - stream->stats.frame.nb_empty++; - - if (data[1] & UVC_STREAM_ERR) - stream->stats.frame.nb_errors++; -} - -static void uvc_video_stats_update(struct uvc_streaming *stream) -{ - struct uvc_stats_frame *frame = &stream->stats.frame; - - uvc_trace(UVC_TRACE_STATS, "frame %u stats: %u/%u/%u packets, " - "%u/%u/%u pts (%searly %sinitial), %u/%u scr, " - "last pts/stc/sof %u/%u/%u\n", - stream->sequence, frame->first_data, - frame->nb_packets - frame->nb_empty, frame->nb_packets, - frame->nb_pts_diffs, frame->last_pts_diff, frame->nb_pts, - frame->has_early_pts ? "" : "!", - frame->has_initial_pts ? "" : "!", - frame->nb_scr_diffs, frame->nb_scr, - frame->pts, frame->scr_stc, frame->scr_sof); - - stream->stats.stream.nb_frames++; - stream->stats.stream.nb_packets += stream->stats.frame.nb_packets; - stream->stats.stream.nb_empty += stream->stats.frame.nb_empty; - stream->stats.stream.nb_errors += stream->stats.frame.nb_errors; - stream->stats.stream.nb_invalid += stream->stats.frame.nb_invalid; - - if (frame->has_early_pts) - stream->stats.stream.nb_pts_early++; - if (frame->has_initial_pts) - stream->stats.stream.nb_pts_initial++; - if (frame->last_pts_diff <= frame->first_data) - stream->stats.stream.nb_pts_constant++; - if (frame->nb_scr >= frame->nb_packets - frame->nb_empty) - stream->stats.stream.nb_scr_count_ok++; - if (frame->nb_scr_diffs + 1 == frame->nb_scr) - stream->stats.stream.nb_scr_diffs_ok++; - - memset(&stream->stats.frame, 0, sizeof(stream->stats.frame)); -} - -size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf, - size_t size) -{ - unsigned int scr_sof_freq; - unsigned int duration; - struct timespec ts; - size_t count = 0; - - ts.tv_sec = stream->stats.stream.stop_ts.tv_sec - - stream->stats.stream.start_ts.tv_sec; - ts.tv_nsec = stream->stats.stream.stop_ts.tv_nsec - - stream->stats.stream.start_ts.tv_nsec; - if (ts.tv_nsec < 0) { - ts.tv_sec--; - ts.tv_nsec += 1000000000; - } - - /* Compute the SCR.SOF frequency estimate. At the nominal 1kHz SOF - * frequency this will not overflow before more than 1h. - */ - duration = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; - if (duration != 0) - scr_sof_freq = stream->stats.stream.scr_sof_count * 1000 - / duration; - else - scr_sof_freq = 0; - - count += scnprintf(buf + count, size - count, - "frames: %u\npackets: %u\nempty: %u\n" - "errors: %u\ninvalid: %u\n", - stream->stats.stream.nb_frames, - stream->stats.stream.nb_packets, - stream->stats.stream.nb_empty, - stream->stats.stream.nb_errors, - stream->stats.stream.nb_invalid); - count += scnprintf(buf + count, size - count, - "pts: %u early, %u initial, %u ok\n", - stream->stats.stream.nb_pts_early, - stream->stats.stream.nb_pts_initial, - stream->stats.stream.nb_pts_constant); - count += scnprintf(buf + count, size - count, - "scr: %u count ok, %u diff ok\n", - stream->stats.stream.nb_scr_count_ok, - stream->stats.stream.nb_scr_diffs_ok); - count += scnprintf(buf + count, size - count, - "sof: %u <= sof <= %u, freq %u.%03u kHz\n", - stream->stats.stream.min_sof, - stream->stats.stream.max_sof, - scr_sof_freq / 1000, scr_sof_freq % 1000); - - return count; -} - -static void uvc_video_stats_start(struct uvc_streaming *stream) -{ - memset(&stream->stats, 0, sizeof(stream->stats)); - stream->stats.stream.min_sof = 2048; -} - -static void uvc_video_stats_stop(struct uvc_streaming *stream) -{ - ktime_get_ts(&stream->stats.stream.stop_ts); -} - -/* ------------------------------------------------------------------------ - * Video codecs - */ - -/* Video payload decoding is handled by uvc_video_decode_start(), - * uvc_video_decode_data() and uvc_video_decode_end(). - * - * uvc_video_decode_start is called with URB data at the start of a bulk or - * isochronous payload. It processes header data and returns the header size - * in bytes if successful. If an error occurs, it returns a negative error - * code. The following error codes have special meanings. - * - * - EAGAIN informs the caller that the current video buffer should be marked - * as done, and that the function should be called again with the same data - * and a new video buffer. This is used when end of frame conditions can be - * reliably detected at the beginning of the next frame only. - * - * If an error other than -EAGAIN is returned, the caller will drop the current - * payload. No call to uvc_video_decode_data and uvc_video_decode_end will be - * made until the next payload. -ENODATA can be used to drop the current - * payload if no other error code is appropriate. - * - * uvc_video_decode_data is called for every URB with URB data. It copies the - * data to the video buffer. - * - * uvc_video_decode_end is called with header data at the end of a bulk or - * isochronous payload. It performs any additional header data processing and - * returns 0 or a negative error code if an error occurred. As header data have - * already been processed by uvc_video_decode_start, this functions isn't - * required to perform sanity checks a second time. - * - * For isochronous transfers where a payload is always transferred in a single - * URB, the three functions will be called in a row. - * - * To let the decoder process header data and update its internal state even - * when no video buffer is available, uvc_video_decode_start must be prepared - * to be called with a NULL buf parameter. uvc_video_decode_data and - * uvc_video_decode_end will never be called with a NULL buffer. - */ -static int uvc_video_decode_start(struct uvc_streaming *stream, - struct uvc_buffer *buf, const __u8 *data, int len) -{ - __u8 fid; - - /* Sanity checks: - * - packet must be at least 2 bytes long - * - bHeaderLength value must be at least 2 bytes (see above) - * - bHeaderLength value can't be larger than the packet size. - */ - if (len < 2 || data[0] < 2 || data[0] > len) { - stream->stats.frame.nb_invalid++; - return -EINVAL; - } - - fid = data[1] & UVC_STREAM_FID; - - /* Increase the sequence number regardless of any buffer states, so - * that discontinuous sequence numbers always indicate lost frames. - */ - if (stream->last_fid != fid) { - stream->sequence++; - if (stream->sequence) - uvc_video_stats_update(stream); - } - - uvc_video_clock_decode(stream, buf, data, len); - uvc_video_stats_decode(stream, data, len); - - /* Store the payload FID bit and return immediately when the buffer is - * NULL. - */ - if (buf == NULL) { - stream->last_fid = fid; - return -ENODATA; - } - - /* Mark the buffer as bad if the error bit is set. */ - if (data[1] & UVC_STREAM_ERR) { - uvc_trace(UVC_TRACE_FRAME, "Marking buffer as bad (error bit " - "set).\n"); - buf->error = 1; - } - - /* Synchronize to the input stream by waiting for the FID bit to be - * toggled when the the buffer state is not UVC_BUF_STATE_ACTIVE. - * stream->last_fid is initialized to -1, so the first isochronous - * frame will always be in sync. - * - * If the device doesn't toggle the FID bit, invert stream->last_fid - * when the EOF bit is set to force synchronisation on the next packet. - */ - if (buf->state != UVC_BUF_STATE_ACTIVE) { - struct timespec ts; - - if (fid == stream->last_fid) { - uvc_trace(UVC_TRACE_FRAME, "Dropping payload (out of " - "sync).\n"); - if ((stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) && - (data[1] & UVC_STREAM_EOF)) - stream->last_fid ^= UVC_STREAM_FID; - return -ENODATA; - } - - if (uvc_clock_param == CLOCK_MONOTONIC) - ktime_get_ts(&ts); - else - ktime_get_real_ts(&ts); - - buf->buf.v4l2_buf.sequence = stream->sequence; - buf->buf.v4l2_buf.timestamp.tv_sec = ts.tv_sec; - buf->buf.v4l2_buf.timestamp.tv_usec = - ts.tv_nsec / NSEC_PER_USEC; - - /* TODO: Handle PTS and SCR. */ - buf->state = UVC_BUF_STATE_ACTIVE; - } - - /* Mark the buffer as done if we're at the beginning of a new frame. - * End of frame detection is better implemented by checking the EOF - * bit (FID bit toggling is delayed by one frame compared to the EOF - * bit), but some devices don't set the bit at end of frame (and the - * last payload can be lost anyway). We thus must check if the FID has - * been toggled. - * - * stream->last_fid is initialized to -1, so the first isochronous - * frame will never trigger an end of frame detection. - * - * Empty buffers (bytesused == 0) don't trigger end of frame detection - * as it doesn't make sense to return an empty buffer. This also - * avoids detecting end of frame conditions at FID toggling if the - * previous payload had the EOF bit set. - */ - if (fid != stream->last_fid && buf->bytesused != 0) { - uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit " - "toggled).\n"); - buf->state = UVC_BUF_STATE_READY; - return -EAGAIN; - } - - stream->last_fid = fid; - - return data[0]; -} - -static void uvc_video_decode_data(struct uvc_streaming *stream, - struct uvc_buffer *buf, const __u8 *data, int len) -{ - unsigned int maxlen, nbytes; - void *mem; - - if (len <= 0) - return; - - /* Copy the video data to the buffer. */ - maxlen = buf->length - buf->bytesused; - mem = buf->mem + buf->bytesused; - nbytes = min((unsigned int)len, maxlen); - memcpy(mem, data, nbytes); - buf->bytesused += nbytes; - - /* Complete the current frame if the buffer size was exceeded. */ - if (len > maxlen) { - uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n"); - buf->state = UVC_BUF_STATE_READY; - } -} - -static void uvc_video_decode_end(struct uvc_streaming *stream, - struct uvc_buffer *buf, const __u8 *data, int len) -{ - /* Mark the buffer as done if the EOF marker is set. */ - if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) { - uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); - if (data[0] == len) - uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n"); - buf->state = UVC_BUF_STATE_READY; - if (stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) - stream->last_fid ^= UVC_STREAM_FID; - } -} - -/* Video payload encoding is handled by uvc_video_encode_header() and - * uvc_video_encode_data(). Only bulk transfers are currently supported. - * - * uvc_video_encode_header is called at the start of a payload. It adds header - * data to the transfer buffer and returns the header size. As the only known - * UVC output device transfers a whole frame in a single payload, the EOF bit - * is always set in the header. - * - * uvc_video_encode_data is called for every URB and copies the data from the - * video buffer to the transfer buffer. - */ -static int uvc_video_encode_header(struct uvc_streaming *stream, - struct uvc_buffer *buf, __u8 *data, int len) -{ - data[0] = 2; /* Header length */ - data[1] = UVC_STREAM_EOH | UVC_STREAM_EOF - | (stream->last_fid & UVC_STREAM_FID); - return 2; -} - -static int uvc_video_encode_data(struct uvc_streaming *stream, - struct uvc_buffer *buf, __u8 *data, int len) -{ - struct uvc_video_queue *queue = &stream->queue; - unsigned int nbytes; - void *mem; - - /* Copy video data to the URB buffer. */ - mem = buf->mem + queue->buf_used; - nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used); - nbytes = min(stream->bulk.max_payload_size - stream->bulk.payload_size, - nbytes); - memcpy(data, mem, nbytes); - - queue->buf_used += nbytes; - - return nbytes; -} - -/* ------------------------------------------------------------------------ - * URB handling - */ - -/* - * Completion handler for video URBs. - */ -static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream, - struct uvc_buffer *buf) -{ - u8 *mem; - int ret, i; - - for (i = 0; i < urb->number_of_packets; ++i) { - if (urb->iso_frame_desc[i].status < 0) { - uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame " - "lost (%d).\n", urb->iso_frame_desc[i].status); - /* Mark the buffer as faulty. */ - if (buf != NULL) - buf->error = 1; - continue; - } - - /* Decode the payload header. */ - mem = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - do { - ret = uvc_video_decode_start(stream, buf, mem, - urb->iso_frame_desc[i].actual_length); - if (ret == -EAGAIN) - buf = uvc_queue_next_buffer(&stream->queue, - buf); - } while (ret == -EAGAIN); - - if (ret < 0) - continue; - - /* Decode the payload data. */ - uvc_video_decode_data(stream, buf, mem + ret, - urb->iso_frame_desc[i].actual_length - ret); - - /* Process the header again. */ - uvc_video_decode_end(stream, buf, mem, - urb->iso_frame_desc[i].actual_length); - - if (buf->state == UVC_BUF_STATE_READY) { - if (buf->length != buf->bytesused && - !(stream->cur_format->flags & - UVC_FMT_FLAG_COMPRESSED)) - buf->error = 1; - - buf = uvc_queue_next_buffer(&stream->queue, buf); - } - } -} - -static void uvc_video_decode_bulk(struct urb *urb, struct uvc_streaming *stream, - struct uvc_buffer *buf) -{ - u8 *mem; - int len, ret; - - /* - * Ignore ZLPs if they're not part of a frame, otherwise process them - * to trigger the end of payload detection. - */ - if (urb->actual_length == 0 && stream->bulk.header_size == 0) - return; - - mem = urb->transfer_buffer; - len = urb->actual_length; - stream->bulk.payload_size += len; - - /* If the URB is the first of its payload, decode and save the - * header. - */ - if (stream->bulk.header_size == 0 && !stream->bulk.skip_payload) { - do { - ret = uvc_video_decode_start(stream, buf, mem, len); - if (ret == -EAGAIN) - buf = uvc_queue_next_buffer(&stream->queue, - buf); - } while (ret == -EAGAIN); - - /* If an error occurred skip the rest of the payload. */ - if (ret < 0 || buf == NULL) { - stream->bulk.skip_payload = 1; - } else { - memcpy(stream->bulk.header, mem, ret); - stream->bulk.header_size = ret; - - mem += ret; - len -= ret; - } - } - - /* The buffer queue might have been cancelled while a bulk transfer - * was in progress, so we can reach here with buf equal to NULL. Make - * sure buf is never dereferenced if NULL. - */ - - /* Process video data. */ - if (!stream->bulk.skip_payload && buf != NULL) - uvc_video_decode_data(stream, buf, mem, len); - - /* Detect the payload end by a URB smaller than the maximum size (or - * a payload size equal to the maximum) and process the header again. - */ - if (urb->actual_length < urb->transfer_buffer_length || - stream->bulk.payload_size >= stream->bulk.max_payload_size) { - if (!stream->bulk.skip_payload && buf != NULL) { - uvc_video_decode_end(stream, buf, stream->bulk.header, - stream->bulk.payload_size); - if (buf->state == UVC_BUF_STATE_READY) - buf = uvc_queue_next_buffer(&stream->queue, - buf); - } - - stream->bulk.header_size = 0; - stream->bulk.skip_payload = 0; - stream->bulk.payload_size = 0; - } -} - -static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream, - struct uvc_buffer *buf) -{ - u8 *mem = urb->transfer_buffer; - int len = stream->urb_size, ret; - - if (buf == NULL) { - urb->transfer_buffer_length = 0; - return; - } - - /* If the URB is the first of its payload, add the header. */ - if (stream->bulk.header_size == 0) { - ret = uvc_video_encode_header(stream, buf, mem, len); - stream->bulk.header_size = ret; - stream->bulk.payload_size += ret; - mem += ret; - len -= ret; - } - - /* Process video data. */ - ret = uvc_video_encode_data(stream, buf, mem, len); - - stream->bulk.payload_size += ret; - len -= ret; - - if (buf->bytesused == stream->queue.buf_used || - stream->bulk.payload_size == stream->bulk.max_payload_size) { - if (buf->bytesused == stream->queue.buf_used) { - stream->queue.buf_used = 0; - buf->state = UVC_BUF_STATE_READY; - buf->buf.v4l2_buf.sequence = ++stream->sequence; - uvc_queue_next_buffer(&stream->queue, buf); - stream->last_fid ^= UVC_STREAM_FID; - } - - stream->bulk.header_size = 0; - stream->bulk.payload_size = 0; - } - - urb->transfer_buffer_length = stream->urb_size - len; -} - -static void uvc_video_complete(struct urb *urb) -{ - struct uvc_streaming *stream = urb->context; - struct uvc_video_queue *queue = &stream->queue; - struct uvc_buffer *buf = NULL; - unsigned long flags; - int ret; - - switch (urb->status) { - case 0: - break; - - default: - uvc_printk(KERN_WARNING, "Non-zero status (%d) in video " - "completion handler.\n", urb->status); - - case -ENOENT: /* usb_kill_urb() called. */ - if (stream->frozen) - return; - - case -ECONNRESET: /* usb_unlink_urb() called. */ - case -ESHUTDOWN: /* The endpoint is being disabled. */ - uvc_queue_cancel(queue, urb->status == -ESHUTDOWN); - return; - } - - spin_lock_irqsave(&queue->irqlock, flags); - if (!list_empty(&queue->irqqueue)) - buf = list_first_entry(&queue->irqqueue, struct uvc_buffer, - queue); - spin_unlock_irqrestore(&queue->irqlock, flags); - - stream->decode(urb, stream, buf); - - if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { - uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n", - ret); - } -} - -/* - * Free transfer buffers. - */ -static void uvc_free_urb_buffers(struct uvc_streaming *stream) -{ - unsigned int i; - - for (i = 0; i < UVC_URBS; ++i) { - if (stream->urb_buffer[i]) { -#ifndef CONFIG_DMA_NONCOHERENT - usb_free_coherent(stream->dev->udev, stream->urb_size, - stream->urb_buffer[i], stream->urb_dma[i]); -#else - kfree(stream->urb_buffer[i]); -#endif - stream->urb_buffer[i] = NULL; - } - } - - stream->urb_size = 0; -} - -/* - * Allocate transfer buffers. This function can be called with buffers - * already allocated when resuming from suspend, in which case it will - * return without touching the buffers. - * - * Limit the buffer size to UVC_MAX_PACKETS bulk/isochronous packets. If the - * system is too low on memory try successively smaller numbers of packets - * until allocation succeeds. - * - * Return the number of allocated packets on success or 0 when out of memory. - */ -static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, - unsigned int size, unsigned int psize, gfp_t gfp_flags) -{ - unsigned int npackets; - unsigned int i; - - /* Buffers are already allocated, bail out. */ - if (stream->urb_size) - return stream->urb_size / psize; - - /* Compute the number of packets. Bulk endpoints might transfer UVC - * payloads across multiple URBs. - */ - npackets = DIV_ROUND_UP(size, psize); - if (npackets > UVC_MAX_PACKETS) - npackets = UVC_MAX_PACKETS; - - /* Retry allocations until one succeed. */ - for (; npackets > 1; npackets /= 2) { - for (i = 0; i < UVC_URBS; ++i) { - stream->urb_size = psize * npackets; -#ifndef CONFIG_DMA_NONCOHERENT - stream->urb_buffer[i] = usb_alloc_coherent( - stream->dev->udev, stream->urb_size, - gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]); -#else - stream->urb_buffer[i] = - kmalloc(stream->urb_size, gfp_flags | __GFP_NOWARN); -#endif - if (!stream->urb_buffer[i]) { - uvc_free_urb_buffers(stream); - break; - } - } - - if (i == UVC_URBS) { - uvc_trace(UVC_TRACE_VIDEO, "Allocated %u URB buffers " - "of %ux%u bytes each.\n", UVC_URBS, npackets, - psize); - return npackets; - } - } - - uvc_trace(UVC_TRACE_VIDEO, "Failed to allocate URB buffers (%u bytes " - "per packet).\n", psize); - return 0; -} - -/* - * Uninitialize isochronous/bulk URBs and free transfer buffers. - */ -static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) -{ - struct urb *urb; - unsigned int i; - - uvc_video_stats_stop(stream); - - for (i = 0; i < UVC_URBS; ++i) { - urb = stream->urb[i]; - if (urb == NULL) - continue; - - usb_kill_urb(urb); - usb_free_urb(urb); - stream->urb[i] = NULL; - } - - if (free_buffers) - uvc_free_urb_buffers(stream); -} - -/* - * Compute the maximum number of bytes per interval for an endpoint. - */ -static unsigned int uvc_endpoint_max_bpi(struct usb_device *dev, - struct usb_host_endpoint *ep) -{ - u16 psize; - - switch (dev->speed) { - case USB_SPEED_SUPER: - return ep->ss_ep_comp.wBytesPerInterval; - case USB_SPEED_HIGH: - psize = usb_endpoint_maxp(&ep->desc); - return (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); - default: - psize = usb_endpoint_maxp(&ep->desc); - return psize & 0x07ff; - } -} - -/* - * Initialize isochronous URBs and allocate transfer buffers. The packet size - * is given by the endpoint. - */ -static int uvc_init_video_isoc(struct uvc_streaming *stream, - struct usb_host_endpoint *ep, gfp_t gfp_flags) -{ - struct urb *urb; - unsigned int npackets, i, j; - u16 psize; - u32 size; - - psize = uvc_endpoint_max_bpi(stream->dev->udev, ep); - size = stream->ctrl.dwMaxVideoFrameSize; - - npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags); - if (npackets == 0) - return -ENOMEM; - - size = npackets * psize; - - for (i = 0; i < UVC_URBS; ++i) { - urb = usb_alloc_urb(npackets, gfp_flags); - if (urb == NULL) { - uvc_uninit_video(stream, 1); - return -ENOMEM; - } - - urb->dev = stream->dev->udev; - urb->context = stream; - urb->pipe = usb_rcvisocpipe(stream->dev->udev, - ep->desc.bEndpointAddress); -#ifndef CONFIG_DMA_NONCOHERENT - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; - urb->transfer_dma = stream->urb_dma[i]; -#else - urb->transfer_flags = URB_ISO_ASAP; -#endif - urb->interval = ep->desc.bInterval; - urb->transfer_buffer = stream->urb_buffer[i]; - urb->complete = uvc_video_complete; - urb->number_of_packets = npackets; - urb->transfer_buffer_length = size; - - for (j = 0; j < npackets; ++j) { - urb->iso_frame_desc[j].offset = j * psize; - urb->iso_frame_desc[j].length = psize; - } - - stream->urb[i] = urb; - } - - return 0; -} - -/* - * Initialize bulk URBs and allocate transfer buffers. The packet size is - * given by the endpoint. - */ -static int uvc_init_video_bulk(struct uvc_streaming *stream, - struct usb_host_endpoint *ep, gfp_t gfp_flags) -{ - struct urb *urb; - unsigned int npackets, pipe, i; - u16 psize; - u32 size; - - psize = usb_endpoint_maxp(&ep->desc) & 0x7ff; - size = stream->ctrl.dwMaxPayloadTransferSize; - stream->bulk.max_payload_size = size; - - npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags); - if (npackets == 0) - return -ENOMEM; - - size = npackets * psize; - - if (usb_endpoint_dir_in(&ep->desc)) - pipe = usb_rcvbulkpipe(stream->dev->udev, - ep->desc.bEndpointAddress); - else - pipe = usb_sndbulkpipe(stream->dev->udev, - ep->desc.bEndpointAddress); - - if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) - size = 0; - - for (i = 0; i < UVC_URBS; ++i) { - urb = usb_alloc_urb(0, gfp_flags); - if (urb == NULL) { - uvc_uninit_video(stream, 1); - return -ENOMEM; - } - - usb_fill_bulk_urb(urb, stream->dev->udev, pipe, - stream->urb_buffer[i], size, uvc_video_complete, - stream); -#ifndef CONFIG_DMA_NONCOHERENT - urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; - urb->transfer_dma = stream->urb_dma[i]; -#endif - - stream->urb[i] = urb; - } - - return 0; -} - -/* - * Initialize isochronous/bulk URBs and allocate transfer buffers. - */ -static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) -{ - struct usb_interface *intf = stream->intf; - struct usb_host_endpoint *ep; - unsigned int i; - int ret; - - stream->sequence = -1; - stream->last_fid = -1; - stream->bulk.header_size = 0; - stream->bulk.skip_payload = 0; - stream->bulk.payload_size = 0; - - uvc_video_stats_start(stream); - - if (intf->num_altsetting > 1) { - struct usb_host_endpoint *best_ep = NULL; - unsigned int best_psize = UINT_MAX; - unsigned int bandwidth; - unsigned int uninitialized_var(altsetting); - int intfnum = stream->intfnum; - - /* Isochronous endpoint, select the alternate setting. */ - bandwidth = stream->ctrl.dwMaxPayloadTransferSize; - - if (bandwidth == 0) { - uvc_trace(UVC_TRACE_VIDEO, "Device requested null " - "bandwidth, defaulting to lowest.\n"); - bandwidth = 1; - } else { - uvc_trace(UVC_TRACE_VIDEO, "Device requested %u " - "B/frame bandwidth.\n", bandwidth); - } - - for (i = 0; i < intf->num_altsetting; ++i) { - struct usb_host_interface *alts; - unsigned int psize; - - alts = &intf->altsetting[i]; - ep = uvc_find_endpoint(alts, - stream->header.bEndpointAddress); - if (ep == NULL) - continue; - - /* Check if the bandwidth is high enough. */ - psize = uvc_endpoint_max_bpi(stream->dev->udev, ep); - if (psize >= bandwidth && psize <= best_psize) { - altsetting = alts->desc.bAlternateSetting; - best_psize = psize; - best_ep = ep; - } - } - - if (best_ep == NULL) { - uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting " - "for requested bandwidth.\n"); - return -EIO; - } - - uvc_trace(UVC_TRACE_VIDEO, "Selecting alternate setting %u " - "(%u B/frame bandwidth).\n", altsetting, best_psize); - - ret = usb_set_interface(stream->dev->udev, intfnum, altsetting); - if (ret < 0) - return ret; - - ret = uvc_init_video_isoc(stream, best_ep, gfp_flags); - } else { - /* Bulk endpoint, proceed to URB initialization. */ - ep = uvc_find_endpoint(&intf->altsetting[0], - stream->header.bEndpointAddress); - if (ep == NULL) - return -EIO; - - ret = uvc_init_video_bulk(stream, ep, gfp_flags); - } - - if (ret < 0) - return ret; - - /* Submit the URBs. */ - for (i = 0; i < UVC_URBS; ++i) { - ret = usb_submit_urb(stream->urb[i], gfp_flags); - if (ret < 0) { - uvc_printk(KERN_ERR, "Failed to submit URB %u " - "(%d).\n", i, ret); - uvc_uninit_video(stream, 1); - return ret; - } - } - - return 0; -} - -/* -------------------------------------------------------------------------- - * Suspend/resume - */ - -/* - * Stop streaming without disabling the video queue. - * - * To let userspace applications resume without trouble, we must not touch the - * video buffers in any way. We mark the device as frozen to make sure the URB - * completion handler won't try to cancel the queue when we kill the URBs. - */ -int uvc_video_suspend(struct uvc_streaming *stream) -{ - if (!uvc_queue_streaming(&stream->queue)) - return 0; - - stream->frozen = 1; - uvc_uninit_video(stream, 0); - usb_set_interface(stream->dev->udev, stream->intfnum, 0); - return 0; -} - -/* - * Reconfigure the video interface and restart streaming if it was enabled - * before suspend. - * - * If an error occurs, disable the video queue. This will wake all pending - * buffers, making sure userspace applications are notified of the problem - * instead of waiting forever. - */ -int uvc_video_resume(struct uvc_streaming *stream, int reset) -{ - int ret; - - /* If the bus has been reset on resume, set the alternate setting to 0. - * This should be the default value, but some devices crash or otherwise - * misbehave if they don't receive a SET_INTERFACE request before any - * other video control request. - */ - if (reset) - usb_set_interface(stream->dev->udev, stream->intfnum, 0); - - stream->frozen = 0; - - uvc_video_clock_reset(stream); - - ret = uvc_commit_video(stream, &stream->ctrl); - if (ret < 0) { - uvc_queue_enable(&stream->queue, 0); - return ret; - } - - if (!uvc_queue_streaming(&stream->queue)) - return 0; - - ret = uvc_init_video(stream, GFP_NOIO); - if (ret < 0) - uvc_queue_enable(&stream->queue, 0); - - return ret; -} - -/* ------------------------------------------------------------------------ - * Video device - */ - -/* - * Initialize the UVC video device by switching to alternate setting 0 and - * retrieve the default format. - * - * Some cameras (namely the Fuji Finepix) set the format and frame - * indexes to zero. The UVC standard doesn't clearly make this a spec - * violation, so try to silently fix the values if possible. - * - * This function is called before registering the device with V4L. - */ -int uvc_video_init(struct uvc_streaming *stream) -{ - struct uvc_streaming_control *probe = &stream->ctrl; - struct uvc_format *format = NULL; - struct uvc_frame *frame = NULL; - unsigned int i; - int ret; - - if (stream->nformats == 0) { - uvc_printk(KERN_INFO, "No supported video formats found.\n"); - return -EINVAL; - } - - atomic_set(&stream->active, 0); - - /* Initialize the video buffers queue. */ - uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param); - - /* Alternate setting 0 should be the default, yet the XBox Live Vision - * Cam (and possibly other devices) crash or otherwise misbehave if - * they don't receive a SET_INTERFACE request before any other video - * control request. - */ - usb_set_interface(stream->dev->udev, stream->intfnum, 0); - - /* Set the streaming probe control with default streaming parameters - * retrieved from the device. Webcams that don't suport GET_DEF - * requests on the probe control will just keep their current streaming - * parameters. - */ - if (uvc_get_video_ctrl(stream, probe, 1, UVC_GET_DEF) == 0) - uvc_set_video_ctrl(stream, probe, 1); - - /* Initialize the streaming parameters with the probe control current - * value. This makes sure SET_CUR requests on the streaming commit - * control will always use values retrieved from a successful GET_CUR - * request on the probe control, as required by the UVC specification. - */ - ret = uvc_get_video_ctrl(stream, probe, 1, UVC_GET_CUR); - if (ret < 0) - return ret; - - /* Check if the default format descriptor exists. Use the first - * available format otherwise. - */ - for (i = stream->nformats; i > 0; --i) { - format = &stream->format[i-1]; - if (format->index == probe->bFormatIndex) - break; - } - - if (format->nframes == 0) { - uvc_printk(KERN_INFO, "No frame descriptor found for the " - "default format.\n"); - return -EINVAL; - } - - /* Zero bFrameIndex might be correct. Stream-based formats (including - * MPEG-2 TS and DV) do not support frames but have a dummy frame - * descriptor with bFrameIndex set to zero. If the default frame - * descriptor is not found, use the first available frame. - */ - for (i = format->nframes; i > 0; --i) { - frame = &format->frame[i-1]; - if (frame->bFrameIndex == probe->bFrameIndex) - break; - } - - probe->bFormatIndex = format->index; - probe->bFrameIndex = frame->bFrameIndex; - - stream->cur_format = format; - stream->cur_frame = frame; - - /* Select the video decoding function */ - if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (stream->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT) - stream->decode = uvc_video_decode_isight; - else if (stream->intf->num_altsetting > 1) - stream->decode = uvc_video_decode_isoc; - else - stream->decode = uvc_video_decode_bulk; - } else { - if (stream->intf->num_altsetting == 1) - stream->decode = uvc_video_encode_bulk; - else { - uvc_printk(KERN_INFO, "Isochronous endpoints are not " - "supported for video output devices.\n"); - return -EINVAL; - } - } - - return 0; -} - -/* - * Enable or disable the video stream. - */ -int uvc_video_enable(struct uvc_streaming *stream, int enable) -{ - int ret; - - if (!enable) { - uvc_uninit_video(stream, 1); - usb_set_interface(stream->dev->udev, stream->intfnum, 0); - uvc_queue_enable(&stream->queue, 0); - uvc_video_clock_cleanup(stream); - return 0; - } - - ret = uvc_video_clock_init(stream); - if (ret < 0) - return ret; - - ret = uvc_queue_enable(&stream->queue, 1); - if (ret < 0) - goto error_queue; - - /* Commit the streaming parameters. */ - ret = uvc_commit_video(stream, &stream->ctrl); - if (ret < 0) - goto error_commit; - - ret = uvc_init_video(stream, GFP_KERNEL); - if (ret < 0) - goto error_video; - - return 0; - -error_video: - usb_set_interface(stream->dev->udev, stream->intfnum, 0); -error_commit: - uvc_queue_enable(&stream->queue, 0); -error_queue: - uvc_video_clock_cleanup(stream); - - return ret; -} diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h deleted file mode 100644 index 3764040475bb..000000000000 --- a/drivers/media/video/uvc/uvcvideo.h +++ /dev/null @@ -1,718 +0,0 @@ -#ifndef _USB_VIDEO_H_ -#define _USB_VIDEO_H_ - -#ifndef __KERNEL__ -#error "The uvcvideo.h header is deprecated, use linux/uvcvideo.h instead." -#endif /* __KERNEL__ */ - -#include <linux/kernel.h> -#include <linux/poll.h> -#include <linux/usb.h> -#include <linux/usb/video.h> -#include <linux/uvcvideo.h> -#include <linux/videodev2.h> -#include <media/media-device.h> -#include <media/v4l2-device.h> -#include <media/v4l2-event.h> -#include <media/v4l2-fh.h> -#include <media/videobuf2-core.h> - -/* -------------------------------------------------------------------------- - * UVC constants - */ - -#define UVC_TERM_INPUT 0x0000 -#define UVC_TERM_OUTPUT 0x8000 -#define UVC_TERM_DIRECTION(term) ((term)->type & 0x8000) - -#define UVC_ENTITY_TYPE(entity) ((entity)->type & 0x7fff) -#define UVC_ENTITY_IS_UNIT(entity) (((entity)->type & 0xff00) == 0) -#define UVC_ENTITY_IS_TERM(entity) (((entity)->type & 0xff00) != 0) -#define UVC_ENTITY_IS_ITERM(entity) \ - (UVC_ENTITY_IS_TERM(entity) && \ - ((entity)->type & 0x8000) == UVC_TERM_INPUT) -#define UVC_ENTITY_IS_OTERM(entity) \ - (UVC_ENTITY_IS_TERM(entity) && \ - ((entity)->type & 0x8000) == UVC_TERM_OUTPUT) - - -/* ------------------------------------------------------------------------ - * GUIDs - */ -#define UVC_GUID_UVC_CAMERA \ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01} -#define UVC_GUID_UVC_OUTPUT \ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02} -#define UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT \ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03} -#define UVC_GUID_UVC_PROCESSING \ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01} -#define UVC_GUID_UVC_SELECTOR \ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02} - -#define UVC_GUID_FORMAT_MJPEG \ - { 'M', 'J', 'P', 'G', 0x00, 0x00, 0x10, 0x00, \ - 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -#define UVC_GUID_FORMAT_YUY2 \ - { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, \ - 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -#define UVC_GUID_FORMAT_YUY2_ISIGHT \ - { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, \ - 0x80, 0x00, 0x00, 0x00, 0x00, 0x38, 0x9b, 0x71} -#define UVC_GUID_FORMAT_NV12 \ - { 'N', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, \ - 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -#define UVC_GUID_FORMAT_YV12 \ - { 'Y', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, \ - 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -#define UVC_GUID_FORMAT_I420 \ - { 'I', '4', '2', '0', 0x00, 0x00, 0x10, 0x00, \ - 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -#define UVC_GUID_FORMAT_UYVY \ - { 'U', 'Y', 'V', 'Y', 0x00, 0x00, 0x10, 0x00, \ - 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -#define UVC_GUID_FORMAT_Y800 \ - { 'Y', '8', '0', '0', 0x00, 0x00, 0x10, 0x00, \ - 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -#define UVC_GUID_FORMAT_Y8 \ - { 'Y', '8', ' ', ' ', 0x00, 0x00, 0x10, 0x00, \ - 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -#define UVC_GUID_FORMAT_Y10 \ - { 'Y', '1', '0', ' ', 0x00, 0x00, 0x10, 0x00, \ - 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -#define UVC_GUID_FORMAT_Y12 \ - { 'Y', '1', '2', ' ', 0x00, 0x00, 0x10, 0x00, \ - 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -#define UVC_GUID_FORMAT_Y16 \ - { 'Y', '1', '6', ' ', 0x00, 0x00, 0x10, 0x00, \ - 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -#define UVC_GUID_FORMAT_BY8 \ - { 'B', 'Y', '8', ' ', 0x00, 0x00, 0x10, 0x00, \ - 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -#define UVC_GUID_FORMAT_RGBP \ - { 'R', 'G', 'B', 'P', 0x00, 0x00, 0x10, 0x00, \ - 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} -#define UVC_GUID_FORMAT_M420 \ - { 'M', '4', '2', '0', 0x00, 0x00, 0x10, 0x00, \ - 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} - -#define UVC_GUID_FORMAT_H264 \ - { 'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00, \ - 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} - -/* ------------------------------------------------------------------------ - * Driver specific constants. - */ - -#define DRIVER_VERSION "1.1.1" - -/* Number of isochronous URBs. */ -#define UVC_URBS 5 -/* Maximum number of packets per URB. */ -#define UVC_MAX_PACKETS 32 -/* Maximum number of video buffers. */ -#define UVC_MAX_VIDEO_BUFFERS 32 -/* Maximum status buffer size in bytes of interrupt URB. */ -#define UVC_MAX_STATUS_SIZE 16 - -#define UVC_CTRL_CONTROL_TIMEOUT 300 -#define UVC_CTRL_STREAMING_TIMEOUT 5000 - -/* Maximum allowed number of control mappings per device */ -#define UVC_MAX_CONTROL_MAPPINGS 1024 -#define UVC_MAX_CONTROL_MENU_ENTRIES 32 - -/* Devices quirks */ -#define UVC_QUIRK_STATUS_INTERVAL 0x00000001 -#define UVC_QUIRK_PROBE_MINMAX 0x00000002 -#define UVC_QUIRK_PROBE_EXTRAFIELDS 0x00000004 -#define UVC_QUIRK_BUILTIN_ISIGHT 0x00000008 -#define UVC_QUIRK_STREAM_NO_FID 0x00000010 -#define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020 -#define UVC_QUIRK_FIX_BANDWIDTH 0x00000080 -#define UVC_QUIRK_PROBE_DEF 0x00000100 -#define UVC_QUIRK_RESTRICT_FRAME_RATE 0x00000200 - -/* Format flags */ -#define UVC_FMT_FLAG_COMPRESSED 0x00000001 -#define UVC_FMT_FLAG_STREAM 0x00000002 - -/* ------------------------------------------------------------------------ - * Structures. - */ - -struct uvc_device; - -/* TODO: Put the most frequently accessed fields at the beginning of - * structures to maximize cache efficiency. - */ -struct uvc_control_info { - struct list_head mappings; - - __u8 entity[16]; - __u8 index; /* Bit index in bmControls */ - __u8 selector; - - __u16 size; - __u32 flags; -}; - -struct uvc_control_mapping { - struct list_head list; - struct list_head ev_subs; - - __u32 id; - __u8 name[32]; - __u8 entity[16]; - __u8 selector; - - __u8 size; - __u8 offset; - enum v4l2_ctrl_type v4l2_type; - __u32 data_type; - - struct uvc_menu_info *menu_info; - __u32 menu_count; - - __u32 master_id; - __s32 master_manual; - __u32 slave_ids[2]; - - __s32 (*get) (struct uvc_control_mapping *mapping, __u8 query, - const __u8 *data); - void (*set) (struct uvc_control_mapping *mapping, __s32 value, - __u8 *data); -}; - -struct uvc_control { - struct uvc_entity *entity; - struct uvc_control_info info; - - __u8 index; /* Used to match the uvc_control entry with a - uvc_control_info. */ - __u8 dirty:1, - loaded:1, - modified:1, - cached:1, - initialized:1; - - __u8 *uvc_data; -}; - -struct uvc_format_desc { - char *name; - __u8 guid[16]; - __u32 fcc; -}; - -/* The term 'entity' refers to both UVC units and UVC terminals. - * - * The type field is either the terminal type (wTerminalType in the terminal - * descriptor), or the unit type (bDescriptorSubtype in the unit descriptor). - * As the bDescriptorSubtype field is one byte long, the type value will - * always have a null MSB for units. All terminal types defined by the UVC - * specification have a non-null MSB, so it is safe to use the MSB to - * differentiate between units and terminals as long as the descriptor parsing - * code makes sure terminal types have a non-null MSB. - * - * For terminals, the type's most significant bit stores the terminal - * direction (either UVC_TERM_INPUT or UVC_TERM_OUTPUT). The type field should - * always be accessed with the UVC_ENTITY_* macros and never directly. - */ - -struct uvc_entity { - struct list_head list; /* Entity as part of a UVC device. */ - struct list_head chain; /* Entity as part of a video device - * chain. */ - __u8 id; - __u16 type; - char name[64]; - - /* Media controller-related fields. */ - struct video_device *vdev; - struct v4l2_subdev subdev; - unsigned int num_pads; - unsigned int num_links; - struct media_pad *pads; - - union { - struct { - __u16 wObjectiveFocalLengthMin; - __u16 wObjectiveFocalLengthMax; - __u16 wOcularFocalLength; - __u8 bControlSize; - __u8 *bmControls; - } camera; - - struct { - __u8 bControlSize; - __u8 *bmControls; - __u8 bTransportModeSize; - __u8 *bmTransportModes; - } media; - - struct { - } output; - - struct { - __u16 wMaxMultiplier; - __u8 bControlSize; - __u8 *bmControls; - __u8 bmVideoStandards; - } processing; - - struct { - } selector; - - struct { - __u8 guidExtensionCode[16]; - __u8 bNumControls; - __u8 bControlSize; - __u8 *bmControls; - __u8 *bmControlsType; - } extension; - }; - - __u8 bNrInPins; - __u8 *baSourceID; - - unsigned int ncontrols; - struct uvc_control *controls; -}; - -struct uvc_frame { - __u8 bFrameIndex; - __u8 bmCapabilities; - __u16 wWidth; - __u16 wHeight; - __u32 dwMinBitRate; - __u32 dwMaxBitRate; - __u32 dwMaxVideoFrameBufferSize; - __u8 bFrameIntervalType; - __u32 dwDefaultFrameInterval; - __u32 *dwFrameInterval; -}; - -struct uvc_format { - __u8 type; - __u8 index; - __u8 bpp; - __u8 colorspace; - __u32 fcc; - __u32 flags; - - char name[32]; - - unsigned int nframes; - struct uvc_frame *frame; -}; - -struct uvc_streaming_header { - __u8 bNumFormats; - __u8 bEndpointAddress; - __u8 bTerminalLink; - __u8 bControlSize; - __u8 *bmaControls; - /* The following fields are used by input headers only. */ - __u8 bmInfo; - __u8 bStillCaptureMethod; - __u8 bTriggerSupport; - __u8 bTriggerUsage; -}; - -enum uvc_buffer_state { - UVC_BUF_STATE_IDLE = 0, - UVC_BUF_STATE_QUEUED = 1, - UVC_BUF_STATE_ACTIVE = 2, - UVC_BUF_STATE_READY = 3, - UVC_BUF_STATE_DONE = 4, - UVC_BUF_STATE_ERROR = 5, -}; - -struct uvc_buffer { - struct vb2_buffer buf; - struct list_head queue; - - enum uvc_buffer_state state; - unsigned int error; - - void *mem; - unsigned int length; - unsigned int bytesused; - - u32 pts; -}; - -#define UVC_QUEUE_DISCONNECTED (1 << 0) -#define UVC_QUEUE_DROP_CORRUPTED (1 << 1) - -struct uvc_video_queue { - struct vb2_queue queue; - struct mutex mutex; /* Protects queue */ - - unsigned int flags; - unsigned int buf_used; - - spinlock_t irqlock; /* Protects irqqueue */ - struct list_head irqqueue; -}; - -struct uvc_video_chain { - struct uvc_device *dev; - struct list_head list; - - struct list_head entities; /* All entities */ - struct uvc_entity *processing; /* Processing unit */ - struct uvc_entity *selector; /* Selector unit */ - - struct mutex ctrl_mutex; /* Protects ctrl.info */ -}; - -struct uvc_stats_frame { - unsigned int size; /* Number of bytes captured */ - unsigned int first_data; /* Index of the first non-empty packet */ - - unsigned int nb_packets; /* Number of packets */ - unsigned int nb_empty; /* Number of empty packets */ - unsigned int nb_invalid; /* Number of packets with an invalid header */ - unsigned int nb_errors; /* Number of packets with the error bit set */ - - unsigned int nb_pts; /* Number of packets with a PTS timestamp */ - unsigned int nb_pts_diffs; /* Number of PTS differences inside a frame */ - unsigned int last_pts_diff; /* Index of the last PTS difference */ - bool has_initial_pts; /* Whether the first non-empty packet has a PTS */ - bool has_early_pts; /* Whether a PTS is present before the first non-empty packet */ - u32 pts; /* PTS of the last packet */ - - unsigned int nb_scr; /* Number of packets with a SCR timestamp */ - unsigned int nb_scr_diffs; /* Number of SCR.STC differences inside a frame */ - u16 scr_sof; /* SCR.SOF of the last packet */ - u32 scr_stc; /* SCR.STC of the last packet */ -}; - -struct uvc_stats_stream { - struct timespec start_ts; /* Stream start timestamp */ - struct timespec stop_ts; /* Stream stop timestamp */ - - unsigned int nb_frames; /* Number of frames */ - - unsigned int nb_packets; /* Number of packets */ - unsigned int nb_empty; /* Number of empty packets */ - unsigned int nb_invalid; /* Number of packets with an invalid header */ - unsigned int nb_errors; /* Number of packets with the error bit set */ - - unsigned int nb_pts_constant; /* Number of frames with constant PTS */ - unsigned int nb_pts_early; /* Number of frames with early PTS */ - unsigned int nb_pts_initial; /* Number of frames with initial PTS */ - - unsigned int nb_scr_count_ok; /* Number of frames with at least one SCR per non empty packet */ - unsigned int nb_scr_diffs_ok; /* Number of frames with varying SCR.STC */ - unsigned int scr_sof_count; /* STC.SOF counter accumulated since stream start */ - unsigned int scr_sof; /* STC.SOF of the last packet */ - unsigned int min_sof; /* Minimum STC.SOF value */ - unsigned int max_sof; /* Maximum STC.SOF value */ -}; - -struct uvc_streaming { - struct list_head list; - struct uvc_device *dev; - struct video_device *vdev; - struct uvc_video_chain *chain; - atomic_t active; - - struct usb_interface *intf; - int intfnum; - __u16 maxpsize; - - struct uvc_streaming_header header; - enum v4l2_buf_type type; - - unsigned int nformats; - struct uvc_format *format; - - struct uvc_streaming_control ctrl; - struct uvc_format *cur_format; - struct uvc_frame *cur_frame; - /* Protect access to ctrl, cur_format, cur_frame and hardware video - * probe control. - */ - struct mutex mutex; - - /* Buffers queue. */ - unsigned int frozen : 1; - struct uvc_video_queue queue; - void (*decode) (struct urb *urb, struct uvc_streaming *video, - struct uvc_buffer *buf); - - /* Context data used by the bulk completion handler. */ - struct { - __u8 header[256]; - unsigned int header_size; - int skip_payload; - __u32 payload_size; - __u32 max_payload_size; - } bulk; - - struct urb *urb[UVC_URBS]; - char *urb_buffer[UVC_URBS]; - dma_addr_t urb_dma[UVC_URBS]; - unsigned int urb_size; - - __u32 sequence; - __u8 last_fid; - - /* debugfs */ - struct dentry *debugfs_dir; - struct { - struct uvc_stats_frame frame; - struct uvc_stats_stream stream; - } stats; - - /* Timestamps support. */ - struct uvc_clock { - struct uvc_clock_sample { - u32 dev_stc; - u16 dev_sof; - struct timespec host_ts; - u16 host_sof; - } *samples; - - unsigned int head; - unsigned int count; - unsigned int size; - - u16 last_sof; - u16 sof_offset; - - spinlock_t lock; - } clock; -}; - -enum uvc_device_state { - UVC_DEV_DISCONNECTED = 1, -}; - -struct uvc_device { - struct usb_device *udev; - struct usb_interface *intf; - unsigned long warnings; - __u32 quirks; - int intfnum; - char name[32]; - - enum uvc_device_state state; - atomic_t users; - atomic_t nmappings; - - /* Video control interface */ -#ifdef CONFIG_MEDIA_CONTROLLER - struct media_device mdev; -#endif - struct v4l2_device vdev; - __u16 uvc_version; - __u32 clock_frequency; - - struct list_head entities; - struct list_head chains; - - /* Video Streaming interfaces */ - struct list_head streams; - atomic_t nstreams; - - /* Status Interrupt Endpoint */ - struct usb_host_endpoint *int_ep; - struct urb *int_urb; - __u8 *status; - struct input_dev *input; - char input_phys[64]; -}; - -enum uvc_handle_state { - UVC_HANDLE_PASSIVE = 0, - UVC_HANDLE_ACTIVE = 1, -}; - -struct uvc_fh { - struct v4l2_fh vfh; - struct uvc_video_chain *chain; - struct uvc_streaming *stream; - enum uvc_handle_state state; -}; - -struct uvc_driver { - struct usb_driver driver; -}; - -/* ------------------------------------------------------------------------ - * Debugging, printing and logging - */ - -#define UVC_TRACE_PROBE (1 << 0) -#define UVC_TRACE_DESCR (1 << 1) -#define UVC_TRACE_CONTROL (1 << 2) -#define UVC_TRACE_FORMAT (1 << 3) -#define UVC_TRACE_CAPTURE (1 << 4) -#define UVC_TRACE_CALLS (1 << 5) -#define UVC_TRACE_IOCTL (1 << 6) -#define UVC_TRACE_FRAME (1 << 7) -#define UVC_TRACE_SUSPEND (1 << 8) -#define UVC_TRACE_STATUS (1 << 9) -#define UVC_TRACE_VIDEO (1 << 10) -#define UVC_TRACE_STATS (1 << 11) -#define UVC_TRACE_CLOCK (1 << 12) - -#define UVC_WARN_MINMAX 0 -#define UVC_WARN_PROBE_DEF 1 -#define UVC_WARN_XU_GET_RES 2 - -extern unsigned int uvc_clock_param; -extern unsigned int uvc_no_drop_param; -extern unsigned int uvc_trace_param; -extern unsigned int uvc_timeout_param; - -#define uvc_trace(flag, msg...) \ - do { \ - if (uvc_trace_param & flag) \ - printk(KERN_DEBUG "uvcvideo: " msg); \ - } while (0) - -#define uvc_warn_once(dev, warn, msg...) \ - do { \ - if (!test_and_set_bit(warn, &dev->warnings)) \ - printk(KERN_INFO "uvcvideo: " msg); \ - } while (0) - -#define uvc_printk(level, msg...) \ - printk(level "uvcvideo: " msg) - -/* -------------------------------------------------------------------------- - * Internal functions. - */ - -/* Core driver */ -extern struct uvc_driver uvc_driver; - -extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id); - -/* Video buffers queue management. */ -extern void uvc_queue_init(struct uvc_video_queue *queue, - enum v4l2_buf_type type, int drop_corrupted); -extern int uvc_alloc_buffers(struct uvc_video_queue *queue, - struct v4l2_requestbuffers *rb); -extern void uvc_free_buffers(struct uvc_video_queue *queue); -extern int uvc_query_buffer(struct uvc_video_queue *queue, - struct v4l2_buffer *v4l2_buf); -extern int uvc_queue_buffer(struct uvc_video_queue *queue, - struct v4l2_buffer *v4l2_buf); -extern int uvc_dequeue_buffer(struct uvc_video_queue *queue, - struct v4l2_buffer *v4l2_buf, int nonblocking); -extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable); -extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect); -extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, - struct uvc_buffer *buf); -extern int uvc_queue_mmap(struct uvc_video_queue *queue, - struct vm_area_struct *vma); -extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, - struct file *file, poll_table *wait); -#ifndef CONFIG_MMU -extern unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, - unsigned long pgoff); -#endif -extern int uvc_queue_allocated(struct uvc_video_queue *queue); -static inline int uvc_queue_streaming(struct uvc_video_queue *queue) -{ - return vb2_is_streaming(&queue->queue); -} - -/* V4L2 interface */ -extern const struct v4l2_file_operations uvc_fops; - -/* Media controller */ -extern int uvc_mc_register_entities(struct uvc_video_chain *chain); -extern void uvc_mc_cleanup_entity(struct uvc_entity *entity); - -/* Video */ -extern int uvc_video_init(struct uvc_streaming *stream); -extern int uvc_video_suspend(struct uvc_streaming *stream); -extern int uvc_video_resume(struct uvc_streaming *stream, int reset); -extern int uvc_video_enable(struct uvc_streaming *stream, int enable); -extern int uvc_probe_video(struct uvc_streaming *stream, - struct uvc_streaming_control *probe); -extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, - __u8 intfnum, __u8 cs, void *data, __u16 size); -void uvc_video_clock_update(struct uvc_streaming *stream, - struct v4l2_buffer *v4l2_buf, - struct uvc_buffer *buf); - -/* Status */ -extern int uvc_status_init(struct uvc_device *dev); -extern void uvc_status_cleanup(struct uvc_device *dev); -extern int uvc_status_start(struct uvc_device *dev); -extern void uvc_status_stop(struct uvc_device *dev); -extern int uvc_status_suspend(struct uvc_device *dev); -extern int uvc_status_resume(struct uvc_device *dev); - -/* Controls */ -extern const struct v4l2_subscribed_event_ops uvc_ctrl_sub_ev_ops; - -extern int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, - struct v4l2_queryctrl *v4l2_ctrl); -extern int uvc_query_v4l2_menu(struct uvc_video_chain *chain, - struct v4l2_querymenu *query_menu); - -extern int uvc_ctrl_add_mapping(struct uvc_video_chain *chain, - const struct uvc_control_mapping *mapping); -extern int uvc_ctrl_init_device(struct uvc_device *dev); -extern void uvc_ctrl_cleanup_device(struct uvc_device *dev); -extern int uvc_ctrl_resume_device(struct uvc_device *dev); - -extern int uvc_ctrl_begin(struct uvc_video_chain *chain); -extern int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback, - const struct v4l2_ext_control *xctrls, - unsigned int xctrls_count); -static inline int uvc_ctrl_commit(struct uvc_fh *handle, - const struct v4l2_ext_control *xctrls, - unsigned int xctrls_count) -{ - return __uvc_ctrl_commit(handle, 0, xctrls, xctrls_count); -} -static inline int uvc_ctrl_rollback(struct uvc_fh *handle) -{ - return __uvc_ctrl_commit(handle, 1, NULL, 0); -} - -extern int uvc_ctrl_get(struct uvc_video_chain *chain, - struct v4l2_ext_control *xctrl); -extern int uvc_ctrl_set(struct uvc_video_chain *chain, - struct v4l2_ext_control *xctrl); - -extern int uvc_xu_ctrl_query(struct uvc_video_chain *chain, - struct uvc_xu_control_query *xqry); - -/* Utility functions */ -extern void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator, - unsigned int n_terms, unsigned int threshold); -extern uint32_t uvc_fraction_to_interval(uint32_t numerator, - uint32_t denominator); -extern struct usb_host_endpoint *uvc_find_endpoint( - struct usb_host_interface *alts, __u8 epaddr); - -/* Quirks support */ -void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream, - struct uvc_buffer *buf); - -/* debugfs and statistics */ -int uvc_debugfs_init(void); -void uvc_debugfs_cleanup(void); -int uvc_debugfs_init_stream(struct uvc_streaming *stream); -void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream); - -size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf, - size_t size); - -#endif |