18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * SPCA506 chip based cameras function
48c2ecf20Sopenharmony_ci * M Xhaard 15/04/2004 based on different work Mark Taylor and others
58c2ecf20Sopenharmony_ci * and my own snoopy file on a pv-321c donate by a german compagny
68c2ecf20Sopenharmony_ci *                "Firma Frank Gmbh" from  Saarbruecken
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#define MODULE_NAME "spca506"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include "gspca.h"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ciMODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
168c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("GSPCA/SPCA506 USB Camera Driver");
178c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/* specific webcam descriptor */
208c2ecf20Sopenharmony_cistruct sd {
218c2ecf20Sopenharmony_ci	struct gspca_dev gspca_dev;	/* !! must be the first item */
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	char norme;
248c2ecf20Sopenharmony_ci	char channel;
258c2ecf20Sopenharmony_ci};
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format vga_mode[] = {
288c2ecf20Sopenharmony_ci	{160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
298c2ecf20Sopenharmony_ci		.bytesperline = 160,
308c2ecf20Sopenharmony_ci		.sizeimage = 160 * 120 * 3 / 2,
318c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
328c2ecf20Sopenharmony_ci		.priv = 5},
338c2ecf20Sopenharmony_ci	{176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
348c2ecf20Sopenharmony_ci		.bytesperline = 176,
358c2ecf20Sopenharmony_ci		.sizeimage = 176 * 144 * 3 / 2,
368c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
378c2ecf20Sopenharmony_ci		.priv = 4},
388c2ecf20Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
398c2ecf20Sopenharmony_ci		.bytesperline = 320,
408c2ecf20Sopenharmony_ci		.sizeimage = 320 * 240 * 3 / 2,
418c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
428c2ecf20Sopenharmony_ci		.priv = 2},
438c2ecf20Sopenharmony_ci	{352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
448c2ecf20Sopenharmony_ci		.bytesperline = 352,
458c2ecf20Sopenharmony_ci		.sizeimage = 352 * 288 * 3 / 2,
468c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
478c2ecf20Sopenharmony_ci		.priv = 1},
488c2ecf20Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
498c2ecf20Sopenharmony_ci		.bytesperline = 640,
508c2ecf20Sopenharmony_ci		.sizeimage = 640 * 480 * 3 / 2,
518c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
528c2ecf20Sopenharmony_ci		.priv = 0},
538c2ecf20Sopenharmony_ci};
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define SPCA50X_OFFSET_DATA 10
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#define SAA7113_bright 0x0a	/* defaults 0x80 */
588c2ecf20Sopenharmony_ci#define SAA7113_contrast 0x0b	/* defaults 0x47 */
598c2ecf20Sopenharmony_ci#define SAA7113_saturation 0x0c	/* defaults 0x40 */
608c2ecf20Sopenharmony_ci#define SAA7113_hue 0x0d	/* defaults 0x00 */
618c2ecf20Sopenharmony_ci#define SAA7113_I2C_BASE_WRITE 0x4a
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci/* read 'len' bytes to gspca_dev->usb_buf */
648c2ecf20Sopenharmony_cistatic void reg_r(struct gspca_dev *gspca_dev,
658c2ecf20Sopenharmony_ci		  __u16 req,
668c2ecf20Sopenharmony_ci		  __u16 index,
678c2ecf20Sopenharmony_ci		  __u16 length)
688c2ecf20Sopenharmony_ci{
698c2ecf20Sopenharmony_ci	usb_control_msg(gspca_dev->dev,
708c2ecf20Sopenharmony_ci			usb_rcvctrlpipe(gspca_dev->dev, 0),
718c2ecf20Sopenharmony_ci			req,
728c2ecf20Sopenharmony_ci			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
738c2ecf20Sopenharmony_ci			0,		/* value */
748c2ecf20Sopenharmony_ci			index, gspca_dev->usb_buf, length,
758c2ecf20Sopenharmony_ci			500);
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cistatic void reg_w(struct usb_device *dev,
798c2ecf20Sopenharmony_ci		  __u16 req,
808c2ecf20Sopenharmony_ci		  __u16 value,
818c2ecf20Sopenharmony_ci		  __u16 index)
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	usb_control_msg(dev,
848c2ecf20Sopenharmony_ci			usb_sndctrlpipe(dev, 0),
858c2ecf20Sopenharmony_ci			req,
868c2ecf20Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
878c2ecf20Sopenharmony_ci			value, index,
888c2ecf20Sopenharmony_ci			NULL, 0, 500);
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic void spca506_Initi2c(struct gspca_dev *gspca_dev)
928c2ecf20Sopenharmony_ci{
938c2ecf20Sopenharmony_ci	reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004);
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_cistatic void spca506_WriteI2c(struct gspca_dev *gspca_dev, __u16 valeur,
978c2ecf20Sopenharmony_ci			     __u16 reg)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	int retry = 60;
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	reg_w(gspca_dev->dev, 0x07, reg, 0x0001);
1028c2ecf20Sopenharmony_ci	reg_w(gspca_dev->dev, 0x07, valeur, 0x0000);
1038c2ecf20Sopenharmony_ci	while (retry--) {
1048c2ecf20Sopenharmony_ci		reg_r(gspca_dev, 0x07, 0x0003, 2);
1058c2ecf20Sopenharmony_ci		if ((gspca_dev->usb_buf[0] | gspca_dev->usb_buf[1]) == 0x00)
1068c2ecf20Sopenharmony_ci			break;
1078c2ecf20Sopenharmony_ci	}
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistatic void spca506_SetNormeInput(struct gspca_dev *gspca_dev,
1118c2ecf20Sopenharmony_ci				 __u16 norme,
1128c2ecf20Sopenharmony_ci				 __u16 channel)
1138c2ecf20Sopenharmony_ci{
1148c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
1158c2ecf20Sopenharmony_ci/* fixme: check if channel == 0..3 and 6..9 (8 values) */
1168c2ecf20Sopenharmony_ci	__u8 setbit0 = 0x00;
1178c2ecf20Sopenharmony_ci	__u8 setbit1 = 0x00;
1188c2ecf20Sopenharmony_ci	__u8 videomask = 0x00;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_STREAM, "** Open Set Norme **\n");
1218c2ecf20Sopenharmony_ci	spca506_Initi2c(gspca_dev);
1228c2ecf20Sopenharmony_ci	/* NTSC bit0 -> 1(525 l) PAL SECAM bit0 -> 0 (625 l) */
1238c2ecf20Sopenharmony_ci	/* Composite channel bit1 -> 1 S-video bit 1 -> 0 */
1248c2ecf20Sopenharmony_ci	/* and exclude SAA7113 reserved channel set default 0 otherwise */
1258c2ecf20Sopenharmony_ci	if (norme & V4L2_STD_NTSC)
1268c2ecf20Sopenharmony_ci		setbit0 = 0x01;
1278c2ecf20Sopenharmony_ci	if (channel == 4 || channel == 5 || channel > 9)
1288c2ecf20Sopenharmony_ci		channel = 0;
1298c2ecf20Sopenharmony_ci	if (channel < 4)
1308c2ecf20Sopenharmony_ci		setbit1 = 0x02;
1318c2ecf20Sopenharmony_ci	videomask = (0x48 | setbit0 | setbit1);
1328c2ecf20Sopenharmony_ci	reg_w(gspca_dev->dev, 0x08, videomask, 0x0000);
1338c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, (0xc0 | (channel & 0x0F)), 0x02);
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	if (norme & V4L2_STD_NTSC)
1368c2ecf20Sopenharmony_ci		spca506_WriteI2c(gspca_dev, 0x33, 0x0e);
1378c2ecf20Sopenharmony_ci					/* Chrominance Control NTSC N */
1388c2ecf20Sopenharmony_ci	else if (norme & V4L2_STD_SECAM)
1398c2ecf20Sopenharmony_ci		spca506_WriteI2c(gspca_dev, 0x53, 0x0e);
1408c2ecf20Sopenharmony_ci					/* Chrominance Control SECAM */
1418c2ecf20Sopenharmony_ci	else
1428c2ecf20Sopenharmony_ci		spca506_WriteI2c(gspca_dev, 0x03, 0x0e);
1438c2ecf20Sopenharmony_ci					/* Chrominance Control PAL BGHIV */
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	sd->norme = norme;
1468c2ecf20Sopenharmony_ci	sd->channel = channel;
1478c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_STREAM, "Set Video Byte to 0x%2x\n", videomask);
1488c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_STREAM, "Set Norme: %08x Channel %d",
1498c2ecf20Sopenharmony_ci		  norme, channel);
1508c2ecf20Sopenharmony_ci}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_cistatic void spca506_GetNormeInput(struct gspca_dev *gspca_dev,
1538c2ecf20Sopenharmony_ci				  __u16 *norme, __u16 *channel)
1548c2ecf20Sopenharmony_ci{
1558c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	/* Read the register is not so good value change so
1588c2ecf20Sopenharmony_ci	   we use your own copy in spca50x struct */
1598c2ecf20Sopenharmony_ci	*norme = sd->norme;
1608c2ecf20Sopenharmony_ci	*channel = sd->channel;
1618c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_STREAM, "Get Norme: %d Channel %d\n",
1628c2ecf20Sopenharmony_ci		  *norme, *channel);
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_cistatic void spca506_Setsize(struct gspca_dev *gspca_dev, __u16 code,
1668c2ecf20Sopenharmony_ci			    __u16 xmult, __u16 ymult)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	struct usb_device *dev = gspca_dev->dev;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_STREAM, "** SetSize **\n");
1718c2ecf20Sopenharmony_ci	reg_w(dev, 0x04, (0x18 | (code & 0x07)), 0x0000);
1728c2ecf20Sopenharmony_ci	/* Soft snap 0x40 Hard 0x41 */
1738c2ecf20Sopenharmony_ci	reg_w(dev, 0x04, 0x41, 0x0001);
1748c2ecf20Sopenharmony_ci	reg_w(dev, 0x04, 0x00, 0x0002);
1758c2ecf20Sopenharmony_ci	/* reserved */
1768c2ecf20Sopenharmony_ci	reg_w(dev, 0x04, 0x00, 0x0003);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	/* reserved */
1798c2ecf20Sopenharmony_ci	reg_w(dev, 0x04, 0x00, 0x0004);
1808c2ecf20Sopenharmony_ci	/* reserved */
1818c2ecf20Sopenharmony_ci	reg_w(dev, 0x04, 0x01, 0x0005);
1828c2ecf20Sopenharmony_ci	/* reserced */
1838c2ecf20Sopenharmony_ci	reg_w(dev, 0x04, xmult, 0x0006);
1848c2ecf20Sopenharmony_ci	/* reserved */
1858c2ecf20Sopenharmony_ci	reg_w(dev, 0x04, ymult, 0x0007);
1868c2ecf20Sopenharmony_ci	/* compression 1 */
1878c2ecf20Sopenharmony_ci	reg_w(dev, 0x04, 0x00, 0x0008);
1888c2ecf20Sopenharmony_ci	/* T=64 -> 2 */
1898c2ecf20Sopenharmony_ci	reg_w(dev, 0x04, 0x00, 0x0009);
1908c2ecf20Sopenharmony_ci	/* threshold2D */
1918c2ecf20Sopenharmony_ci	reg_w(dev, 0x04, 0x21, 0x000a);
1928c2ecf20Sopenharmony_ci	/* quantization */
1938c2ecf20Sopenharmony_ci	reg_w(dev, 0x04, 0x00, 0x000b);
1948c2ecf20Sopenharmony_ci}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci/* this function is called at probe time */
1978c2ecf20Sopenharmony_cistatic int sd_config(struct gspca_dev *gspca_dev,
1988c2ecf20Sopenharmony_ci			const struct usb_device_id *id)
1998c2ecf20Sopenharmony_ci{
2008c2ecf20Sopenharmony_ci	struct cam *cam;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	cam = &gspca_dev->cam;
2038c2ecf20Sopenharmony_ci	cam->cam_mode = vga_mode;
2048c2ecf20Sopenharmony_ci	cam->nmodes = ARRAY_SIZE(vga_mode);
2058c2ecf20Sopenharmony_ci	return 0;
2068c2ecf20Sopenharmony_ci}
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci/* this function is called at probe and resume time */
2098c2ecf20Sopenharmony_cistatic int sd_init(struct gspca_dev *gspca_dev)
2108c2ecf20Sopenharmony_ci{
2118c2ecf20Sopenharmony_ci	struct usb_device *dev = gspca_dev->dev;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x00, 0x0004);
2148c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0xFF, 0x0003);
2158c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x00, 0x0000);
2168c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x1c, 0x0001);
2178c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x18, 0x0001);
2188c2ecf20Sopenharmony_ci	/* Init on PAL and composite input0 */
2198c2ecf20Sopenharmony_ci	spca506_SetNormeInput(gspca_dev, 0, 0);
2208c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x1c, 0x0001);
2218c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x18, 0x0001);
2228c2ecf20Sopenharmony_ci	reg_w(dev, 0x05, 0x00, 0x0000);
2238c2ecf20Sopenharmony_ci	reg_w(dev, 0x05, 0xef, 0x0001);
2248c2ecf20Sopenharmony_ci	reg_w(dev, 0x05, 0x00, 0x00c1);
2258c2ecf20Sopenharmony_ci	reg_w(dev, 0x05, 0x00, 0x00c2);
2268c2ecf20Sopenharmony_ci	reg_w(dev, 0x06, 0x18, 0x0002);
2278c2ecf20Sopenharmony_ci	reg_w(dev, 0x06, 0xf5, 0x0011);
2288c2ecf20Sopenharmony_ci	reg_w(dev, 0x06, 0x02, 0x0012);
2298c2ecf20Sopenharmony_ci	reg_w(dev, 0x06, 0xfb, 0x0013);
2308c2ecf20Sopenharmony_ci	reg_w(dev, 0x06, 0x00, 0x0014);
2318c2ecf20Sopenharmony_ci	reg_w(dev, 0x06, 0xa4, 0x0051);
2328c2ecf20Sopenharmony_ci	reg_w(dev, 0x06, 0x40, 0x0052);
2338c2ecf20Sopenharmony_ci	reg_w(dev, 0x06, 0x71, 0x0053);
2348c2ecf20Sopenharmony_ci	reg_w(dev, 0x06, 0x40, 0x0054);
2358c2ecf20Sopenharmony_ci	/************************************************/
2368c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x00, 0x0004);
2378c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x00, 0x0003);
2388c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x00, 0x0004);
2398c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0xFF, 0x0003);
2408c2ecf20Sopenharmony_ci	reg_w(dev, 0x02, 0x00, 0x0000);
2418c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x60, 0x0000);
2428c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x18, 0x0001);
2438c2ecf20Sopenharmony_ci	/* for a better reading mx :)	  */
2448c2ecf20Sopenharmony_ci	/*sdca506_WriteI2c(value,register) */
2458c2ecf20Sopenharmony_ci	spca506_Initi2c(gspca_dev);
2468c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x08, 0x01);
2478c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xc0, 0x02);
2488c2ecf20Sopenharmony_ci						/* input composite video */
2498c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x33, 0x03);
2508c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x04);
2518c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x05);
2528c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
2538c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
2548c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x98, 0x08);
2558c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x03, 0x09);
2568c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
2578c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x47, 0x0b);
2588c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
2598c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
2608c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x03, 0x0e);	/* Chroma Pal adjust */
2618c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
2628c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x10);
2638c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x0c, 0x11);
2648c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xb8, 0x12);
2658c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x01, 0x13);
2668c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x14);
2678c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x15);
2688c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x16);
2698c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x17);
2708c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x18);
2718c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x19);
2728c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
2738c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
2748c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
2758c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
2768c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
2778c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
2788c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x02, 0x40);
2798c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x41);
2808c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x42);
2818c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x43);
2828c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x44);
2838c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x45);
2848c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x46);
2858c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x47);
2868c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x48);
2878c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x49);
2888c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
2898c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
2908c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
2918c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
2928c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
2938c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
2948c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x50);
2958c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x51);
2968c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x52);
2978c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x53);
2988c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x54);
2998c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x55);
3008c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x56);
3018c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x57);
3028c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x58);
3038c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x54, 0x59);
3048c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
3058c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
3068c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
3078c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
3088c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
3098c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
3108c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x60);
3118c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x05, 0x61);
3128c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
3138c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_STREAM, "** Close Init *\n");
3148c2ecf20Sopenharmony_ci	return 0;
3158c2ecf20Sopenharmony_ci}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_cistatic int sd_start(struct gspca_dev *gspca_dev)
3188c2ecf20Sopenharmony_ci{
3198c2ecf20Sopenharmony_ci	struct usb_device *dev = gspca_dev->dev;
3208c2ecf20Sopenharmony_ci	__u16 norme;
3218c2ecf20Sopenharmony_ci	__u16 channel;
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	/**************************************/
3248c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x00, 0x0004);
3258c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x00, 0x0003);
3268c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x00, 0x0004);
3278c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0xFF, 0x0003);
3288c2ecf20Sopenharmony_ci	reg_w(dev, 0x02, 0x00, 0x0000);
3298c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x60, 0x0000);
3308c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x18, 0x0001);
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	/*sdca506_WriteI2c(value,register) */
3338c2ecf20Sopenharmony_ci	spca506_Initi2c(gspca_dev);
3348c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x08, 0x01);	/* Increment Delay */
3358c2ecf20Sopenharmony_ci/*	spca506_WriteI2c(gspca_dev, 0xc0, 0x02); * Analog Input Control 1 */
3368c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x33, 0x03);
3378c2ecf20Sopenharmony_ci						/* Analog Input Control 2 */
3388c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x04);
3398c2ecf20Sopenharmony_ci						/* Analog Input Control 3 */
3408c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x05);
3418c2ecf20Sopenharmony_ci						/* Analog Input Control 4 */
3428c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
3438c2ecf20Sopenharmony_ci					/* Horizontal Sync Start 0xe9-0x0d */
3448c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
3458c2ecf20Sopenharmony_ci					/* Horizontal Sync Stop  0x0d-0xf0 */
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x98, 0x08);	/* Sync Control */
3488c2ecf20Sopenharmony_ci/*		Defaults value			*/
3498c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x03, 0x09);	/* Luminance Control */
3508c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
3518c2ecf20Sopenharmony_ci						/* Luminance Brightness */
3528c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x47, 0x0b);	/* Luminance Contrast */
3538c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
3548c2ecf20Sopenharmony_ci						/* Chrominance Saturation */
3558c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
3568c2ecf20Sopenharmony_ci						/* Chrominance Hue Control */
3578c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
3588c2ecf20Sopenharmony_ci						/* Chrominance Gain Control */
3598c2ecf20Sopenharmony_ci	/**************************************/
3608c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x10);
3618c2ecf20Sopenharmony_ci						/* Format/Delay Control */
3628c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x0c, 0x11);	/* Output Control 1 */
3638c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xb8, 0x12);	/* Output Control 2 */
3648c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x01, 0x13);	/* Output Control 3 */
3658c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x14);	/* reserved */
3668c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x15);	/* VGATE START */
3678c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x16);	/* VGATE STOP */
3688c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x17);    /* VGATE Control (MSB) */
3698c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x18);
3708c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x19);
3718c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
3728c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
3738c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
3748c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
3758c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
3768c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
3778c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x02, 0x40);
3788c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x41);
3798c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x42);
3808c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x43);
3818c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x44);
3828c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x45);
3838c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x46);
3848c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x47);
3858c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x48);
3868c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x49);
3878c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
3888c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
3898c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
3908c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
3918c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
3928c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
3938c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x50);
3948c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x51);
3958c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x52);
3968c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x53);
3978c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x54);
3988c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x55);
3998c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x56);
4008c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0xff, 0x57);
4018c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x58);
4028c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x54, 0x59);
4038c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
4048c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
4058c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
4068c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
4078c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
4088c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
4098c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x00, 0x60);
4108c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x05, 0x61);
4118c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
4128c2ecf20Sopenharmony_ci	/**************************************/
4138c2ecf20Sopenharmony_ci	reg_w(dev, 0x05, 0x00, 0x0003);
4148c2ecf20Sopenharmony_ci	reg_w(dev, 0x05, 0x00, 0x0004);
4158c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x10, 0x0001);
4168c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x78, 0x0000);
4178c2ecf20Sopenharmony_ci	switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
4188c2ecf20Sopenharmony_ci	case 0:
4198c2ecf20Sopenharmony_ci		spca506_Setsize(gspca_dev, 0, 0x10, 0x10);
4208c2ecf20Sopenharmony_ci		break;
4218c2ecf20Sopenharmony_ci	case 1:
4228c2ecf20Sopenharmony_ci		spca506_Setsize(gspca_dev, 1, 0x1a, 0x1a);
4238c2ecf20Sopenharmony_ci		break;
4248c2ecf20Sopenharmony_ci	case 2:
4258c2ecf20Sopenharmony_ci		spca506_Setsize(gspca_dev, 2, 0x1c, 0x1c);
4268c2ecf20Sopenharmony_ci		break;
4278c2ecf20Sopenharmony_ci	case 4:
4288c2ecf20Sopenharmony_ci		spca506_Setsize(gspca_dev, 4, 0x34, 0x34);
4298c2ecf20Sopenharmony_ci		break;
4308c2ecf20Sopenharmony_ci	default:
4318c2ecf20Sopenharmony_ci/*	case 5: */
4328c2ecf20Sopenharmony_ci		spca506_Setsize(gspca_dev, 5, 0x40, 0x40);
4338c2ecf20Sopenharmony_ci		break;
4348c2ecf20Sopenharmony_ci	}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	/* compress setting and size */
4378c2ecf20Sopenharmony_ci	/* set i2c luma */
4388c2ecf20Sopenharmony_ci	reg_w(dev, 0x02, 0x01, 0x0000);
4398c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x12, 0x0000);
4408c2ecf20Sopenharmony_ci	reg_r(gspca_dev, 0x04, 0x0001, 2);
4418c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_STREAM, "webcam started\n");
4428c2ecf20Sopenharmony_ci	spca506_GetNormeInput(gspca_dev, &norme, &channel);
4438c2ecf20Sopenharmony_ci	spca506_SetNormeInput(gspca_dev, norme, channel);
4448c2ecf20Sopenharmony_ci	return 0;
4458c2ecf20Sopenharmony_ci}
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_cistatic void sd_stopN(struct gspca_dev *gspca_dev)
4488c2ecf20Sopenharmony_ci{
4498c2ecf20Sopenharmony_ci	struct usb_device *dev = gspca_dev->dev;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	reg_w(dev, 0x02, 0x00, 0x0000);
4528c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x00, 0x0004);
4538c2ecf20Sopenharmony_ci	reg_w(dev, 0x03, 0x00, 0x0003);
4548c2ecf20Sopenharmony_ci}
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_cistatic void sd_pkt_scan(struct gspca_dev *gspca_dev,
4578c2ecf20Sopenharmony_ci			u8 *data,			/* isoc packet */
4588c2ecf20Sopenharmony_ci			int len)			/* iso packet length */
4598c2ecf20Sopenharmony_ci{
4608c2ecf20Sopenharmony_ci	switch (data[0]) {
4618c2ecf20Sopenharmony_ci	case 0:				/* start of frame */
4628c2ecf20Sopenharmony_ci		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
4638c2ecf20Sopenharmony_ci		data += SPCA50X_OFFSET_DATA;
4648c2ecf20Sopenharmony_ci		len -= SPCA50X_OFFSET_DATA;
4658c2ecf20Sopenharmony_ci		gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
4668c2ecf20Sopenharmony_ci		break;
4678c2ecf20Sopenharmony_ci	case 0xff:			/* drop */
4688c2ecf20Sopenharmony_ci/*		gspca_dev->last_packet_type = DISCARD_PACKET; */
4698c2ecf20Sopenharmony_ci		break;
4708c2ecf20Sopenharmony_ci	default:
4718c2ecf20Sopenharmony_ci		data += 1;
4728c2ecf20Sopenharmony_ci		len -= 1;
4738c2ecf20Sopenharmony_ci		gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
4748c2ecf20Sopenharmony_ci		break;
4758c2ecf20Sopenharmony_ci	}
4768c2ecf20Sopenharmony_ci}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_cistatic void setbrightness(struct gspca_dev *gspca_dev, s32 val)
4798c2ecf20Sopenharmony_ci{
4808c2ecf20Sopenharmony_ci	spca506_Initi2c(gspca_dev);
4818c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, val, SAA7113_bright);
4828c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x01, 0x09);
4838c2ecf20Sopenharmony_ci}
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_cistatic void setcontrast(struct gspca_dev *gspca_dev, s32 val)
4868c2ecf20Sopenharmony_ci{
4878c2ecf20Sopenharmony_ci	spca506_Initi2c(gspca_dev);
4888c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, val, SAA7113_contrast);
4898c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x01, 0x09);
4908c2ecf20Sopenharmony_ci}
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_cistatic void setcolors(struct gspca_dev *gspca_dev, s32 val)
4938c2ecf20Sopenharmony_ci{
4948c2ecf20Sopenharmony_ci	spca506_Initi2c(gspca_dev);
4958c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, val, SAA7113_saturation);
4968c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x01, 0x09);
4978c2ecf20Sopenharmony_ci}
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_cistatic void sethue(struct gspca_dev *gspca_dev, s32 val)
5008c2ecf20Sopenharmony_ci{
5018c2ecf20Sopenharmony_ci	spca506_Initi2c(gspca_dev);
5028c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, val, SAA7113_hue);
5038c2ecf20Sopenharmony_ci	spca506_WriteI2c(gspca_dev, 0x01, 0x09);
5048c2ecf20Sopenharmony_ci}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_cistatic int sd_s_ctrl(struct v4l2_ctrl *ctrl)
5078c2ecf20Sopenharmony_ci{
5088c2ecf20Sopenharmony_ci	struct gspca_dev *gspca_dev =
5098c2ecf20Sopenharmony_ci		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	gspca_dev->usb_err = 0;
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	if (!gspca_dev->streaming)
5148c2ecf20Sopenharmony_ci		return 0;
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	switch (ctrl->id) {
5178c2ecf20Sopenharmony_ci	case V4L2_CID_BRIGHTNESS:
5188c2ecf20Sopenharmony_ci		setbrightness(gspca_dev, ctrl->val);
5198c2ecf20Sopenharmony_ci		break;
5208c2ecf20Sopenharmony_ci	case V4L2_CID_CONTRAST:
5218c2ecf20Sopenharmony_ci		setcontrast(gspca_dev, ctrl->val);
5228c2ecf20Sopenharmony_ci		break;
5238c2ecf20Sopenharmony_ci	case V4L2_CID_SATURATION:
5248c2ecf20Sopenharmony_ci		setcolors(gspca_dev, ctrl->val);
5258c2ecf20Sopenharmony_ci		break;
5268c2ecf20Sopenharmony_ci	case V4L2_CID_HUE:
5278c2ecf20Sopenharmony_ci		sethue(gspca_dev, ctrl->val);
5288c2ecf20Sopenharmony_ci		break;
5298c2ecf20Sopenharmony_ci	}
5308c2ecf20Sopenharmony_ci	return gspca_dev->usb_err;
5318c2ecf20Sopenharmony_ci}
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops sd_ctrl_ops = {
5348c2ecf20Sopenharmony_ci	.s_ctrl = sd_s_ctrl,
5358c2ecf20Sopenharmony_ci};
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_cistatic int sd_init_controls(struct gspca_dev *gspca_dev)
5388c2ecf20Sopenharmony_ci{
5398c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	gspca_dev->vdev.ctrl_handler = hdl;
5428c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl, 4);
5438c2ecf20Sopenharmony_ci	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
5448c2ecf20Sopenharmony_ci			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
5458c2ecf20Sopenharmony_ci	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
5468c2ecf20Sopenharmony_ci			V4L2_CID_CONTRAST, 0, 255, 1, 0x47);
5478c2ecf20Sopenharmony_ci	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
5488c2ecf20Sopenharmony_ci			V4L2_CID_SATURATION, 0, 255, 1, 0x40);
5498c2ecf20Sopenharmony_ci	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
5508c2ecf20Sopenharmony_ci			V4L2_CID_HUE, 0, 255, 1, 0);
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	if (hdl->error) {
5538c2ecf20Sopenharmony_ci		pr_err("Could not initialize controls\n");
5548c2ecf20Sopenharmony_ci		return hdl->error;
5558c2ecf20Sopenharmony_ci	}
5568c2ecf20Sopenharmony_ci	return 0;
5578c2ecf20Sopenharmony_ci}
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci/* sub-driver description */
5608c2ecf20Sopenharmony_cistatic const struct sd_desc sd_desc = {
5618c2ecf20Sopenharmony_ci	.name = MODULE_NAME,
5628c2ecf20Sopenharmony_ci	.config = sd_config,
5638c2ecf20Sopenharmony_ci	.init = sd_init,
5648c2ecf20Sopenharmony_ci	.init_controls = sd_init_controls,
5658c2ecf20Sopenharmony_ci	.start = sd_start,
5668c2ecf20Sopenharmony_ci	.stopN = sd_stopN,
5678c2ecf20Sopenharmony_ci	.pkt_scan = sd_pkt_scan,
5688c2ecf20Sopenharmony_ci};
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci/* -- module initialisation -- */
5718c2ecf20Sopenharmony_cistatic const struct usb_device_id device_table[] = {
5728c2ecf20Sopenharmony_ci	{USB_DEVICE(0x06e1, 0xa190)},
5738c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0733, 0x0430)}, FIXME: may be IntelPCCameraPro BRIDGE_SPCA505 */
5748c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0734, 0x043b)},
5758c2ecf20Sopenharmony_ci	{USB_DEVICE(0x99fa, 0x8988)},
5768c2ecf20Sopenharmony_ci	{}
5778c2ecf20Sopenharmony_ci};
5788c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, device_table);
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci/* -- device connect -- */
5818c2ecf20Sopenharmony_cistatic int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
5828c2ecf20Sopenharmony_ci{
5838c2ecf20Sopenharmony_ci	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
5848c2ecf20Sopenharmony_ci				THIS_MODULE);
5858c2ecf20Sopenharmony_ci}
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_cistatic struct usb_driver sd_driver = {
5888c2ecf20Sopenharmony_ci	.name = MODULE_NAME,
5898c2ecf20Sopenharmony_ci	.id_table = device_table,
5908c2ecf20Sopenharmony_ci	.probe = sd_probe,
5918c2ecf20Sopenharmony_ci	.disconnect = gspca_disconnect,
5928c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
5938c2ecf20Sopenharmony_ci	.suspend = gspca_suspend,
5948c2ecf20Sopenharmony_ci	.resume = gspca_resume,
5958c2ecf20Sopenharmony_ci	.reset_resume = gspca_resume,
5968c2ecf20Sopenharmony_ci#endif
5978c2ecf20Sopenharmony_ci};
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_cimodule_usb_driver(sd_driver);
600