brintos

brintos / linux-shallow public Read only

0
0
Text · 17.7 KiB · 0e8cccb Raw
792 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * SPCA505 chip based cameras initialization data4 *5 * V4L2 by Jean-Francis Moine <http://moinejf.free.fr>6 */7 8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt9 10#define MODULE_NAME "spca505"11 12#include "gspca.h"13 14MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");15MODULE_DESCRIPTION("GSPCA/SPCA505 USB Camera Driver");16MODULE_LICENSE("GPL");17 18/* specific webcam descriptor */19struct sd {20	struct gspca_dev gspca_dev;		/* !! must be the first item */21 22	u8 subtype;23#define IntelPCCameraPro 024#define Nxultra 125};26 27static const struct v4l2_pix_format vga_mode[] = {28	{160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,29		.bytesperline = 160,30		.sizeimage = 160 * 120 * 3 / 2,31		.colorspace = V4L2_COLORSPACE_SRGB,32		.priv = 4},33	{176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,34		.bytesperline = 176,35		.sizeimage = 176 * 144 * 3 / 2,36		.colorspace = V4L2_COLORSPACE_SRGB,37		.priv = 3},38	{320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,39		.bytesperline = 320,40		.sizeimage = 320 * 240 * 3 / 2,41		.colorspace = V4L2_COLORSPACE_SRGB,42		.priv = 2},43	{352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,44		.bytesperline = 352,45		.sizeimage = 352 * 288 * 3 / 2,46		.colorspace = V4L2_COLORSPACE_SRGB,47		.priv = 1},48	{640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,49		.bytesperline = 640,50		.sizeimage = 640 * 480 * 3 / 2,51		.colorspace = V4L2_COLORSPACE_SRGB,52		.priv = 0},53};54 55#define SPCA50X_OFFSET_DATA 1056 57#define SPCA50X_REG_USB 0x02	/* spca505 501 */58 59#define SPCA50X_USB_CTRL 0x00	/* spca505 */60#define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */61 62#define SPCA50X_REG_GLOBAL 0x03	/* spca505 */63#define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */64#define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */65 66#define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */67#define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */68#define SPCA50X_GMISC3_SAA7113RST 0x20	/* Not sure about this one spca505 */69 70/* Image format and compression control */71#define SPCA50X_REG_COMPRESS 0x0472 73/*74 * Data to initialize a SPCA505. Common to the CCD and external modes75 */76static const u8 spca505_init_data[][3] = {77	/* bmRequest,value,index */78	{SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3},79	/* Sensor reset */80	{SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},81	{SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},82	/* Block USB reset */83	{SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL, SPCA50X_GLOBAL_MISC0},84 85	{0x05, 0x01, 0x10},86					/* Maybe power down some stuff */87	{0x05, 0x0f, 0x11},88 89	/* Setup internal CCD  ? */90	{0x06, 0x10, 0x08},91	{0x06, 0x00, 0x09},92	{0x06, 0x00, 0x0a},93	{0x06, 0x00, 0x0b},94	{0x06, 0x10, 0x0c},95	{0x06, 0x00, 0x0d},96	{0x06, 0x00, 0x0e},97	{0x06, 0x00, 0x0f},98	{0x06, 0x10, 0x10},99	{0x06, 0x02, 0x11},100	{0x06, 0x00, 0x12},101	{0x06, 0x04, 0x13},102	{0x06, 0x02, 0x14},103	{0x06, 0x8a, 0x51},104	{0x06, 0x40, 0x52},105	{0x06, 0xb6, 0x53},106	{0x06, 0x3d, 0x54},107	{}108};109 110/*111 * Data to initialize the camera using the internal CCD112 */113static const u8 spca505_open_data_ccd[][3] = {114	/* bmRequest,value,index */115	/* Internal CCD data set */116	{0x03, 0x04, 0x01},117	/* This could be a reset */118	{0x03, 0x00, 0x01},119 120	/* Setup compression and image registers. 0x6 and 0x7 seem to be121	   related to H&V hold, and are resolution mode specific */122		{0x04, 0x10, 0x01},123		/* DIFF(0x50), was (0x10) */124	{0x04, 0x00, 0x04},125	{0x04, 0x00, 0x05},126	{0x04, 0x20, 0x06},127	{0x04, 0x20, 0x07},128 129	{0x08, 0x0a, 0x00},130	/* DIFF (0x4a), was (0xa) */131 132	{0x05, 0x00, 0x10},133	{0x05, 0x00, 0x11},134	{0x05, 0x00, 0x00},135	/* DIFF not written */136	{0x05, 0x00, 0x01},137	/* DIFF not written */138	{0x05, 0x00, 0x02},139	/* DIFF not written */140	{0x05, 0x00, 0x03},141	/* DIFF not written */142	{0x05, 0x00, 0x04},143	/* DIFF not written */144		{0x05, 0x80, 0x05},145		/* DIFF not written */146		{0x05, 0xe0, 0x06},147		/* DIFF not written */148		{0x05, 0x20, 0x07},149		/* DIFF not written */150		{0x05, 0xa0, 0x08},151		/* DIFF not written */152		{0x05, 0x0, 0x12},153		/* DIFF not written */154	{0x05, 0x02, 0x0f},155	/* DIFF not written */156		{0x05, 0x10, 0x46},157		/* DIFF not written */158		{0x05, 0x8, 0x4a},159		/* DIFF not written */160 161	{0x03, 0x08, 0x03},162	/* DIFF (0x3,0x28,0x3) */163	{0x03, 0x08, 0x01},164	{0x03, 0x0c, 0x03},165	/* DIFF not written */166		{0x03, 0x21, 0x00},167		/* DIFF (0x39) */168 169/* Extra block copied from init to hopefully ensure CCD is in a sane state */170	{0x06, 0x10, 0x08},171	{0x06, 0x00, 0x09},172	{0x06, 0x00, 0x0a},173	{0x06, 0x00, 0x0b},174	{0x06, 0x10, 0x0c},175	{0x06, 0x00, 0x0d},176	{0x06, 0x00, 0x0e},177	{0x06, 0x00, 0x0f},178	{0x06, 0x10, 0x10},179	{0x06, 0x02, 0x11},180	{0x06, 0x00, 0x12},181	{0x06, 0x04, 0x13},182	{0x06, 0x02, 0x14},183	{0x06, 0x8a, 0x51},184	{0x06, 0x40, 0x52},185	{0x06, 0xb6, 0x53},186	{0x06, 0x3d, 0x54},187	/* End of extra block */188 189		{0x06, 0x3f, 0x1},190		/* Block skipped */191	{0x06, 0x10, 0x02},192	{0x06, 0x64, 0x07},193	{0x06, 0x10, 0x08},194	{0x06, 0x00, 0x09},195	{0x06, 0x00, 0x0a},196	{0x06, 0x00, 0x0b},197	{0x06, 0x10, 0x0c},198	{0x06, 0x00, 0x0d},199	{0x06, 0x00, 0x0e},200	{0x06, 0x00, 0x0f},201	{0x06, 0x10, 0x10},202	{0x06, 0x02, 0x11},203	{0x06, 0x00, 0x12},204	{0x06, 0x04, 0x13},205	{0x06, 0x02, 0x14},206	{0x06, 0x8a, 0x51},207	{0x06, 0x40, 0x52},208	{0x06, 0xb6, 0x53},209	{0x06, 0x3d, 0x54},210	{0x06, 0x60, 0x57},211	{0x06, 0x20, 0x58},212	{0x06, 0x15, 0x59},213	{0x06, 0x05, 0x5a},214 215	{0x05, 0x01, 0xc0},216	{0x05, 0x10, 0xcb},217		{0x05, 0x80, 0xc1},218		/* */219		{0x05, 0x0, 0xc2},220		/* 4 was 0 */221	{0x05, 0x00, 0xca},222		{0x05, 0x80, 0xc1},223		/*  */224	{0x05, 0x04, 0xc2},225	{0x05, 0x00, 0xca},226		{0x05, 0x0, 0xc1},227		/*  */228	{0x05, 0x00, 0xc2},229	{0x05, 0x00, 0xca},230		{0x05, 0x40, 0xc1},231		/* */232	{0x05, 0x17, 0xc2},233	{0x05, 0x00, 0xca},234		{0x05, 0x80, 0xc1},235		/* */236	{0x05, 0x06, 0xc2},237	{0x05, 0x00, 0xca},238		{0x05, 0x80, 0xc1},239		/* */240	{0x05, 0x04, 0xc2},241	{0x05, 0x00, 0xca},242 243	{0x03, 0x4c, 0x3},244	{0x03, 0x18, 0x1},245 246	{0x06, 0x70, 0x51},247	{0x06, 0xbe, 0x53},248	{0x06, 0x71, 0x57},249	{0x06, 0x20, 0x58},250	{0x06, 0x05, 0x59},251	{0x06, 0x15, 0x5a},252 253	{0x04, 0x00, 0x08},254	/* Compress = OFF (0x1 to turn on) */255	{0x04, 0x12, 0x09},256	{0x04, 0x21, 0x0a},257	{0x04, 0x10, 0x0b},258	{0x04, 0x21, 0x0c},259	{0x04, 0x05, 0x00},260	/* was 5 (Image Type ? ) */261	{0x04, 0x00, 0x01},262 263	{0x06, 0x3f, 0x01},264 265	{0x04, 0x00, 0x04},266	{0x04, 0x00, 0x05},267	{0x04, 0x40, 0x06},268	{0x04, 0x40, 0x07},269 270	{0x06, 0x1c, 0x17},271	{0x06, 0xe2, 0x19},272	{0x06, 0x1c, 0x1b},273	{0x06, 0xe2, 0x1d},274	{0x06, 0xaa, 0x1f},275	{0x06, 0x70, 0x20},276 277	{0x05, 0x01, 0x10},278	{0x05, 0x00, 0x11},279	{0x05, 0x01, 0x00},280	{0x05, 0x05, 0x01},281		{0x05, 0x00, 0xc1},282		/* */283	{0x05, 0x00, 0xc2},284	{0x05, 0x00, 0xca},285 286	{0x06, 0x70, 0x51},287	{0x06, 0xbe, 0x53},288	{}289};290 291/*292 * Made by Tomasz Zablocki (skalamandra@poczta.onet.pl)293 * SPCA505b chip based cameras initialization data294 */295/* jfm */296#define initial_brightness 0x7f	/* 0x0(white)-0xff(black) */297/* #define initial_brightness 0x0	//0x0(white)-0xff(black) */298/*299 * Data to initialize a SPCA505. Common to the CCD and external modes300 */301static const u8 spca505b_init_data[][3] = {302/* start */303	{0x02, 0x00, 0x00},		/* init */304	{0x02, 0x00, 0x01},305	{0x02, 0x00, 0x02},306	{0x02, 0x00, 0x03},307	{0x02, 0x00, 0x04},308	{0x02, 0x00, 0x05},309	{0x02, 0x00, 0x06},310	{0x02, 0x00, 0x07},311	{0x02, 0x00, 0x08},312	{0x02, 0x00, 0x09},313	{0x03, 0x00, 0x00},314	{0x03, 0x00, 0x01},315	{0x03, 0x00, 0x02},316	{0x03, 0x00, 0x03},317	{0x03, 0x00, 0x04},318	{0x03, 0x00, 0x05},319	{0x03, 0x00, 0x06},320	{0x04, 0x00, 0x00},321	{0x04, 0x00, 0x02},322	{0x04, 0x00, 0x04},323	{0x04, 0x00, 0x05},324	{0x04, 0x00, 0x06},325	{0x04, 0x00, 0x07},326	{0x04, 0x00, 0x08},327	{0x04, 0x00, 0x09},328	{0x04, 0x00, 0x0a},329	{0x04, 0x00, 0x0b},330	{0x04, 0x00, 0x0c},331	{0x07, 0x00, 0x00},332	{0x07, 0x00, 0x03},333	{0x08, 0x00, 0x00},334	{0x08, 0x00, 0x01},335	{0x08, 0x00, 0x02},336	{0x06, 0x18, 0x08},337	{0x06, 0xfc, 0x09},338	{0x06, 0xfc, 0x0a},339	{0x06, 0xfc, 0x0b},340	{0x06, 0x18, 0x0c},341	{0x06, 0xfc, 0x0d},342	{0x06, 0xfc, 0x0e},343	{0x06, 0xfc, 0x0f},344	{0x06, 0x18, 0x10},345	{0x06, 0xfe, 0x12},346	{0x06, 0x00, 0x11},347	{0x06, 0x00, 0x14},348	{0x06, 0x00, 0x13},349	{0x06, 0x28, 0x51},350	{0x06, 0xff, 0x53},351	{0x02, 0x00, 0x08},352 353	{0x03, 0x00, 0x03},354	{0x03, 0x10, 0x03},355	{}356};357 358/*359 * Data to initialize the camera using the internal CCD360 */361static const u8 spca505b_open_data_ccd[][3] = {362 363/* {0x02,0x00,0x00}, */364	{0x03, 0x04, 0x01},		/* rst */365	{0x03, 0x00, 0x01},366	{0x03, 0x00, 0x00},367	{0x03, 0x21, 0x00},368	{0x03, 0x00, 0x04},369	{0x03, 0x00, 0x03},370	{0x03, 0x18, 0x03},371	{0x03, 0x08, 0x01},372	{0x03, 0x1c, 0x03},373	{0x03, 0x5c, 0x03},374	{0x03, 0x5c, 0x03},375	{0x03, 0x18, 0x01},376 377/* same as 505 */378	{0x04, 0x10, 0x01},379	{0x04, 0x00, 0x04},380	{0x04, 0x00, 0x05},381	{0x04, 0x20, 0x06},382	{0x04, 0x20, 0x07},383 384	{0x08, 0x0a, 0x00},385 386	{0x05, 0x00, 0x10},387	{0x05, 0x00, 0x11},388	{0x05, 0x00, 0x12},389	{0x05, 0x6f, 0x00},390	{0x05, initial_brightness >> 6, 0x00},391	{0x05, (initial_brightness << 2) & 0xff, 0x01},392	{0x05, 0x00, 0x02},393	{0x05, 0x01, 0x03},394	{0x05, 0x00, 0x04},395	{0x05, 0x03, 0x05},396	{0x05, 0xe0, 0x06},397	{0x05, 0x20, 0x07},398	{0x05, 0xa0, 0x08},399	{0x05, 0x00, 0x12},400	{0x05, 0x02, 0x0f},401	{0x05, 0x80, 0x14},		/* max exposure off (0=on) */402	{0x05, 0x01, 0xb0},403	{0x05, 0x01, 0xbf},404	{0x03, 0x02, 0x06},405	{0x05, 0x10, 0x46},406	{0x05, 0x08, 0x4a},407 408	{0x06, 0x00, 0x01},409	{0x06, 0x10, 0x02},410	{0x06, 0x64, 0x07},411	{0x06, 0x18, 0x08},412	{0x06, 0xfc, 0x09},413	{0x06, 0xfc, 0x0a},414	{0x06, 0xfc, 0x0b},415	{0x04, 0x00, 0x01},416	{0x06, 0x18, 0x0c},417	{0x06, 0xfc, 0x0d},418	{0x06, 0xfc, 0x0e},419	{0x06, 0xfc, 0x0f},420	{0x06, 0x11, 0x10},		/* contrast */421	{0x06, 0x00, 0x11},422	{0x06, 0xfe, 0x12},423	{0x06, 0x00, 0x13},424	{0x06, 0x00, 0x14},425	{0x06, 0x9d, 0x51},426	{0x06, 0x40, 0x52},427	{0x06, 0x7c, 0x53},428	{0x06, 0x40, 0x54},429	{0x06, 0x02, 0x57},430	{0x06, 0x03, 0x58},431	{0x06, 0x15, 0x59},432	{0x06, 0x05, 0x5a},433	{0x06, 0x03, 0x56},434	{0x06, 0x02, 0x3f},435	{0x06, 0x00, 0x40},436	{0x06, 0x39, 0x41},437	{0x06, 0x69, 0x42},438	{0x06, 0x87, 0x43},439	{0x06, 0x9e, 0x44},440	{0x06, 0xb1, 0x45},441	{0x06, 0xbf, 0x46},442	{0x06, 0xcc, 0x47},443	{0x06, 0xd5, 0x48},444	{0x06, 0xdd, 0x49},445	{0x06, 0xe3, 0x4a},446	{0x06, 0xe8, 0x4b},447	{0x06, 0xed, 0x4c},448	{0x06, 0xf2, 0x4d},449	{0x06, 0xf7, 0x4e},450	{0x06, 0xfc, 0x4f},451	{0x06, 0xff, 0x50},452 453	{0x05, 0x01, 0xc0},454	{0x05, 0x10, 0xcb},455	{0x05, 0x40, 0xc1},456	{0x05, 0x04, 0xc2},457	{0x05, 0x00, 0xca},458	{0x05, 0x40, 0xc1},459	{0x05, 0x09, 0xc2},460	{0x05, 0x00, 0xca},461	{0x05, 0xc0, 0xc1},462	{0x05, 0x09, 0xc2},463	{0x05, 0x00, 0xca},464	{0x05, 0x40, 0xc1},465	{0x05, 0x59, 0xc2},466	{0x05, 0x00, 0xca},467	{0x04, 0x00, 0x01},468	{0x05, 0x80, 0xc1},469	{0x05, 0xec, 0xc2},470	{0x05, 0x0, 0xca},471 472	{0x06, 0x02, 0x57},473	{0x06, 0x01, 0x58},474	{0x06, 0x15, 0x59},475	{0x06, 0x0a, 0x5a},476	{0x06, 0x01, 0x57},477	{0x06, 0x8a, 0x03},478	{0x06, 0x0a, 0x6c},479	{0x06, 0x30, 0x01},480	{0x06, 0x20, 0x02},481	{0x06, 0x00, 0x03},482 483	{0x05, 0x8c, 0x25},484 485	{0x06, 0x4d, 0x51},		/* maybe saturation (4d) */486	{0x06, 0x84, 0x53},		/* making green (84) */487	{0x06, 0x00, 0x57},		/* sharpness (1) */488	{0x06, 0x18, 0x08},489	{0x06, 0xfc, 0x09},490	{0x06, 0xfc, 0x0a},491	{0x06, 0xfc, 0x0b},492	{0x06, 0x18, 0x0c},		/* maybe hue (18) */493	{0x06, 0xfc, 0x0d},494	{0x06, 0xfc, 0x0e},495	{0x06, 0xfc, 0x0f},496	{0x06, 0x18, 0x10},		/* maybe contrast (18) */497 498	{0x05, 0x01, 0x02},499 500	{0x04, 0x00, 0x08},		/* compression */501	{0x04, 0x12, 0x09},502	{0x04, 0x21, 0x0a},503	{0x04, 0x10, 0x0b},504	{0x04, 0x21, 0x0c},505	{0x04, 0x1d, 0x00},		/* imagetype (1d) */506	{0x04, 0x41, 0x01},		/* hardware snapcontrol */507 508	{0x04, 0x00, 0x04},509	{0x04, 0x00, 0x05},510	{0x04, 0x10, 0x06},511	{0x04, 0x10, 0x07},512	{0x04, 0x40, 0x06},513	{0x04, 0x40, 0x07},514	{0x04, 0x00, 0x04},515	{0x04, 0x00, 0x05},516 517	{0x06, 0x1c, 0x17},518	{0x06, 0xe2, 0x19},519	{0x06, 0x1c, 0x1b},520	{0x06, 0xe2, 0x1d},521	{0x06, 0x5f, 0x1f},522	{0x06, 0x32, 0x20},523 524	{0x05, initial_brightness >> 6, 0x00},525	{0x05, (initial_brightness << 2) & 0xff, 0x01},526	{0x05, 0x06, 0xc1},527	{0x05, 0x58, 0xc2},528	{0x05, 0x00, 0xca},529	{0x05, 0x00, 0x11},530	{}531};532 533static int reg_write(struct gspca_dev *gspca_dev,534		     u16 req, u16 index, u16 value)535{536	int ret;537	struct usb_device *dev = gspca_dev->dev;538 539	ret = usb_control_msg(dev,540			usb_sndctrlpipe(dev, 0),541			req,542			USB_TYPE_VENDOR | USB_RECIP_DEVICE,543			value, index, NULL, 0, 500);544	gspca_dbg(gspca_dev, D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d\n",545		  req, index, value, ret);546	if (ret < 0)547		pr_err("reg write: error %d\n", ret);548	return ret;549}550 551/* returns: negative is error, pos or zero is data */552static int reg_read(struct gspca_dev *gspca_dev,553			u16 req,	/* bRequest */554			u16 index)	/* wIndex */555{556	int ret;557 558	ret = usb_control_msg(gspca_dev->dev,559			usb_rcvctrlpipe(gspca_dev->dev, 0),560			req,561			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,562			0,			/* value */563			index,564			gspca_dev->usb_buf, 2,565			500);			/* timeout */566	if (ret < 0)567		return ret;568	return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];569}570 571static int write_vector(struct gspca_dev *gspca_dev,572			const u8 data[][3])573{574	int ret, i = 0;575 576	while (data[i][0] != 0) {577		ret = reg_write(gspca_dev, data[i][0], data[i][2],578								data[i][1]);579		if (ret < 0)580			return ret;581		i++;582	}583	return 0;584}585 586/* this function is called at probe time */587static int sd_config(struct gspca_dev *gspca_dev,588			const struct usb_device_id *id)589{590	struct sd *sd = (struct sd *) gspca_dev;591	struct cam *cam;592 593	cam = &gspca_dev->cam;594	cam->cam_mode = vga_mode;595	sd->subtype = id->driver_info;596	if (sd->subtype != IntelPCCameraPro)597		cam->nmodes = ARRAY_SIZE(vga_mode);598	else			/* no 640x480 for IntelPCCameraPro */599		cam->nmodes = ARRAY_SIZE(vga_mode) - 1;600 601	return 0;602}603 604/* this function is called at probe and resume time */605static int sd_init(struct gspca_dev *gspca_dev)606{607	struct sd *sd = (struct sd *) gspca_dev;608 609	if (write_vector(gspca_dev,610			 sd->subtype == Nxultra611				? spca505b_init_data612				: spca505_init_data))613		return -EIO;614	return 0;615}616 617static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)618{619	reg_write(gspca_dev, 0x05, 0x00, (255 - brightness) >> 6);620	reg_write(gspca_dev, 0x05, 0x01, (255 - brightness) << 2);621}622 623static int sd_start(struct gspca_dev *gspca_dev)624{625	struct sd *sd = (struct sd *) gspca_dev;626	int ret, mode;627	static u8 mode_tb[][3] = {628	/*	  r00   r06   r07	*/629		{0x00, 0x10, 0x10},	/* 640x480 */630		{0x01, 0x1a, 0x1a},	/* 352x288 */631		{0x02, 0x1c, 0x1d},	/* 320x240 */632		{0x04, 0x34, 0x34},	/* 176x144 */633		{0x05, 0x40, 0x40}	/* 160x120 */634	};635 636	if (sd->subtype == Nxultra)637		write_vector(gspca_dev, spca505b_open_data_ccd);638	else639		write_vector(gspca_dev, spca505_open_data_ccd);640	ret = reg_read(gspca_dev, 0x06, 0x16);641 642	if (ret < 0) {643		gspca_err(gspca_dev, "register read failed err: %d\n", ret);644		return ret;645	}646	if (ret != 0x0101) {647		pr_err("After vector read returns 0x%04x should be 0x0101\n",648		       ret);649	}650 651	ret = reg_write(gspca_dev, 0x06, 0x16, 0x0a);652	if (ret < 0)653		return ret;654	reg_write(gspca_dev, 0x05, 0xc2, 0x12);655 656	/* necessary because without it we can see stream657	 * only once after loading module */658	/* stopping usb registers Tomasz change */659	reg_write(gspca_dev, 0x02, 0x00, 0x00);660 661	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;662	reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]);663	reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]);664	reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]);665 666	return reg_write(gspca_dev, SPCA50X_REG_USB,667			 SPCA50X_USB_CTRL,668			 SPCA50X_CUSB_ENABLE);669}670 671static void sd_stopN(struct gspca_dev *gspca_dev)672{673	/* Disable ISO packet machine */674	reg_write(gspca_dev, 0x02, 0x00, 0x00);675}676 677/* called on streamoff with alt 0 and on disconnect */678static void sd_stop0(struct gspca_dev *gspca_dev)679{680	if (!gspca_dev->present)681		return;682 683	/* This maybe reset or power control */684	reg_write(gspca_dev, 0x03, 0x03, 0x20);685	reg_write(gspca_dev, 0x03, 0x01, 0x00);686	reg_write(gspca_dev, 0x03, 0x00, 0x01);687	reg_write(gspca_dev, 0x05, 0x10, 0x01);688	reg_write(gspca_dev, 0x05, 0x11, 0x0f);689}690 691static void sd_pkt_scan(struct gspca_dev *gspca_dev,692			u8 *data,			/* isoc packet */693			int len)			/* iso packet length */694{695	switch (data[0]) {696	case 0:				/* start of frame */697		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);698		data += SPCA50X_OFFSET_DATA;699		len -= SPCA50X_OFFSET_DATA;700		gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);701		break;702	case 0xff:			/* drop */703		break;704	default:705		data += 1;706		len -= 1;707		gspca_frame_add(gspca_dev, INTER_PACKET, data, len);708		break;709	}710}711 712static int sd_s_ctrl(struct v4l2_ctrl *ctrl)713{714	struct gspca_dev *gspca_dev =715		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);716 717	gspca_dev->usb_err = 0;718 719	if (!gspca_dev->streaming)720		return 0;721 722	switch (ctrl->id) {723	case V4L2_CID_BRIGHTNESS:724		setbrightness(gspca_dev, ctrl->val);725		break;726	}727	return gspca_dev->usb_err;728}729 730static const struct v4l2_ctrl_ops sd_ctrl_ops = {731	.s_ctrl = sd_s_ctrl,732};733 734static int sd_init_controls(struct gspca_dev *gspca_dev)735{736	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;737 738	gspca_dev->vdev.ctrl_handler = hdl;739	v4l2_ctrl_handler_init(hdl, 5);740	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,741			V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);742 743	if (hdl->error) {744		pr_err("Could not initialize controls\n");745		return hdl->error;746	}747	return 0;748}749 750/* sub-driver description */751static const struct sd_desc sd_desc = {752	.name = MODULE_NAME,753	.config = sd_config,754	.init_controls = sd_init_controls,755	.init = sd_init,756	.start = sd_start,757	.stopN = sd_stopN,758	.stop0 = sd_stop0,759	.pkt_scan = sd_pkt_scan,760};761 762/* -- module initialisation -- */763static const struct usb_device_id device_table[] = {764	{USB_DEVICE(0x041e, 0x401d), .driver_info = Nxultra},765	{USB_DEVICE(0x0733, 0x0430), .driver_info = IntelPCCameraPro},766/*fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */767	{}768};769MODULE_DEVICE_TABLE(usb, device_table);770 771/* -- device connect -- */772static int sd_probe(struct usb_interface *intf,773			const struct usb_device_id *id)774{775	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),776				THIS_MODULE);777}778 779static struct usb_driver sd_driver = {780	.name = MODULE_NAME,781	.id_table = device_table,782	.probe = sd_probe,783	.disconnect = gspca_disconnect,784#ifdef CONFIG_PM785	.suspend = gspca_suspend,786	.resume = gspca_resume,787	.reset_resume = gspca_resume,788#endif789};790 791module_usb_driver(sd_driver);792