brintos

brintos / linux-shallow public Read only

0
0
Text · 31.3 KiB · c361024 Raw
1157 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * SQ930x subdriver4 *5 * Copyright (C) 2010 Jean-François Moine <http://moinejf.free.fr>6 * Copyright (C) 2006 -2008 Gerard Klaver <gerard at gkall dot hobby dot nl>7 * Copyright (C) 2007 Sam Revitch <samr7@cs.washington.edu>8 */9 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt11 12#define MODULE_NAME "sq930x"13 14#include "gspca.h"15 16MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>\n"17		"Gerard Klaver <gerard at gkall dot hobby dot nl\n"18		"Sam Revitch <samr7@cs.washington.edu>");19MODULE_DESCRIPTION("GSPCA/SQ930x USB Camera Driver");20MODULE_LICENSE("GPL");21 22/* Structure to hold all of our device specific stuff */23struct sd {24	struct gspca_dev gspca_dev;	/* !! must be the first item */25 26	struct { /* exposure/gain control cluster */27		struct v4l2_ctrl *exposure;28		struct v4l2_ctrl *gain;29	};30 31	u8 do_ctrl;32	u8 gpio[2];33	u8 sensor;34	u8 type;35#define Generic 036#define Creative_live_motion 137};38enum sensors {39	SENSOR_ICX098BQ,40	SENSOR_LZ24BP,41	SENSOR_MI0360,42	SENSOR_MT9V111,		/* = MI360SOC */43	SENSOR_OV7660,44	SENSOR_OV9630,45};46 47static struct v4l2_pix_format vga_mode[] = {48	{320, 240, V4L2_PIX_FMT_SRGGB8, V4L2_FIELD_NONE,49		.bytesperline = 320,50		.sizeimage = 320 * 240,51		.colorspace = V4L2_COLORSPACE_SRGB,52		.priv = 0},53	{640, 480, V4L2_PIX_FMT_SRGGB8, V4L2_FIELD_NONE,54		.bytesperline = 640,55		.sizeimage = 640 * 480,56		.colorspace = V4L2_COLORSPACE_SRGB,57		.priv = 1},58};59 60/* sq930x registers */61#define SQ930_CTRL_UCBUS_IO	0x000162#define SQ930_CTRL_I2C_IO	0x000263#define SQ930_CTRL_GPIO		0x000564#define SQ930_CTRL_CAP_START	0x001065#define SQ930_CTRL_CAP_STOP	0x001166#define SQ930_CTRL_SET_EXPOSURE 0x001d67#define SQ930_CTRL_RESET	0x001e68#define SQ930_CTRL_GET_DEV_INFO 0x001f69 70/* gpio 1 (8..15) */71#define SQ930_GPIO_DFL_I2C_SDA	0x000172#define SQ930_GPIO_DFL_I2C_SCL	0x000273#define SQ930_GPIO_RSTBAR	0x000474#define SQ930_GPIO_EXTRA1	0x004075#define SQ930_GPIO_EXTRA2	0x008076/* gpio 3 (24..31) */77#define SQ930_GPIO_POWER	0x020078#define SQ930_GPIO_DFL_LED	0x100079 80struct ucbus_write_cmd {81	u16	bw_addr;82	u8	bw_data;83};84struct i2c_write_cmd {85	u8	reg;86	u16	val;87};88 89static const struct ucbus_write_cmd icx098bq_start_0[] = {90	{0x0354, 0x00}, {0x03fa, 0x00}, {0xf800, 0x02}, {0xf801, 0xce},91	{0xf802, 0xc1}, {0xf804, 0x00}, {0xf808, 0x00}, {0xf809, 0x0e},92	{0xf80a, 0x01}, {0xf80b, 0xee}, {0xf807, 0x60}, {0xf80c, 0x02},93	{0xf80d, 0xf0}, {0xf80e, 0x03}, {0xf80f, 0x0a}, {0xf81c, 0x02},94	{0xf81d, 0xf0}, {0xf81e, 0x03}, {0xf81f, 0x0a}, {0xf83a, 0x00},95	{0xf83b, 0x10}, {0xf83c, 0x00}, {0xf83d, 0x4e}, {0xf810, 0x04},96	{0xf811, 0x00}, {0xf812, 0x02}, {0xf813, 0x10}, {0xf803, 0x00},97	{0xf814, 0x01}, {0xf815, 0x18}, {0xf816, 0x00}, {0xf817, 0x48},98	{0xf818, 0x00}, {0xf819, 0x25}, {0xf81a, 0x00}, {0xf81b, 0x3c},99	{0xf82f, 0x03}, {0xf820, 0xff}, {0xf821, 0x0d}, {0xf822, 0xff},100	{0xf823, 0x07}, {0xf824, 0xff}, {0xf825, 0x03}, {0xf826, 0xff},101	{0xf827, 0x06}, {0xf828, 0xff}, {0xf829, 0x03}, {0xf82a, 0xff},102	{0xf82b, 0x0c}, {0xf82c, 0xfd}, {0xf82d, 0x01}, {0xf82e, 0x00},103	{0xf830, 0x00}, {0xf831, 0x47}, {0xf832, 0x00}, {0xf833, 0x00},104	{0xf850, 0x00}, {0xf851, 0x00}, {0xf852, 0x00}, {0xf853, 0x24},105	{0xf854, 0x00}, {0xf855, 0x18}, {0xf856, 0x00}, {0xf857, 0x3c},106	{0xf858, 0x00}, {0xf859, 0x0c}, {0xf85a, 0x00}, {0xf85b, 0x30},107	{0xf85c, 0x00}, {0xf85d, 0x0c}, {0xf85e, 0x00}, {0xf85f, 0x30},108	{0xf860, 0x00}, {0xf861, 0x48}, {0xf862, 0x01}, {0xf863, 0xdc},109	{0xf864, 0xff}, {0xf865, 0x98}, {0xf866, 0xff}, {0xf867, 0xc0},110	{0xf868, 0xff}, {0xf869, 0x70}, {0xf86c, 0xff}, {0xf86d, 0x00},111	{0xf86a, 0xff}, {0xf86b, 0x48}, {0xf86e, 0xff}, {0xf86f, 0x00},112	{0xf870, 0x01}, {0xf871, 0xdb}, {0xf872, 0x01}, {0xf873, 0xfa},113	{0xf874, 0x01}, {0xf875, 0xdb}, {0xf876, 0x01}, {0xf877, 0xfa},114	{0xf878, 0x0f}, {0xf879, 0x0f}, {0xf87a, 0xff}, {0xf87b, 0xff},115	{0xf800, 0x03}116};117static const struct ucbus_write_cmd icx098bq_start_1[] = {118	{0xf5f0, 0x00}, {0xf5f1, 0xcd}, {0xf5f2, 0x80}, {0xf5f3, 0x80},119	{0xf5f4, 0xc0},120	{0xf5f0, 0x49}, {0xf5f1, 0xcd}, {0xf5f2, 0x80}, {0xf5f3, 0x80},121	{0xf5f4, 0xc0},122	{0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},123	{0xf5f9, 0x00}124};125 126static const struct ucbus_write_cmd icx098bq_start_2[] = {127	{0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x82}, {0xf806, 0x00},128	{0xf807, 0x7f}, {0xf800, 0x03},129	{0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x40}, {0xf806, 0x00},130	{0xf807, 0x7f}, {0xf800, 0x03},131	{0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0xcf}, {0xf806, 0xd0},132	{0xf807, 0x7f}, {0xf800, 0x03},133	{0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x00}, {0xf806, 0x00},134	{0xf807, 0x7f}, {0xf800, 0x03}135};136 137static const struct ucbus_write_cmd lz24bp_start_0[] = {138	{0x0354, 0x00}, {0x03fa, 0x00}, {0xf800, 0x02}, {0xf801, 0xbe},139	{0xf802, 0xc6}, {0xf804, 0x00}, {0xf808, 0x00}, {0xf809, 0x06},140	{0xf80a, 0x01}, {0xf80b, 0xfe}, {0xf807, 0x84}, {0xf80c, 0x02},141	{0xf80d, 0xf7}, {0xf80e, 0x03}, {0xf80f, 0x0b}, {0xf81c, 0x00},142	{0xf81d, 0x49}, {0xf81e, 0x03}, {0xf81f, 0x0b}, {0xf83a, 0x00},143	{0xf83b, 0x01}, {0xf83c, 0x00}, {0xf83d, 0x6b}, {0xf810, 0x03},144	{0xf811, 0x10}, {0xf812, 0x02}, {0xf813, 0x6f}, {0xf803, 0x00},145	{0xf814, 0x00}, {0xf815, 0x44}, {0xf816, 0x00}, {0xf817, 0x48},146	{0xf818, 0x00}, {0xf819, 0x25}, {0xf81a, 0x00}, {0xf81b, 0x3c},147	{0xf82f, 0x03}, {0xf820, 0xff}, {0xf821, 0x0d}, {0xf822, 0xff},148	{0xf823, 0x07}, {0xf824, 0xfd}, {0xf825, 0x07}, {0xf826, 0xf0},149	{0xf827, 0x0c}, {0xf828, 0xff}, {0xf829, 0x03}, {0xf82a, 0xff},150	{0xf82b, 0x0c}, {0xf82c, 0xfc}, {0xf82d, 0x01}, {0xf82e, 0x00},151	{0xf830, 0x00}, {0xf831, 0x47}, {0xf832, 0x00}, {0xf833, 0x00},152	{0xf850, 0x00}, {0xf851, 0x00}, {0xf852, 0x00}, {0xf853, 0x24},153	{0xf854, 0x00}, {0xf855, 0x0c}, {0xf856, 0x00}, {0xf857, 0x30},154	{0xf858, 0x00}, {0xf859, 0x18}, {0xf85a, 0x00}, {0xf85b, 0x3c},155	{0xf85c, 0x00}, {0xf85d, 0x18}, {0xf85e, 0x00}, {0xf85f, 0x3c},156	{0xf860, 0xff}, {0xf861, 0x37}, {0xf862, 0xff}, {0xf863, 0x1d},157	{0xf864, 0xff}, {0xf865, 0x98}, {0xf866, 0xff}, {0xf867, 0xc0},158	{0xf868, 0x00}, {0xf869, 0x37}, {0xf86c, 0x02}, {0xf86d, 0x1d},159	{0xf86a, 0x00}, {0xf86b, 0x37}, {0xf86e, 0x02}, {0xf86f, 0x1d},160	{0xf870, 0x01}, {0xf871, 0xc6}, {0xf872, 0x02}, {0xf873, 0x04},161	{0xf874, 0x01}, {0xf875, 0xc6}, {0xf876, 0x02}, {0xf877, 0x04},162	{0xf878, 0x0f}, {0xf879, 0x0f}, {0xf87a, 0xff}, {0xf87b, 0xff},163	{0xf800, 0x03}164};165static const struct ucbus_write_cmd lz24bp_start_1_gen[] = {166	{0xf5f0, 0x00}, {0xf5f1, 0xff}, {0xf5f2, 0x80}, {0xf5f3, 0x80},167	{0xf5f4, 0xb3},168	{0xf5f0, 0x40}, {0xf5f1, 0xff}, {0xf5f2, 0x80}, {0xf5f3, 0x80},169	{0xf5f4, 0xb3},170	{0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},171	{0xf5f9, 0x00}172};173 174static const struct ucbus_write_cmd lz24bp_start_1_clm[] = {175	{0xf5f0, 0x00}, {0xf5f1, 0xff}, {0xf5f2, 0x88}, {0xf5f3, 0x88},176	{0xf5f4, 0xc0},177	{0xf5f0, 0x40}, {0xf5f1, 0xff}, {0xf5f2, 0x88}, {0xf5f3, 0x88},178	{0xf5f4, 0xc0},179	{0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},180	{0xf5f9, 0x00}181};182 183static const struct ucbus_write_cmd lz24bp_start_2[] = {184	{0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x80}, {0xf806, 0x00},185	{0xf807, 0x7f}, {0xf800, 0x03},186	{0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x4e}, {0xf806, 0x00},187	{0xf807, 0x7f}, {0xf800, 0x03},188	{0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0xc0}, {0xf806, 0x48},189	{0xf807, 0x7f}, {0xf800, 0x03},190	{0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x00}, {0xf806, 0x00},191	{0xf807, 0x7f}, {0xf800, 0x03}192};193 194static const struct ucbus_write_cmd mi0360_start_0[] = {195	{0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0xcc}, {0xf333, 0xcc},196	{0xf334, 0xcc}, {0xf335, 0xcc}, {0xf33f, 0x00}197};198static const struct i2c_write_cmd mi0360_init_23[] = {199	{0x30, 0x0040},		/* reserved - def 0x0005 */200	{0x31, 0x0000},		/* reserved - def 0x002a */201	{0x34, 0x0100},		/* reserved - def 0x0100 */202	{0x3d, 0x068f},		/* reserved - def 0x068f */203};204static const struct i2c_write_cmd mi0360_init_24[] = {205	{0x03, 0x01e5},		/* window height */206	{0x04, 0x0285},		/* window width */207};208static const struct i2c_write_cmd mi0360_init_25[] = {209	{0x35, 0x0020},		/* global gain */210	{0x2b, 0x0020},		/* green1 gain */211	{0x2c, 0x002a},		/* blue gain */212	{0x2d, 0x0028},		/* red gain */213	{0x2e, 0x0020},		/* green2 gain */214};215static const struct ucbus_write_cmd mi0360_start_1[] = {216	{0xf5f0, 0x11}, {0xf5f1, 0x99}, {0xf5f2, 0x80}, {0xf5f3, 0x80},217	{0xf5f4, 0xa6},218	{0xf5f0, 0x51}, {0xf5f1, 0x99}, {0xf5f2, 0x80}, {0xf5f3, 0x80},219	{0xf5f4, 0xa6},220	{0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},221	{0xf5f9, 0x00}222};223static const struct i2c_write_cmd mi0360_start_2[] = {224	{0x62, 0x041d},		/* reserved - def 0x0418 */225};226static const struct i2c_write_cmd mi0360_start_3[] = {227	{0x05, 0x007b},		/* horiz blanking */228};229static const struct i2c_write_cmd mi0360_start_4[] = {230	{0x05, 0x03f5},		/* horiz blanking */231};232 233static const struct i2c_write_cmd mt9v111_init_0[] = {234	{0x01, 0x0001},		/* select IFP/SOC registers */235	{0x06, 0x300c},		/* operating mode control */236	{0x08, 0xcc00},		/* output format control (RGB) */237	{0x01, 0x0004},		/* select sensor core registers */238};239static const struct i2c_write_cmd mt9v111_init_1[] = {240	{0x03, 0x01e5},		/* window height */241	{0x04, 0x0285},		/* window width */242};243static const struct i2c_write_cmd mt9v111_init_2[] = {244	{0x30, 0x7800},245	{0x31, 0x0000},246	{0x07, 0x3002},		/* output control */247	{0x35, 0x0020},		/* global gain */248	{0x2b, 0x0020},		/* green1 gain */249	{0x2c, 0x0020},		/* blue gain */250	{0x2d, 0x0020},		/* red gain */251	{0x2e, 0x0020},		/* green2 gain */252};253static const struct ucbus_write_cmd mt9v111_start_1[] = {254	{0xf5f0, 0x11}, {0xf5f1, 0x96}, {0xf5f2, 0x80}, {0xf5f3, 0x80},255	{0xf5f4, 0xaa},256	{0xf5f0, 0x51}, {0xf5f1, 0x96}, {0xf5f2, 0x80}, {0xf5f3, 0x80},257	{0xf5f4, 0xaa},258	{0xf5fa, 0x00}, {0xf5f6, 0x0a}, {0xf5f7, 0x0a}, {0xf5f8, 0x0a},259	{0xf5f9, 0x0a}260};261static const struct i2c_write_cmd mt9v111_init_3[] = {262	{0x62, 0x0405},263};264static const struct i2c_write_cmd mt9v111_init_4[] = {265/*	{0x05, 0x00ce}, */266	{0x05, 0x005d},		/* horizontal blanking */267};268 269static const struct ucbus_write_cmd ov7660_start_0[] = {270	{0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0x00}, {0xf333, 0xc0},271	{0xf334, 0x39}, {0xf335, 0xe7}, {0xf33f, 0x03}272};273 274static const struct ucbus_write_cmd ov9630_start_0[] = {275	{0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0x00}, {0xf333, 0x00},276	{0xf334, 0x3e}, {0xf335, 0xf8}, {0xf33f, 0x03}277};278 279/* start parameters indexed by [sensor][mode] */280static const struct cap_s {281	u8	cc_sizeid;282	u8	cc_bytes[32];283} capconfig[4][2] = {284	[SENSOR_ICX098BQ] = {285		{2,				/* Bayer 320x240 */286		  {0x05, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee,287		   0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,288		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0,289		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },290		{4,				/* Bayer 640x480 */291		  {0x01, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee,292		   0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,293		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,294		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },295	},296	[SENSOR_LZ24BP] = {297		{2,				/* Bayer 320x240 */298		  {0x05, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee,299		   0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,300		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,301		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },302		{4,				/* Bayer 640x480 */303		  {0x01, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee,304		   0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,305		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,306		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },307	},308	[SENSOR_MI0360] = {309		{2,				/* Bayer 320x240 */310		  {0x05, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,311		   0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,312		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,313		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },314		{4,				/* Bayer 640x480 */315		  {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,316		   0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,317		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,318		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },319	},320	[SENSOR_MT9V111] = {321		{2,				/* Bayer 320x240 */322		  {0x05, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,323		   0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,324		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,325		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },326		{4,				/* Bayer 640x480 */327		  {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,328		   0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,329		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,330		   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },331	},332};333 334struct sensor_s {335	const char *name;336	u8 i2c_addr;337	u8 i2c_dum;338	u8 gpio[5];339	u8 cmd_len;340	const struct ucbus_write_cmd *cmd;341};342 343static const struct sensor_s sensor_tb[] = {344	[SENSOR_ICX098BQ] = {345		"icx098bp",346		0x00, 0x00,347		{0,348		 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,349		 SQ930_GPIO_DFL_I2C_SDA,350		 0,351		 SQ930_GPIO_RSTBAR352		},353		8, icx098bq_start_0354	    },355	[SENSOR_LZ24BP] = {356		"lz24bp",357		0x00, 0x00,358		{0,359		 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,360		 SQ930_GPIO_DFL_I2C_SDA,361		 0,362		 SQ930_GPIO_RSTBAR363		},364		8, lz24bp_start_0365	    },366	[SENSOR_MI0360] = {367		"mi0360",368		0x5d, 0x80,369		{SQ930_GPIO_RSTBAR,370		 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,371		 SQ930_GPIO_DFL_I2C_SDA,372		 0,373		 0374		},375		7, mi0360_start_0376	    },377	[SENSOR_MT9V111] = {378		"mt9v111",379		0x5c, 0x7f,380		{SQ930_GPIO_RSTBAR,381		 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,382		 SQ930_GPIO_DFL_I2C_SDA,383		 0,384		 0385		},386		7, mi0360_start_0387	    },388	[SENSOR_OV7660] = {389		"ov7660",390		0x21, 0x00,391		{0,392		 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,393		 SQ930_GPIO_DFL_I2C_SDA,394		 0,395		 SQ930_GPIO_RSTBAR396		},397		7, ov7660_start_0398	    },399	[SENSOR_OV9630] = {400		"ov9630",401		0x30, 0x00,402		{0,403		 SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,404		 SQ930_GPIO_DFL_I2C_SDA,405		 0,406		 SQ930_GPIO_RSTBAR407		},408		7, ov9630_start_0409	    },410};411 412static void reg_r(struct gspca_dev *gspca_dev,413		u16 value, int len)414{415	int ret;416 417	if (gspca_dev->usb_err < 0)418		return;419	ret = usb_control_msg(gspca_dev->dev,420			usb_rcvctrlpipe(gspca_dev->dev, 0),421			0x0c,422			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,423			value, 0, gspca_dev->usb_buf, len,424			500);425	if (ret < 0) {426		pr_err("reg_r %04x failed %d\n", value, ret);427		gspca_dev->usb_err = ret;428		/*429		 * Make sure the buffer is zeroed to avoid uninitialized430		 * values.431		 */432		memset(gspca_dev->usb_buf, 0, USB_BUF_SZ);433	}434}435 436static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index)437{438	int ret;439 440	if (gspca_dev->usb_err < 0)441		return;442	gspca_dbg(gspca_dev, D_USBO, "reg_w v: %04x i: %04x\n", value, index);443	ret = usb_control_msg(gspca_dev->dev,444			usb_sndctrlpipe(gspca_dev->dev, 0),445			0x0c,			/* request */446			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,447			value, index, NULL, 0,448			500);449	msleep(30);450	if (ret < 0) {451		pr_err("reg_w %04x %04x failed %d\n", value, index, ret);452		gspca_dev->usb_err = ret;453	}454}455 456static void reg_wb(struct gspca_dev *gspca_dev, u16 value, u16 index,457		const u8 *data, int len)458{459	int ret;460 461	if (gspca_dev->usb_err < 0)462		return;463	gspca_dbg(gspca_dev, D_USBO, "reg_wb v: %04x i: %04x %02x...%02x\n",464		  value, index, *data, data[len - 1]);465	memcpy(gspca_dev->usb_buf, data, len);466	ret = usb_control_msg(gspca_dev->dev,467			usb_sndctrlpipe(gspca_dev->dev, 0),468			0x0c,			/* request */469			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,470			value, index, gspca_dev->usb_buf, len,471			1000);472	msleep(30);473	if (ret < 0) {474		pr_err("reg_wb %04x %04x failed %d\n", value, index, ret);475		gspca_dev->usb_err = ret;476	}477}478 479static void i2c_write(struct sd *sd,480			const struct i2c_write_cmd *cmd,481			int ncmds)482{483	struct gspca_dev *gspca_dev = &sd->gspca_dev;484	const struct sensor_s *sensor;485	u16 val, idx;486	u8 *buf;487	int ret;488 489	if (gspca_dev->usb_err < 0)490		return;491 492	sensor = &sensor_tb[sd->sensor];493 494	val = (sensor->i2c_addr << 8) | SQ930_CTRL_I2C_IO;495	idx = (cmd->val & 0xff00) | cmd->reg;496 497	buf = gspca_dev->usb_buf;498	*buf++ = sensor->i2c_dum;499	*buf++ = cmd->val;500 501	while (--ncmds > 0) {502		cmd++;503		*buf++ = cmd->reg;504		*buf++ = cmd->val >> 8;505		*buf++ = sensor->i2c_dum;506		*buf++ = cmd->val;507	}508 509	gspca_dbg(gspca_dev, D_USBO, "i2c_w v: %04x i: %04x %02x...%02x\n",510		  val, idx, gspca_dev->usb_buf[0], buf[-1]);511	ret = usb_control_msg(gspca_dev->dev,512			usb_sndctrlpipe(gspca_dev->dev, 0),513			0x0c,			/* request */514			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,515			val, idx,516			gspca_dev->usb_buf, buf - gspca_dev->usb_buf,517			500);518	if (ret < 0) {519		pr_err("i2c_write failed %d\n", ret);520		gspca_dev->usb_err = ret;521	}522}523 524static void ucbus_write(struct gspca_dev *gspca_dev,525			const struct ucbus_write_cmd *cmd,526			int ncmds,527			int batchsize)528{529	u8 *buf;530	u16 val, idx;531	int len, ret;532 533	if (gspca_dev->usb_err < 0)534		return;535 536	if ((batchsize - 1) * 3 > USB_BUF_SZ) {537		gspca_err(gspca_dev, "Bug: usb_buf overflow\n");538		gspca_dev->usb_err = -ENOMEM;539		return;540	}541 542	for (;;) {543		len = ncmds;544		if (len > batchsize)545			len = batchsize;546		ncmds -= len;547 548		val = (cmd->bw_addr << 8) | SQ930_CTRL_UCBUS_IO;549		idx = (cmd->bw_data << 8) | (cmd->bw_addr >> 8);550 551		buf = gspca_dev->usb_buf;552		while (--len > 0) {553			cmd++;554			*buf++ = cmd->bw_addr;555			*buf++ = cmd->bw_addr >> 8;556			*buf++ = cmd->bw_data;557		}558		if (buf != gspca_dev->usb_buf)559			gspca_dbg(gspca_dev, D_USBO, "ucbus v: %04x i: %04x %02x...%02x\n",560				  val, idx,561				  gspca_dev->usb_buf[0], buf[-1]);562		else563			gspca_dbg(gspca_dev, D_USBO, "ucbus v: %04x i: %04x\n",564				  val, idx);565		ret = usb_control_msg(gspca_dev->dev,566				usb_sndctrlpipe(gspca_dev->dev, 0),567				0x0c,			/* request */568			   USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,569				val, idx,570				gspca_dev->usb_buf, buf - gspca_dev->usb_buf,571				500);572		if (ret < 0) {573			pr_err("ucbus_write failed %d\n", ret);574			gspca_dev->usb_err = ret;575			return;576		}577		msleep(30);578		if (ncmds <= 0)579			break;580		cmd++;581	}582}583 584static void gpio_set(struct sd *sd, u16 val, u16 mask)585{586	struct gspca_dev *gspca_dev = &sd->gspca_dev;587 588	if (mask & 0x00ff) {589		sd->gpio[0] &= ~mask;590		sd->gpio[0] |= val;591		reg_w(gspca_dev, 0x0100 | SQ930_CTRL_GPIO,592			~sd->gpio[0] << 8);593	}594	mask >>= 8;595	val >>= 8;596	if (mask) {597		sd->gpio[1] &= ~mask;598		sd->gpio[1] |= val;599		reg_w(gspca_dev, 0x0300 | SQ930_CTRL_GPIO,600			~sd->gpio[1] << 8);601	}602}603 604static void gpio_init(struct sd *sd,605			const u8 *gpio)606{607	gpio_set(sd, *gpio++, 0x000f);608	gpio_set(sd, *gpio++, 0x000f);609	gpio_set(sd, *gpio++, 0x000f);610	gpio_set(sd, *gpio++, 0x000f);611	gpio_set(sd, *gpio, 0x000f);612}613 614static void bridge_init(struct sd *sd)615{616	static const struct ucbus_write_cmd clkfreq_cmd = {617				0xf031, 0	/* SQ930_CLKFREQ_60MHZ */618	};619 620	ucbus_write(&sd->gspca_dev, &clkfreq_cmd, 1, 1);621 622	gpio_set(sd, SQ930_GPIO_POWER, 0xff00);623}624 625static void cmos_probe(struct gspca_dev *gspca_dev)626{627	struct sd *sd = (struct sd *) gspca_dev;628	int i;629	const struct sensor_s *sensor;630	static const u8 probe_order[] = {631/*		SENSOR_LZ24BP,		(tested as ccd) */632		SENSOR_OV9630,633		SENSOR_MI0360,634		SENSOR_OV7660,635		SENSOR_MT9V111,636	};637 638	for (i = 0; i < ARRAY_SIZE(probe_order); i++) {639		sensor = &sensor_tb[probe_order[i]];640		ucbus_write(&sd->gspca_dev, sensor->cmd, sensor->cmd_len, 8);641		gpio_init(sd, sensor->gpio);642		msleep(100);643		reg_r(gspca_dev, (sensor->i2c_addr << 8) | 0x001c, 1);644		msleep(100);645		if (gspca_dev->usb_buf[0] != 0)646			break;647	}648	if (i >= ARRAY_SIZE(probe_order)) {649		pr_err("Unknown sensor\n");650		gspca_dev->usb_err = -EINVAL;651		return;652	}653	sd->sensor = probe_order[i];654	switch (sd->sensor) {655	case SENSOR_OV7660:656	case SENSOR_OV9630:657		pr_err("Sensor %s not yet treated\n",658		       sensor_tb[sd->sensor].name);659		gspca_dev->usb_err = -EINVAL;660		break;661	}662}663 664static void mt9v111_init(struct gspca_dev *gspca_dev)665{666	int i, nwait;667	static const u8 cmd_001b[] = {668		0x00, 0x3b, 0xf6, 0x01, 0x03, 0x02, 0x00, 0x00,669		0x00, 0x00, 0x00670	};671	static const u8 cmd_011b[][7] = {672		{0x10, 0x01, 0x66, 0x08, 0x00, 0x00, 0x00},673		{0x01, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x00},674		{0x20, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00},675		{0x02, 0x01, 0xae, 0x01, 0x00, 0x00, 0x00},676	};677 678	reg_wb(gspca_dev, 0x001b, 0x0000, cmd_001b, sizeof cmd_001b);679	for (i = 0; i < ARRAY_SIZE(cmd_011b); i++) {680		reg_wb(gspca_dev, 0x001b, 0x0000, cmd_011b[i],681				ARRAY_SIZE(cmd_011b[0]));682		msleep(400);683		nwait = 20;684		for (;;) {685			reg_r(gspca_dev, 0x031b, 1);686			if (gspca_dev->usb_buf[0] == 0687			 || gspca_dev->usb_err != 0)688				break;689			if (--nwait < 0) {690				gspca_dbg(gspca_dev, D_PROBE, "mt9v111_init timeout\n");691				gspca_dev->usb_err = -ETIME;692				return;693			}694			msleep(50);695		}696	}697}698 699static void global_init(struct sd *sd, int first_time)700{701	switch (sd->sensor) {702	case SENSOR_ICX098BQ:703		if (first_time)704			ucbus_write(&sd->gspca_dev,705					icx098bq_start_0,706					8, 8);707		gpio_init(sd, sensor_tb[sd->sensor].gpio);708		break;709	case SENSOR_LZ24BP:710		if (sd->type != Creative_live_motion)711			gpio_set(sd, SQ930_GPIO_EXTRA1, 0x00ff);712		else713			gpio_set(sd, 0, 0x00ff);714		msleep(50);715		if (first_time)716			ucbus_write(&sd->gspca_dev,717					lz24bp_start_0,718					8, 8);719		gpio_init(sd, sensor_tb[sd->sensor].gpio);720		break;721	case SENSOR_MI0360:722		if (first_time)723			ucbus_write(&sd->gspca_dev,724					mi0360_start_0,725					ARRAY_SIZE(mi0360_start_0),726					8);727		gpio_init(sd, sensor_tb[sd->sensor].gpio);728		gpio_set(sd, SQ930_GPIO_EXTRA2, SQ930_GPIO_EXTRA2);729		break;730	default:731/*	case SENSOR_MT9V111: */732		if (first_time)733			mt9v111_init(&sd->gspca_dev);734		else735			gpio_init(sd, sensor_tb[sd->sensor].gpio);736		break;737	}738}739 740static void lz24bp_ppl(struct sd *sd, u16 ppl)741{742	struct ucbus_write_cmd cmds[2] = {743		{0xf810, ppl >> 8},744		{0xf811, ppl}745	};746 747	ucbus_write(&sd->gspca_dev, cmds, ARRAY_SIZE(cmds), 2);748}749 750static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 gain)751{752	struct sd *sd = (struct sd *) gspca_dev;753	int i, integclks, intstartclk, frameclks, min_frclk;754	const struct sensor_s *sensor;755	u16 cmd;756	u8 buf[15];757 758	integclks = expo;759	i = 0;760	cmd = SQ930_CTRL_SET_EXPOSURE;761 762	switch (sd->sensor) {763	case SENSOR_ICX098BQ:			/* ccd */764	case SENSOR_LZ24BP:765		min_frclk = sd->sensor == SENSOR_ICX098BQ ? 0x210 : 0x26f;766		if (integclks >= min_frclk) {767			intstartclk = 0;768			frameclks = integclks;769		} else {770			intstartclk = min_frclk - integclks;771			frameclks = min_frclk;772		}773		buf[i++] = intstartclk >> 8;774		buf[i++] = intstartclk;775		buf[i++] = frameclks >> 8;776		buf[i++] = frameclks;777		buf[i++] = gain;778		break;779	default:				/* cmos */780/*	case SENSOR_MI0360: */781/*	case SENSOR_MT9V111: */782		cmd |= 0x0100;783		sensor = &sensor_tb[sd->sensor];784		buf[i++] = sensor->i2c_addr;	/* i2c_slave_addr */785		buf[i++] = 0x08;	/* 2 * ni2c */786		buf[i++] = 0x09;	/* reg = shutter width */787		buf[i++] = integclks >> 8; /* val H */788		buf[i++] = sensor->i2c_dum;789		buf[i++] = integclks;	/* val L */790		buf[i++] = 0x35;	/* reg = global gain */791		buf[i++] = 0x00;	/* val H */792		buf[i++] = sensor->i2c_dum;793		buf[i++] = 0x80 + gain / 2; /* val L */794		buf[i++] = 0x00;795		buf[i++] = 0x00;796		buf[i++] = 0x00;797		buf[i++] = 0x00;798		buf[i++] = 0x83;799		break;800	}801	reg_wb(gspca_dev, cmd, 0, buf, i);802}803 804/* This function is called at probe time just before sd_init */805static int sd_config(struct gspca_dev *gspca_dev,806		const struct usb_device_id *id)807{808	struct sd *sd = (struct sd *) gspca_dev;809	struct cam *cam = &gspca_dev->cam;810 811	sd->sensor = id->driver_info >> 8;812	sd->type = id->driver_info;813 814	cam->cam_mode = vga_mode;815	cam->nmodes = ARRAY_SIZE(vga_mode);816 817	cam->bulk = 1;818 819	return 0;820}821 822/* this function is called at probe and resume time */823static int sd_init(struct gspca_dev *gspca_dev)824{825	struct sd *sd = (struct sd *) gspca_dev;826 827	sd->gpio[0] = sd->gpio[1] = 0xff;	/* force gpio rewrite */828 829/*fixme: is this needed for icx098bp and mi0360?830	if (sd->sensor != SENSOR_LZ24BP)831		reg_w(gspca_dev, SQ930_CTRL_RESET, 0x0000);832 */833 834	reg_r(gspca_dev, SQ930_CTRL_GET_DEV_INFO, 8);835	if (gspca_dev->usb_err < 0)836		return gspca_dev->usb_err;837 838/* it returns:839 * 03 00 12 93 0b f6 c9 00	live! ultra840 * 03 00 07 93 0b f6 ca 00	live! ultra for notebook841 * 03 00 12 93 0b fe c8 00	Trust WB-3500T842 * 02 00 06 93 0b fe c8 00	Joy-IT 318S843 * 03 00 12 93 0b f6 cf 00	icam tracer - sensor icx098bq844 * 02 00 12 93 0b fe cf 00	ProQ Motion Webcam845 *846 * byte847 * 0: 02 = usb 1.0 (12Mbit) / 03 = usb2.0 (480Mbit)848 * 1: 00849 * 2: 06 / 07 / 12 = mode webcam? firmware??850 * 3: 93 chip = 930b (930b or 930c)851 * 4: 0b852 * 5: f6 = cdd (icx098bq, lz24bp) / fe or de = cmos (i2c) (other sensors)853 * 6: c8 / c9 / ca / cf = mode webcam?, sensor? webcam?854 * 7: 00855 */856	gspca_dbg(gspca_dev, D_PROBE, "info: %*ph\n", 8, gspca_dev->usb_buf);857 858	bridge_init(sd);859 860	if (sd->sensor == SENSOR_MI0360) {861 862		/* no sensor probe for icam tracer */863		if (gspca_dev->usb_buf[5] == 0xf6)	/* if ccd */864			sd->sensor = SENSOR_ICX098BQ;865		else866			cmos_probe(gspca_dev);867	}868	if (gspca_dev->usb_err >= 0) {869		gspca_dbg(gspca_dev, D_PROBE, "Sensor %s\n",870			  sensor_tb[sd->sensor].name);871		global_init(sd, 1);872	}873	return gspca_dev->usb_err;874}875 876/* send the start/stop commands to the webcam */877static void send_start(struct gspca_dev *gspca_dev)878{879	struct sd *sd = (struct sd *) gspca_dev;880	const struct cap_s *cap;881	int mode;882 883	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;884	cap = &capconfig[sd->sensor][mode];885	reg_wb(gspca_dev, 0x0900 | SQ930_CTRL_CAP_START,886			0x0a00 | cap->cc_sizeid,887			cap->cc_bytes, 32);888}889 890static void send_stop(struct gspca_dev *gspca_dev)891{892	reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0);893}894 895/* function called at start time before URB creation */896static int sd_isoc_init(struct gspca_dev *gspca_dev)897{898	struct sd *sd = (struct sd *) gspca_dev;899 900	gspca_dev->cam.bulk_nurbs = 1;	/* there must be one URB only */901	sd->do_ctrl = 0;902	gspca_dev->cam.bulk_size = gspca_dev->pixfmt.width *903			gspca_dev->pixfmt.height + 8;904	return 0;905}906 907/* start the capture */908static int sd_start(struct gspca_dev *gspca_dev)909{910	struct sd *sd = (struct sd *) gspca_dev;911	int mode;912 913	bridge_init(sd);914	global_init(sd, 0);915	msleep(100);916 917	switch (sd->sensor) {918	case SENSOR_ICX098BQ:919		ucbus_write(gspca_dev, icx098bq_start_0,920				ARRAY_SIZE(icx098bq_start_0),921				8);922		ucbus_write(gspca_dev, icx098bq_start_1,923				ARRAY_SIZE(icx098bq_start_1),924				5);925		ucbus_write(gspca_dev, icx098bq_start_2,926				ARRAY_SIZE(icx098bq_start_2),927				6);928		msleep(50);929 930		/* 1st start */931		send_start(gspca_dev);932		gpio_set(sd, SQ930_GPIO_EXTRA2 | SQ930_GPIO_RSTBAR, 0x00ff);933		msleep(70);934		reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0x0000);935		gpio_set(sd, 0x7f, 0x00ff);936 937		/* 2nd start */938		send_start(gspca_dev);939		gpio_set(sd, SQ930_GPIO_EXTRA2 | SQ930_GPIO_RSTBAR, 0x00ff);940		goto out;941	case SENSOR_LZ24BP:942		ucbus_write(gspca_dev, lz24bp_start_0,943				ARRAY_SIZE(lz24bp_start_0),944				8);945		if (sd->type != Creative_live_motion)946			ucbus_write(gspca_dev, lz24bp_start_1_gen,947					ARRAY_SIZE(lz24bp_start_1_gen),948					5);949		else950			ucbus_write(gspca_dev, lz24bp_start_1_clm,951					ARRAY_SIZE(lz24bp_start_1_clm),952					5);953		ucbus_write(gspca_dev, lz24bp_start_2,954				ARRAY_SIZE(lz24bp_start_2),955				6);956		mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;957		lz24bp_ppl(sd, mode == 1 ? 0x0564 : 0x0310);958		msleep(10);959		break;960	case SENSOR_MI0360:961		ucbus_write(gspca_dev, mi0360_start_0,962				ARRAY_SIZE(mi0360_start_0),963				8);964		i2c_write(sd, mi0360_init_23,965				ARRAY_SIZE(mi0360_init_23));966		i2c_write(sd, mi0360_init_24,967				ARRAY_SIZE(mi0360_init_24));968		i2c_write(sd, mi0360_init_25,969				ARRAY_SIZE(mi0360_init_25));970		ucbus_write(gspca_dev, mi0360_start_1,971				ARRAY_SIZE(mi0360_start_1),972				5);973		i2c_write(sd, mi0360_start_2,974				ARRAY_SIZE(mi0360_start_2));975		i2c_write(sd, mi0360_start_3,976				ARRAY_SIZE(mi0360_start_3));977 978		/* 1st start */979		send_start(gspca_dev);980		msleep(60);981		send_stop(gspca_dev);982 983		i2c_write(sd,984			mi0360_start_4, ARRAY_SIZE(mi0360_start_4));985		break;986	default:987/*	case SENSOR_MT9V111: */988		ucbus_write(gspca_dev, mi0360_start_0,989				ARRAY_SIZE(mi0360_start_0),990				8);991		i2c_write(sd, mt9v111_init_0,992				ARRAY_SIZE(mt9v111_init_0));993		i2c_write(sd, mt9v111_init_1,994				ARRAY_SIZE(mt9v111_init_1));995		i2c_write(sd, mt9v111_init_2,996				ARRAY_SIZE(mt9v111_init_2));997		ucbus_write(gspca_dev, mt9v111_start_1,998				ARRAY_SIZE(mt9v111_start_1),999				5);1000		i2c_write(sd, mt9v111_init_3,1001				ARRAY_SIZE(mt9v111_init_3));1002		i2c_write(sd, mt9v111_init_4,1003				ARRAY_SIZE(mt9v111_init_4));1004		break;1005	}1006 1007	send_start(gspca_dev);1008out:1009	msleep(1000);1010 1011	if (sd->sensor == SENSOR_MT9V111)1012		gpio_set(sd, SQ930_GPIO_DFL_LED, SQ930_GPIO_DFL_LED);1013 1014	sd->do_ctrl = 1;	/* set the exposure */1015 1016	return gspca_dev->usb_err;1017}1018 1019static void sd_stopN(struct gspca_dev *gspca_dev)1020{1021	struct sd *sd = (struct sd *) gspca_dev;1022 1023	if (sd->sensor == SENSOR_MT9V111)1024		gpio_set(sd, 0, SQ930_GPIO_DFL_LED);1025	send_stop(gspca_dev);1026}1027 1028/* function called when the application gets a new frame */1029/* It sets the exposure if required and restart the bulk transfer. */1030static void sd_dq_callback(struct gspca_dev *gspca_dev)1031{1032	struct sd *sd = (struct sd *) gspca_dev;1033	int ret;1034 1035	if (!sd->do_ctrl || gspca_dev->cam.bulk_nurbs != 0)1036		return;1037	sd->do_ctrl = 0;1038 1039	setexposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure),1040			v4l2_ctrl_g_ctrl(sd->gain));1041 1042	gspca_dev->cam.bulk_nurbs = 1;1043	ret = usb_submit_urb(gspca_dev->urb[0], GFP_KERNEL);1044	if (ret < 0)1045		pr_err("sd_dq_callback() err %d\n", ret);1046 1047	/* wait a little time, otherwise the webcam crashes */1048	msleep(100);1049}1050 1051static void sd_pkt_scan(struct gspca_dev *gspca_dev,1052			u8 *data,		/* isoc packet */1053			int len)		/* iso packet length */1054{1055	struct sd *sd = (struct sd *) gspca_dev;1056 1057	if (sd->do_ctrl)1058		gspca_dev->cam.bulk_nurbs = 0;1059	gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);1060	gspca_frame_add(gspca_dev, INTER_PACKET, data, len - 8);1061	gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);1062}1063 1064static int sd_s_ctrl(struct v4l2_ctrl *ctrl)1065{1066	struct gspca_dev *gspca_dev =1067		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);1068	struct sd *sd = (struct sd *) gspca_dev;1069 1070	gspca_dev->usb_err = 0;1071 1072	if (!gspca_dev->streaming)1073		return 0;1074 1075	switch (ctrl->id) {1076	case V4L2_CID_EXPOSURE:1077		setexposure(gspca_dev, ctrl->val, sd->gain->val);1078		break;1079	}1080	return gspca_dev->usb_err;1081}1082 1083static const struct v4l2_ctrl_ops sd_ctrl_ops = {1084	.s_ctrl = sd_s_ctrl,1085};1086 1087static int sd_init_controls(struct gspca_dev *gspca_dev)1088{1089	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;1090	struct sd *sd = (struct sd *) gspca_dev;1091 1092	gspca_dev->vdev.ctrl_handler = hdl;1093	v4l2_ctrl_handler_init(hdl, 2);1094	sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,1095			V4L2_CID_EXPOSURE, 1, 0xfff, 1, 0x356);1096	sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,1097			V4L2_CID_GAIN, 1, 255, 1, 0x8d);1098 1099	if (hdl->error) {1100		pr_err("Could not initialize controls\n");1101		return hdl->error;1102	}1103	v4l2_ctrl_cluster(2, &sd->exposure);1104	return 0;1105}1106 1107/* sub-driver description */1108static const struct sd_desc sd_desc = {1109	.name   = MODULE_NAME,1110	.config = sd_config,1111	.init   = sd_init,1112	.init_controls = sd_init_controls,1113	.isoc_init = sd_isoc_init,1114	.start  = sd_start,1115	.stopN  = sd_stopN,1116	.pkt_scan = sd_pkt_scan,1117	.dq_callback = sd_dq_callback,1118};1119 1120/* Table of supported USB devices */1121#define ST(sensor, type) \1122	.driver_info = (SENSOR_ ## sensor << 8) \1123			| (type)1124static const struct usb_device_id device_table[] = {1125	{USB_DEVICE(0x041e, 0x4038), ST(MI0360, 0)},1126	{USB_DEVICE(0x041e, 0x403c), ST(LZ24BP, 0)},1127	{USB_DEVICE(0x041e, 0x403d), ST(LZ24BP, 0)},1128	{USB_DEVICE(0x041e, 0x4041), ST(LZ24BP, Creative_live_motion)},1129	{USB_DEVICE(0x2770, 0x930b), ST(MI0360, 0)},1130	{USB_DEVICE(0x2770, 0x930c), ST(MI0360, 0)},1131	{}1132};1133MODULE_DEVICE_TABLE(usb, device_table);1134 1135 1136/* -- device connect -- */1137static int sd_probe(struct usb_interface *intf,1138		const struct usb_device_id *id)1139{1140	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),1141			THIS_MODULE);1142}1143 1144static struct usb_driver sd_driver = {1145	.name	    = MODULE_NAME,1146	.id_table   = device_table,1147	.probe	    = sd_probe,1148	.disconnect = gspca_disconnect,1149#ifdef CONFIG_PM1150	.suspend    = gspca_suspend,1151	.resume     = gspca_resume,1152	.reset_resume = gspca_resume,1153#endif1154};1155 1156module_usb_driver(sd_driver);1157