brintos

brintos / linux-shallow public Read only

0
0
Text · 17.9 KiB · 0886587 Raw
600 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * SPCA506 chip based cameras function4 * M Xhaard 15/04/2004 based on different work Mark Taylor and others5 * and my own snoopy file on a pv-321c donate by a german compagny6 *                "Firma Frank Gmbh" from  Saarbruecken7 *8 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>9 */10 11#define MODULE_NAME "spca506"12 13#include "gspca.h"14 15MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");16MODULE_DESCRIPTION("GSPCA/SPCA506 USB Camera Driver");17MODULE_LICENSE("GPL");18 19/* specific webcam descriptor */20struct sd {21	struct gspca_dev gspca_dev;	/* !! must be the first item */22 23	char norme;24	char channel;25};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 = 5},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 = 4},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 SAA7113_bright 0x0a	/* defaults 0x80 */58#define SAA7113_contrast 0x0b	/* defaults 0x47 */59#define SAA7113_saturation 0x0c	/* defaults 0x40 */60#define SAA7113_hue 0x0d	/* defaults 0x00 */61#define SAA7113_I2C_BASE_WRITE 0x4a62 63/* read 'len' bytes to gspca_dev->usb_buf */64static void reg_r(struct gspca_dev *gspca_dev,65		  __u16 req,66		  __u16 index,67		  __u16 length)68{69	usb_control_msg(gspca_dev->dev,70			usb_rcvctrlpipe(gspca_dev->dev, 0),71			req,72			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,73			0,		/* value */74			index, gspca_dev->usb_buf, length,75			500);76}77 78static void reg_w(struct usb_device *dev,79		  __u16 req,80		  __u16 value,81		  __u16 index)82{83	usb_control_msg(dev,84			usb_sndctrlpipe(dev, 0),85			req,86			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,87			value, index,88			NULL, 0, 500);89}90 91static void spca506_Initi2c(struct gspca_dev *gspca_dev)92{93	reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004);94}95 96static void spca506_WriteI2c(struct gspca_dev *gspca_dev, __u16 valeur,97			     __u16 reg)98{99	int retry = 60;100 101	reg_w(gspca_dev->dev, 0x07, reg, 0x0001);102	reg_w(gspca_dev->dev, 0x07, valeur, 0x0000);103	while (retry--) {104		reg_r(gspca_dev, 0x07, 0x0003, 2);105		if ((gspca_dev->usb_buf[0] | gspca_dev->usb_buf[1]) == 0x00)106			break;107	}108}109 110static void spca506_SetNormeInput(struct gspca_dev *gspca_dev,111				 __u16 norme,112				 __u16 channel)113{114	struct sd *sd = (struct sd *) gspca_dev;115/* fixme: check if channel == 0..3 and 6..9 (8 values) */116	__u8 setbit0 = 0x00;117	__u8 setbit1 = 0x00;118	__u8 videomask = 0x00;119 120	gspca_dbg(gspca_dev, D_STREAM, "** Open Set Norme **\n");121	spca506_Initi2c(gspca_dev);122	/* NTSC bit0 -> 1(525 l) PAL SECAM bit0 -> 0 (625 l) */123	/* Composite channel bit1 -> 1 S-video bit 1 -> 0 */124	/* and exclude SAA7113 reserved channel set default 0 otherwise */125	if (norme & V4L2_STD_NTSC)126		setbit0 = 0x01;127	if (channel == 4 || channel == 5 || channel > 9)128		channel = 0;129	if (channel < 4)130		setbit1 = 0x02;131	videomask = (0x48 | setbit0 | setbit1);132	reg_w(gspca_dev->dev, 0x08, videomask, 0x0000);133	spca506_WriteI2c(gspca_dev, (0xc0 | (channel & 0x0F)), 0x02);134 135	if (norme & V4L2_STD_NTSC)136		spca506_WriteI2c(gspca_dev, 0x33, 0x0e);137					/* Chrominance Control NTSC N */138	else if (norme & V4L2_STD_SECAM)139		spca506_WriteI2c(gspca_dev, 0x53, 0x0e);140					/* Chrominance Control SECAM */141	else142		spca506_WriteI2c(gspca_dev, 0x03, 0x0e);143					/* Chrominance Control PAL BGHIV */144 145	sd->norme = norme;146	sd->channel = channel;147	gspca_dbg(gspca_dev, D_STREAM, "Set Video Byte to 0x%2x\n", videomask);148	gspca_dbg(gspca_dev, D_STREAM, "Set Norme: %08x Channel %d",149		  norme, channel);150}151 152static void spca506_GetNormeInput(struct gspca_dev *gspca_dev,153				  __u16 *norme, __u16 *channel)154{155	struct sd *sd = (struct sd *) gspca_dev;156 157	/* Read the register is not so good value change so158	   we use your own copy in spca50x struct */159	*norme = sd->norme;160	*channel = sd->channel;161	gspca_dbg(gspca_dev, D_STREAM, "Get Norme: %d Channel %d\n",162		  *norme, *channel);163}164 165static void spca506_Setsize(struct gspca_dev *gspca_dev, __u16 code,166			    __u16 xmult, __u16 ymult)167{168	struct usb_device *dev = gspca_dev->dev;169 170	gspca_dbg(gspca_dev, D_STREAM, "** SetSize **\n");171	reg_w(dev, 0x04, (0x18 | (code & 0x07)), 0x0000);172	/* Soft snap 0x40 Hard 0x41 */173	reg_w(dev, 0x04, 0x41, 0x0001);174	reg_w(dev, 0x04, 0x00, 0x0002);175	/* reserved */176	reg_w(dev, 0x04, 0x00, 0x0003);177 178	/* reserved */179	reg_w(dev, 0x04, 0x00, 0x0004);180	/* reserved */181	reg_w(dev, 0x04, 0x01, 0x0005);182	/* reserced */183	reg_w(dev, 0x04, xmult, 0x0006);184	/* reserved */185	reg_w(dev, 0x04, ymult, 0x0007);186	/* compression 1 */187	reg_w(dev, 0x04, 0x00, 0x0008);188	/* T=64 -> 2 */189	reg_w(dev, 0x04, 0x00, 0x0009);190	/* threshold2D */191	reg_w(dev, 0x04, 0x21, 0x000a);192	/* quantization */193	reg_w(dev, 0x04, 0x00, 0x000b);194}195 196/* this function is called at probe time */197static int sd_config(struct gspca_dev *gspca_dev,198			const struct usb_device_id *id)199{200	struct cam *cam;201 202	cam = &gspca_dev->cam;203	cam->cam_mode = vga_mode;204	cam->nmodes = ARRAY_SIZE(vga_mode);205	return 0;206}207 208/* this function is called at probe and resume time */209static int sd_init(struct gspca_dev *gspca_dev)210{211	struct usb_device *dev = gspca_dev->dev;212 213	reg_w(dev, 0x03, 0x00, 0x0004);214	reg_w(dev, 0x03, 0xFF, 0x0003);215	reg_w(dev, 0x03, 0x00, 0x0000);216	reg_w(dev, 0x03, 0x1c, 0x0001);217	reg_w(dev, 0x03, 0x18, 0x0001);218	/* Init on PAL and composite input0 */219	spca506_SetNormeInput(gspca_dev, 0, 0);220	reg_w(dev, 0x03, 0x1c, 0x0001);221	reg_w(dev, 0x03, 0x18, 0x0001);222	reg_w(dev, 0x05, 0x00, 0x0000);223	reg_w(dev, 0x05, 0xef, 0x0001);224	reg_w(dev, 0x05, 0x00, 0x00c1);225	reg_w(dev, 0x05, 0x00, 0x00c2);226	reg_w(dev, 0x06, 0x18, 0x0002);227	reg_w(dev, 0x06, 0xf5, 0x0011);228	reg_w(dev, 0x06, 0x02, 0x0012);229	reg_w(dev, 0x06, 0xfb, 0x0013);230	reg_w(dev, 0x06, 0x00, 0x0014);231	reg_w(dev, 0x06, 0xa4, 0x0051);232	reg_w(dev, 0x06, 0x40, 0x0052);233	reg_w(dev, 0x06, 0x71, 0x0053);234	reg_w(dev, 0x06, 0x40, 0x0054);235	/************************************************/236	reg_w(dev, 0x03, 0x00, 0x0004);237	reg_w(dev, 0x03, 0x00, 0x0003);238	reg_w(dev, 0x03, 0x00, 0x0004);239	reg_w(dev, 0x03, 0xFF, 0x0003);240	reg_w(dev, 0x02, 0x00, 0x0000);241	reg_w(dev, 0x03, 0x60, 0x0000);242	reg_w(dev, 0x03, 0x18, 0x0001);243	/* for a better reading mx :)	  */244	/*sdca506_WriteI2c(value,register) */245	spca506_Initi2c(gspca_dev);246	spca506_WriteI2c(gspca_dev, 0x08, 0x01);247	spca506_WriteI2c(gspca_dev, 0xc0, 0x02);248						/* input composite video */249	spca506_WriteI2c(gspca_dev, 0x33, 0x03);250	spca506_WriteI2c(gspca_dev, 0x00, 0x04);251	spca506_WriteI2c(gspca_dev, 0x00, 0x05);252	spca506_WriteI2c(gspca_dev, 0x0d, 0x06);253	spca506_WriteI2c(gspca_dev, 0xf0, 0x07);254	spca506_WriteI2c(gspca_dev, 0x98, 0x08);255	spca506_WriteI2c(gspca_dev, 0x03, 0x09);256	spca506_WriteI2c(gspca_dev, 0x80, 0x0a);257	spca506_WriteI2c(gspca_dev, 0x47, 0x0b);258	spca506_WriteI2c(gspca_dev, 0x48, 0x0c);259	spca506_WriteI2c(gspca_dev, 0x00, 0x0d);260	spca506_WriteI2c(gspca_dev, 0x03, 0x0e);	/* Chroma Pal adjust */261	spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);262	spca506_WriteI2c(gspca_dev, 0x00, 0x10);263	spca506_WriteI2c(gspca_dev, 0x0c, 0x11);264	spca506_WriteI2c(gspca_dev, 0xb8, 0x12);265	spca506_WriteI2c(gspca_dev, 0x01, 0x13);266	spca506_WriteI2c(gspca_dev, 0x00, 0x14);267	spca506_WriteI2c(gspca_dev, 0x00, 0x15);268	spca506_WriteI2c(gspca_dev, 0x00, 0x16);269	spca506_WriteI2c(gspca_dev, 0x00, 0x17);270	spca506_WriteI2c(gspca_dev, 0x00, 0x18);271	spca506_WriteI2c(gspca_dev, 0x00, 0x19);272	spca506_WriteI2c(gspca_dev, 0x00, 0x1a);273	spca506_WriteI2c(gspca_dev, 0x00, 0x1b);274	spca506_WriteI2c(gspca_dev, 0x00, 0x1c);275	spca506_WriteI2c(gspca_dev, 0x00, 0x1d);276	spca506_WriteI2c(gspca_dev, 0x00, 0x1e);277	spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);278	spca506_WriteI2c(gspca_dev, 0x02, 0x40);279	spca506_WriteI2c(gspca_dev, 0xff, 0x41);280	spca506_WriteI2c(gspca_dev, 0xff, 0x42);281	spca506_WriteI2c(gspca_dev, 0xff, 0x43);282	spca506_WriteI2c(gspca_dev, 0xff, 0x44);283	spca506_WriteI2c(gspca_dev, 0xff, 0x45);284	spca506_WriteI2c(gspca_dev, 0xff, 0x46);285	spca506_WriteI2c(gspca_dev, 0xff, 0x47);286	spca506_WriteI2c(gspca_dev, 0xff, 0x48);287	spca506_WriteI2c(gspca_dev, 0xff, 0x49);288	spca506_WriteI2c(gspca_dev, 0xff, 0x4a);289	spca506_WriteI2c(gspca_dev, 0xff, 0x4b);290	spca506_WriteI2c(gspca_dev, 0xff, 0x4c);291	spca506_WriteI2c(gspca_dev, 0xff, 0x4d);292	spca506_WriteI2c(gspca_dev, 0xff, 0x4e);293	spca506_WriteI2c(gspca_dev, 0xff, 0x4f);294	spca506_WriteI2c(gspca_dev, 0xff, 0x50);295	spca506_WriteI2c(gspca_dev, 0xff, 0x51);296	spca506_WriteI2c(gspca_dev, 0xff, 0x52);297	spca506_WriteI2c(gspca_dev, 0xff, 0x53);298	spca506_WriteI2c(gspca_dev, 0xff, 0x54);299	spca506_WriteI2c(gspca_dev, 0xff, 0x55);300	spca506_WriteI2c(gspca_dev, 0xff, 0x56);301	spca506_WriteI2c(gspca_dev, 0xff, 0x57);302	spca506_WriteI2c(gspca_dev, 0x00, 0x58);303	spca506_WriteI2c(gspca_dev, 0x54, 0x59);304	spca506_WriteI2c(gspca_dev, 0x07, 0x5a);305	spca506_WriteI2c(gspca_dev, 0x83, 0x5b);306	spca506_WriteI2c(gspca_dev, 0x00, 0x5c);307	spca506_WriteI2c(gspca_dev, 0x00, 0x5d);308	spca506_WriteI2c(gspca_dev, 0x00, 0x5e);309	spca506_WriteI2c(gspca_dev, 0x00, 0x5f);310	spca506_WriteI2c(gspca_dev, 0x00, 0x60);311	spca506_WriteI2c(gspca_dev, 0x05, 0x61);312	spca506_WriteI2c(gspca_dev, 0x9f, 0x62);313	gspca_dbg(gspca_dev, D_STREAM, "** Close Init *\n");314	return 0;315}316 317static int sd_start(struct gspca_dev *gspca_dev)318{319	struct usb_device *dev = gspca_dev->dev;320	__u16 norme;321	__u16 channel;322 323	/**************************************/324	reg_w(dev, 0x03, 0x00, 0x0004);325	reg_w(dev, 0x03, 0x00, 0x0003);326	reg_w(dev, 0x03, 0x00, 0x0004);327	reg_w(dev, 0x03, 0xFF, 0x0003);328	reg_w(dev, 0x02, 0x00, 0x0000);329	reg_w(dev, 0x03, 0x60, 0x0000);330	reg_w(dev, 0x03, 0x18, 0x0001);331 332	/*sdca506_WriteI2c(value,register) */333	spca506_Initi2c(gspca_dev);334	spca506_WriteI2c(gspca_dev, 0x08, 0x01);	/* Increment Delay */335/*	spca506_WriteI2c(gspca_dev, 0xc0, 0x02); * Analog Input Control 1 */336	spca506_WriteI2c(gspca_dev, 0x33, 0x03);337						/* Analog Input Control 2 */338	spca506_WriteI2c(gspca_dev, 0x00, 0x04);339						/* Analog Input Control 3 */340	spca506_WriteI2c(gspca_dev, 0x00, 0x05);341						/* Analog Input Control 4 */342	spca506_WriteI2c(gspca_dev, 0x0d, 0x06);343					/* Horizontal Sync Start 0xe9-0x0d */344	spca506_WriteI2c(gspca_dev, 0xf0, 0x07);345					/* Horizontal Sync Stop  0x0d-0xf0 */346 347	spca506_WriteI2c(gspca_dev, 0x98, 0x08);	/* Sync Control */348/*		Defaults value			*/349	spca506_WriteI2c(gspca_dev, 0x03, 0x09);	/* Luminance Control */350	spca506_WriteI2c(gspca_dev, 0x80, 0x0a);351						/* Luminance Brightness */352	spca506_WriteI2c(gspca_dev, 0x47, 0x0b);	/* Luminance Contrast */353	spca506_WriteI2c(gspca_dev, 0x48, 0x0c);354						/* Chrominance Saturation */355	spca506_WriteI2c(gspca_dev, 0x00, 0x0d);356						/* Chrominance Hue Control */357	spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);358						/* Chrominance Gain Control */359	/**************************************/360	spca506_WriteI2c(gspca_dev, 0x00, 0x10);361						/* Format/Delay Control */362	spca506_WriteI2c(gspca_dev, 0x0c, 0x11);	/* Output Control 1 */363	spca506_WriteI2c(gspca_dev, 0xb8, 0x12);	/* Output Control 2 */364	spca506_WriteI2c(gspca_dev, 0x01, 0x13);	/* Output Control 3 */365	spca506_WriteI2c(gspca_dev, 0x00, 0x14);	/* reserved */366	spca506_WriteI2c(gspca_dev, 0x00, 0x15);	/* VGATE START */367	spca506_WriteI2c(gspca_dev, 0x00, 0x16);	/* VGATE STOP */368	spca506_WriteI2c(gspca_dev, 0x00, 0x17);    /* VGATE Control (MSB) */369	spca506_WriteI2c(gspca_dev, 0x00, 0x18);370	spca506_WriteI2c(gspca_dev, 0x00, 0x19);371	spca506_WriteI2c(gspca_dev, 0x00, 0x1a);372	spca506_WriteI2c(gspca_dev, 0x00, 0x1b);373	spca506_WriteI2c(gspca_dev, 0x00, 0x1c);374	spca506_WriteI2c(gspca_dev, 0x00, 0x1d);375	spca506_WriteI2c(gspca_dev, 0x00, 0x1e);376	spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);377	spca506_WriteI2c(gspca_dev, 0x02, 0x40);378	spca506_WriteI2c(gspca_dev, 0xff, 0x41);379	spca506_WriteI2c(gspca_dev, 0xff, 0x42);380	spca506_WriteI2c(gspca_dev, 0xff, 0x43);381	spca506_WriteI2c(gspca_dev, 0xff, 0x44);382	spca506_WriteI2c(gspca_dev, 0xff, 0x45);383	spca506_WriteI2c(gspca_dev, 0xff, 0x46);384	spca506_WriteI2c(gspca_dev, 0xff, 0x47);385	spca506_WriteI2c(gspca_dev, 0xff, 0x48);386	spca506_WriteI2c(gspca_dev, 0xff, 0x49);387	spca506_WriteI2c(gspca_dev, 0xff, 0x4a);388	spca506_WriteI2c(gspca_dev, 0xff, 0x4b);389	spca506_WriteI2c(gspca_dev, 0xff, 0x4c);390	spca506_WriteI2c(gspca_dev, 0xff, 0x4d);391	spca506_WriteI2c(gspca_dev, 0xff, 0x4e);392	spca506_WriteI2c(gspca_dev, 0xff, 0x4f);393	spca506_WriteI2c(gspca_dev, 0xff, 0x50);394	spca506_WriteI2c(gspca_dev, 0xff, 0x51);395	spca506_WriteI2c(gspca_dev, 0xff, 0x52);396	spca506_WriteI2c(gspca_dev, 0xff, 0x53);397	spca506_WriteI2c(gspca_dev, 0xff, 0x54);398	spca506_WriteI2c(gspca_dev, 0xff, 0x55);399	spca506_WriteI2c(gspca_dev, 0xff, 0x56);400	spca506_WriteI2c(gspca_dev, 0xff, 0x57);401	spca506_WriteI2c(gspca_dev, 0x00, 0x58);402	spca506_WriteI2c(gspca_dev, 0x54, 0x59);403	spca506_WriteI2c(gspca_dev, 0x07, 0x5a);404	spca506_WriteI2c(gspca_dev, 0x83, 0x5b);405	spca506_WriteI2c(gspca_dev, 0x00, 0x5c);406	spca506_WriteI2c(gspca_dev, 0x00, 0x5d);407	spca506_WriteI2c(gspca_dev, 0x00, 0x5e);408	spca506_WriteI2c(gspca_dev, 0x00, 0x5f);409	spca506_WriteI2c(gspca_dev, 0x00, 0x60);410	spca506_WriteI2c(gspca_dev, 0x05, 0x61);411	spca506_WriteI2c(gspca_dev, 0x9f, 0x62);412	/**************************************/413	reg_w(dev, 0x05, 0x00, 0x0003);414	reg_w(dev, 0x05, 0x00, 0x0004);415	reg_w(dev, 0x03, 0x10, 0x0001);416	reg_w(dev, 0x03, 0x78, 0x0000);417	switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {418	case 0:419		spca506_Setsize(gspca_dev, 0, 0x10, 0x10);420		break;421	case 1:422		spca506_Setsize(gspca_dev, 1, 0x1a, 0x1a);423		break;424	case 2:425		spca506_Setsize(gspca_dev, 2, 0x1c, 0x1c);426		break;427	case 4:428		spca506_Setsize(gspca_dev, 4, 0x34, 0x34);429		break;430	default:431/*	case 5: */432		spca506_Setsize(gspca_dev, 5, 0x40, 0x40);433		break;434	}435 436	/* compress setting and size */437	/* set i2c luma */438	reg_w(dev, 0x02, 0x01, 0x0000);439	reg_w(dev, 0x03, 0x12, 0x0000);440	reg_r(gspca_dev, 0x04, 0x0001, 2);441	gspca_dbg(gspca_dev, D_STREAM, "webcam started\n");442	spca506_GetNormeInput(gspca_dev, &norme, &channel);443	spca506_SetNormeInput(gspca_dev, norme, channel);444	return 0;445}446 447static void sd_stopN(struct gspca_dev *gspca_dev)448{449	struct usb_device *dev = gspca_dev->dev;450 451	reg_w(dev, 0x02, 0x00, 0x0000);452	reg_w(dev, 0x03, 0x00, 0x0004);453	reg_w(dev, 0x03, 0x00, 0x0003);454}455 456static void sd_pkt_scan(struct gspca_dev *gspca_dev,457			u8 *data,			/* isoc packet */458			int len)			/* iso packet length */459{460	switch (data[0]) {461	case 0:				/* start of frame */462		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);463		data += SPCA50X_OFFSET_DATA;464		len -= SPCA50X_OFFSET_DATA;465		gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);466		break;467	case 0xff:			/* drop */468/*		gspca_dev->last_packet_type = DISCARD_PACKET; */469		break;470	default:471		data += 1;472		len -= 1;473		gspca_frame_add(gspca_dev, INTER_PACKET, data, len);474		break;475	}476}477 478static void setbrightness(struct gspca_dev *gspca_dev, s32 val)479{480	spca506_Initi2c(gspca_dev);481	spca506_WriteI2c(gspca_dev, val, SAA7113_bright);482	spca506_WriteI2c(gspca_dev, 0x01, 0x09);483}484 485static void setcontrast(struct gspca_dev *gspca_dev, s32 val)486{487	spca506_Initi2c(gspca_dev);488	spca506_WriteI2c(gspca_dev, val, SAA7113_contrast);489	spca506_WriteI2c(gspca_dev, 0x01, 0x09);490}491 492static void setcolors(struct gspca_dev *gspca_dev, s32 val)493{494	spca506_Initi2c(gspca_dev);495	spca506_WriteI2c(gspca_dev, val, SAA7113_saturation);496	spca506_WriteI2c(gspca_dev, 0x01, 0x09);497}498 499static void sethue(struct gspca_dev *gspca_dev, s32 val)500{501	spca506_Initi2c(gspca_dev);502	spca506_WriteI2c(gspca_dev, val, SAA7113_hue);503	spca506_WriteI2c(gspca_dev, 0x01, 0x09);504}505 506static int sd_s_ctrl(struct v4l2_ctrl *ctrl)507{508	struct gspca_dev *gspca_dev =509		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);510 511	gspca_dev->usb_err = 0;512 513	if (!gspca_dev->streaming)514		return 0;515 516	switch (ctrl->id) {517	case V4L2_CID_BRIGHTNESS:518		setbrightness(gspca_dev, ctrl->val);519		break;520	case V4L2_CID_CONTRAST:521		setcontrast(gspca_dev, ctrl->val);522		break;523	case V4L2_CID_SATURATION:524		setcolors(gspca_dev, ctrl->val);525		break;526	case V4L2_CID_HUE:527		sethue(gspca_dev, ctrl->val);528		break;529	}530	return gspca_dev->usb_err;531}532 533static const struct v4l2_ctrl_ops sd_ctrl_ops = {534	.s_ctrl = sd_s_ctrl,535};536 537static int sd_init_controls(struct gspca_dev *gspca_dev)538{539	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;540 541	gspca_dev->vdev.ctrl_handler = hdl;542	v4l2_ctrl_handler_init(hdl, 4);543	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,544			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);545	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,546			V4L2_CID_CONTRAST, 0, 255, 1, 0x47);547	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,548			V4L2_CID_SATURATION, 0, 255, 1, 0x40);549	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,550			V4L2_CID_HUE, 0, 255, 1, 0);551 552	if (hdl->error) {553		pr_err("Could not initialize controls\n");554		return hdl->error;555	}556	return 0;557}558 559/* sub-driver description */560static const struct sd_desc sd_desc = {561	.name = MODULE_NAME,562	.config = sd_config,563	.init = sd_init,564	.init_controls = sd_init_controls,565	.start = sd_start,566	.stopN = sd_stopN,567	.pkt_scan = sd_pkt_scan,568};569 570/* -- module initialisation -- */571static const struct usb_device_id device_table[] = {572	{USB_DEVICE(0x06e1, 0xa190)},573/*	{USB_DEVICE(0x0733, 0x0430)}, FIXME: may be IntelPCCameraPro BRIDGE_SPCA505 */574	{USB_DEVICE(0x0734, 0x043b)},575	{USB_DEVICE(0x99fa, 0x8988)},576	{}577};578MODULE_DEVICE_TABLE(usb, device_table);579 580/* -- device connect -- */581static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)582{583	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),584				THIS_MODULE);585}586 587static struct usb_driver sd_driver = {588	.name = MODULE_NAME,589	.id_table = device_table,590	.probe = sd_probe,591	.disconnect = gspca_disconnect,592#ifdef CONFIG_PM593	.suspend = gspca_suspend,594	.resume = gspca_resume,595	.reset_resume = gspca_resume,596#endif597};598 599module_usb_driver(sd_driver);600