diff options
Diffstat (limited to 'drivers/media/video/gspca/sq930x.c')
-rw-r--r-- | drivers/media/video/gspca/sq930x.c | 1164 |
1 files changed, 0 insertions, 1164 deletions
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); |