162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *		Connexant Cx11646 library
462306a36Sopenharmony_ci *		Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#define MODULE_NAME "conex"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include "gspca.h"
1462306a36Sopenharmony_ci#define CONEX_CAM 1		/* special JPEG header */
1562306a36Sopenharmony_ci#include "jpeg.h"
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ciMODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
1862306a36Sopenharmony_ciMODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
1962306a36Sopenharmony_ciMODULE_LICENSE("GPL");
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define QUALITY 50
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/* specific webcam descriptor */
2462306a36Sopenharmony_cistruct sd {
2562306a36Sopenharmony_ci	struct gspca_dev gspca_dev;	/* !! must be the first item */
2662306a36Sopenharmony_ci	struct v4l2_ctrl *brightness;
2762306a36Sopenharmony_ci	struct v4l2_ctrl *contrast;
2862306a36Sopenharmony_ci	struct v4l2_ctrl *sat;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	u8 jpeg_hdr[JPEG_HDR_SZ];
3162306a36Sopenharmony_ci};
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_cistatic const struct v4l2_pix_format vga_mode[] = {
3462306a36Sopenharmony_ci	{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
3562306a36Sopenharmony_ci		.bytesperline = 176,
3662306a36Sopenharmony_ci		.sizeimage = 176 * 144 * 3 / 8 + 590,
3762306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
3862306a36Sopenharmony_ci		.priv = 3},
3962306a36Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
4062306a36Sopenharmony_ci		.bytesperline = 320,
4162306a36Sopenharmony_ci		.sizeimage = 320 * 240 * 3 / 8 + 590,
4262306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
4362306a36Sopenharmony_ci		.priv = 2},
4462306a36Sopenharmony_ci	{352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
4562306a36Sopenharmony_ci		.bytesperline = 352,
4662306a36Sopenharmony_ci		.sizeimage = 352 * 288 * 3 / 8 + 590,
4762306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
4862306a36Sopenharmony_ci		.priv = 1},
4962306a36Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
5062306a36Sopenharmony_ci		.bytesperline = 640,
5162306a36Sopenharmony_ci		.sizeimage = 640 * 480 * 3 / 8 + 590,
5262306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
5362306a36Sopenharmony_ci		.priv = 0},
5462306a36Sopenharmony_ci};
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/* the read bytes are found in gspca_dev->usb_buf */
5762306a36Sopenharmony_cistatic void reg_r(struct gspca_dev *gspca_dev,
5862306a36Sopenharmony_ci		  __u16 index,
5962306a36Sopenharmony_ci		  __u16 len)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	struct usb_device *dev = gspca_dev->dev;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	if (len > USB_BUF_SZ) {
6462306a36Sopenharmony_ci		gspca_err(gspca_dev, "reg_r: buffer overflow\n");
6562306a36Sopenharmony_ci		return;
6662306a36Sopenharmony_ci	}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	usb_control_msg(dev,
6962306a36Sopenharmony_ci			usb_rcvctrlpipe(dev, 0),
7062306a36Sopenharmony_ci			0,
7162306a36Sopenharmony_ci			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
7262306a36Sopenharmony_ci			0,
7362306a36Sopenharmony_ci			index, gspca_dev->usb_buf, len,
7462306a36Sopenharmony_ci			500);
7562306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBI, "reg read [%02x] -> %02x ..\n",
7662306a36Sopenharmony_ci		  index, gspca_dev->usb_buf[0]);
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci/* the bytes to write are in gspca_dev->usb_buf */
8062306a36Sopenharmony_cistatic void reg_w_val(struct gspca_dev *gspca_dev,
8162306a36Sopenharmony_ci			__u16 index,
8262306a36Sopenharmony_ci			__u8 val)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	struct usb_device *dev = gspca_dev->dev;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	gspca_dev->usb_buf[0] = val;
8762306a36Sopenharmony_ci	usb_control_msg(dev,
8862306a36Sopenharmony_ci			usb_sndctrlpipe(dev, 0),
8962306a36Sopenharmony_ci			0,
9062306a36Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
9162306a36Sopenharmony_ci			0,
9262306a36Sopenharmony_ci			index, gspca_dev->usb_buf, 1, 500);
9362306a36Sopenharmony_ci}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistatic void reg_w(struct gspca_dev *gspca_dev,
9662306a36Sopenharmony_ci		  __u16 index,
9762306a36Sopenharmony_ci		  const __u8 *buffer,
9862306a36Sopenharmony_ci		  __u16 len)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	struct usb_device *dev = gspca_dev->dev;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	if (len > USB_BUF_SZ) {
10362306a36Sopenharmony_ci		gspca_err(gspca_dev, "reg_w: buffer overflow\n");
10462306a36Sopenharmony_ci		return;
10562306a36Sopenharmony_ci	}
10662306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBO, "reg write [%02x] = %02x..\n",
10762306a36Sopenharmony_ci		  index, *buffer);
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	memcpy(gspca_dev->usb_buf, buffer, len);
11062306a36Sopenharmony_ci	usb_control_msg(dev,
11162306a36Sopenharmony_ci			usb_sndctrlpipe(dev, 0),
11262306a36Sopenharmony_ci			0,
11362306a36Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
11462306a36Sopenharmony_ci			0,
11562306a36Sopenharmony_ci			index, gspca_dev->usb_buf, len, 500);
11662306a36Sopenharmony_ci}
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_cistatic const __u8 cx_sensor_init[][4] = {
11962306a36Sopenharmony_ci	{0x88, 0x11, 0x01, 0x01},
12062306a36Sopenharmony_ci	{0x88, 0x12, 0x70, 0x01},
12162306a36Sopenharmony_ci	{0x88, 0x0f, 0x00, 0x01},
12262306a36Sopenharmony_ci	{0x88, 0x05, 0x01, 0x01},
12362306a36Sopenharmony_ci	{}
12462306a36Sopenharmony_ci};
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cistatic const __u8 cx11646_fw1[][3] = {
12762306a36Sopenharmony_ci	{0x00, 0x02, 0x00},
12862306a36Sopenharmony_ci	{0x01, 0x43, 0x00},
12962306a36Sopenharmony_ci	{0x02, 0xA7, 0x00},
13062306a36Sopenharmony_ci	{0x03, 0x8B, 0x01},
13162306a36Sopenharmony_ci	{0x04, 0xE9, 0x02},
13262306a36Sopenharmony_ci	{0x05, 0x08, 0x04},
13362306a36Sopenharmony_ci	{0x06, 0x08, 0x05},
13462306a36Sopenharmony_ci	{0x07, 0x07, 0x06},
13562306a36Sopenharmony_ci	{0x08, 0xE7, 0x06},
13662306a36Sopenharmony_ci	{0x09, 0xC6, 0x07},
13762306a36Sopenharmony_ci	{0x0A, 0x86, 0x08},
13862306a36Sopenharmony_ci	{0x0B, 0x46, 0x09},
13962306a36Sopenharmony_ci	{0x0C, 0x05, 0x0A},
14062306a36Sopenharmony_ci	{0x0D, 0xA5, 0x0A},
14162306a36Sopenharmony_ci	{0x0E, 0x45, 0x0B},
14262306a36Sopenharmony_ci	{0x0F, 0xE5, 0x0B},
14362306a36Sopenharmony_ci	{0x10, 0x85, 0x0C},
14462306a36Sopenharmony_ci	{0x11, 0x25, 0x0D},
14562306a36Sopenharmony_ci	{0x12, 0xC4, 0x0D},
14662306a36Sopenharmony_ci	{0x13, 0x45, 0x0E},
14762306a36Sopenharmony_ci	{0x14, 0xE4, 0x0E},
14862306a36Sopenharmony_ci	{0x15, 0x64, 0x0F},
14962306a36Sopenharmony_ci	{0x16, 0xE4, 0x0F},
15062306a36Sopenharmony_ci	{0x17, 0x64, 0x10},
15162306a36Sopenharmony_ci	{0x18, 0xE4, 0x10},
15262306a36Sopenharmony_ci	{0x19, 0x64, 0x11},
15362306a36Sopenharmony_ci	{0x1A, 0xE4, 0x11},
15462306a36Sopenharmony_ci	{0x1B, 0x64, 0x12},
15562306a36Sopenharmony_ci	{0x1C, 0xE3, 0x12},
15662306a36Sopenharmony_ci	{0x1D, 0x44, 0x13},
15762306a36Sopenharmony_ci	{0x1E, 0xC3, 0x13},
15862306a36Sopenharmony_ci	{0x1F, 0x24, 0x14},
15962306a36Sopenharmony_ci	{0x20, 0xA3, 0x14},
16062306a36Sopenharmony_ci	{0x21, 0x04, 0x15},
16162306a36Sopenharmony_ci	{0x22, 0x83, 0x15},
16262306a36Sopenharmony_ci	{0x23, 0xE3, 0x15},
16362306a36Sopenharmony_ci	{0x24, 0x43, 0x16},
16462306a36Sopenharmony_ci	{0x25, 0xA4, 0x16},
16562306a36Sopenharmony_ci	{0x26, 0x23, 0x17},
16662306a36Sopenharmony_ci	{0x27, 0x83, 0x17},
16762306a36Sopenharmony_ci	{0x28, 0xE3, 0x17},
16862306a36Sopenharmony_ci	{0x29, 0x43, 0x18},
16962306a36Sopenharmony_ci	{0x2A, 0xA3, 0x18},
17062306a36Sopenharmony_ci	{0x2B, 0x03, 0x19},
17162306a36Sopenharmony_ci	{0x2C, 0x63, 0x19},
17262306a36Sopenharmony_ci	{0x2D, 0xC3, 0x19},
17362306a36Sopenharmony_ci	{0x2E, 0x22, 0x1A},
17462306a36Sopenharmony_ci	{0x2F, 0x63, 0x1A},
17562306a36Sopenharmony_ci	{0x30, 0xC3, 0x1A},
17662306a36Sopenharmony_ci	{0x31, 0x23, 0x1B},
17762306a36Sopenharmony_ci	{0x32, 0x83, 0x1B},
17862306a36Sopenharmony_ci	{0x33, 0xE2, 0x1B},
17962306a36Sopenharmony_ci	{0x34, 0x23, 0x1C},
18062306a36Sopenharmony_ci	{0x35, 0x83, 0x1C},
18162306a36Sopenharmony_ci	{0x36, 0xE2, 0x1C},
18262306a36Sopenharmony_ci	{0x37, 0x23, 0x1D},
18362306a36Sopenharmony_ci	{0x38, 0x83, 0x1D},
18462306a36Sopenharmony_ci	{0x39, 0xE2, 0x1D},
18562306a36Sopenharmony_ci	{0x3A, 0x23, 0x1E},
18662306a36Sopenharmony_ci	{0x3B, 0x82, 0x1E},
18762306a36Sopenharmony_ci	{0x3C, 0xC3, 0x1E},
18862306a36Sopenharmony_ci	{0x3D, 0x22, 0x1F},
18962306a36Sopenharmony_ci	{0x3E, 0x63, 0x1F},
19062306a36Sopenharmony_ci	{0x3F, 0xC1, 0x1F},
19162306a36Sopenharmony_ci	{}
19262306a36Sopenharmony_ci};
19362306a36Sopenharmony_cistatic void cx11646_fw(struct gspca_dev*gspca_dev)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	int i = 0;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x006a, 0x02);
19862306a36Sopenharmony_ci	while (cx11646_fw1[i][1]) {
19962306a36Sopenharmony_ci		reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
20062306a36Sopenharmony_ci		i++;
20162306a36Sopenharmony_ci	}
20262306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x006a, 0x00);
20362306a36Sopenharmony_ci}
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_cistatic const __u8 cxsensor[] = {
20662306a36Sopenharmony_ci	0x88, 0x12, 0x70, 0x01,
20762306a36Sopenharmony_ci	0x88, 0x0d, 0x02, 0x01,
20862306a36Sopenharmony_ci	0x88, 0x0f, 0x00, 0x01,
20962306a36Sopenharmony_ci	0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01,	/* 3 */
21062306a36Sopenharmony_ci	0x88, 0x02, 0x10, 0x01,
21162306a36Sopenharmony_ci	0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01,	/* 5 */
21262306a36Sopenharmony_ci	0x88, 0x0B, 0x00, 0x01,
21362306a36Sopenharmony_ci	0x88, 0x0A, 0x0A, 0x01,
21462306a36Sopenharmony_ci	0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01,	/* 8 */
21562306a36Sopenharmony_ci	0x88, 0x05, 0x01, 0x01,
21662306a36Sopenharmony_ci	0xA1, 0x18, 0x00, 0x01,
21762306a36Sopenharmony_ci	0x00
21862306a36Sopenharmony_ci};
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_cistatic const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
22162306a36Sopenharmony_cistatic const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
22262306a36Sopenharmony_cistatic const __u8 reg10[] = { 0xb1, 0xb1 };
22362306a36Sopenharmony_cistatic const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e };	/* 640 */
22462306a36Sopenharmony_cistatic const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
22562306a36Sopenharmony_ci	/* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
22662306a36Sopenharmony_cistatic const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
22762306a36Sopenharmony_ci					/* 320{0x04,0x0c,0x05,0x0f}; //320 */
22862306a36Sopenharmony_cistatic const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 };	/* 176 */
22962306a36Sopenharmony_cistatic const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_cistatic void cx_sensor(struct gspca_dev*gspca_dev)
23262306a36Sopenharmony_ci{
23362306a36Sopenharmony_ci	int i = 0;
23462306a36Sopenharmony_ci	int length;
23562306a36Sopenharmony_ci	const __u8 *ptsensor = cxsensor;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0020, reg20, 8);
23862306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0028, reg28, 8);
23962306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0010, reg10, 2);
24062306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0092, 0x03);
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
24362306a36Sopenharmony_ci	case 0:
24462306a36Sopenharmony_ci		reg_w(gspca_dev, 0x0071, reg71a, 4);
24562306a36Sopenharmony_ci		break;
24662306a36Sopenharmony_ci	case 1:
24762306a36Sopenharmony_ci		reg_w(gspca_dev, 0x0071, reg71b, 4);
24862306a36Sopenharmony_ci		break;
24962306a36Sopenharmony_ci	default:
25062306a36Sopenharmony_ci/*	case 2: */
25162306a36Sopenharmony_ci		reg_w(gspca_dev, 0x0071, reg71c, 4);
25262306a36Sopenharmony_ci		break;
25362306a36Sopenharmony_ci	case 3:
25462306a36Sopenharmony_ci		reg_w(gspca_dev, 0x0071, reg71d, 4);
25562306a36Sopenharmony_ci		break;
25662306a36Sopenharmony_ci	}
25762306a36Sopenharmony_ci	reg_w(gspca_dev, 0x007b, reg7b, 6);
25862306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x00f8, 0x00);
25962306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0010, reg10, 2);
26062306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0098, 0x41);
26162306a36Sopenharmony_ci	for (i = 0; i < 11; i++) {
26262306a36Sopenharmony_ci		if (i == 3 || i == 5 || i == 8)
26362306a36Sopenharmony_ci			length = 8;
26462306a36Sopenharmony_ci		else
26562306a36Sopenharmony_ci			length = 4;
26662306a36Sopenharmony_ci		reg_w(gspca_dev, 0x00e5, ptsensor, length);
26762306a36Sopenharmony_ci		if (length == 4)
26862306a36Sopenharmony_ci			reg_r(gspca_dev, 0x00e8, 1);
26962306a36Sopenharmony_ci		else
27062306a36Sopenharmony_ci			reg_r(gspca_dev, 0x00e8, length);
27162306a36Sopenharmony_ci		ptsensor += length;
27262306a36Sopenharmony_ci	}
27362306a36Sopenharmony_ci	reg_r(gspca_dev, 0x00e7, 8);
27462306a36Sopenharmony_ci}
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_cistatic const __u8 cx_inits_176[] = {
27762306a36Sopenharmony_ci	0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03,	/* 176x144 */
27862306a36Sopenharmony_ci	0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
27962306a36Sopenharmony_ci	0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
28062306a36Sopenharmony_ci	0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
28162306a36Sopenharmony_ci	0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
28262306a36Sopenharmony_ci	0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
28362306a36Sopenharmony_ci	0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
28462306a36Sopenharmony_ci};
28562306a36Sopenharmony_cistatic const __u8 cx_inits_320[] = {
28662306a36Sopenharmony_ci	0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
28762306a36Sopenharmony_ci	0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
28862306a36Sopenharmony_ci	0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
28962306a36Sopenharmony_ci	0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
29062306a36Sopenharmony_ci	0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
29162306a36Sopenharmony_ci	0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
29262306a36Sopenharmony_ci	0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
29362306a36Sopenharmony_ci};
29462306a36Sopenharmony_cistatic const __u8 cx_inits_352[] = {
29562306a36Sopenharmony_ci	0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
29662306a36Sopenharmony_ci	0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
29762306a36Sopenharmony_ci	0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
29862306a36Sopenharmony_ci	0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
29962306a36Sopenharmony_ci	0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
30062306a36Sopenharmony_ci	0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
30162306a36Sopenharmony_ci	0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
30262306a36Sopenharmony_ci};
30362306a36Sopenharmony_cistatic const __u8 cx_inits_640[] = {
30462306a36Sopenharmony_ci	0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
30562306a36Sopenharmony_ci	0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
30662306a36Sopenharmony_ci	0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
30762306a36Sopenharmony_ci	0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
30862306a36Sopenharmony_ci	0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
30962306a36Sopenharmony_ci	0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
31062306a36Sopenharmony_ci	0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
31162306a36Sopenharmony_ci};
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_cistatic void cx11646_initsize(struct gspca_dev *gspca_dev)
31462306a36Sopenharmony_ci{
31562306a36Sopenharmony_ci	const __u8 *cxinit;
31662306a36Sopenharmony_ci	static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
31762306a36Sopenharmony_ci	static const __u8 reg17[] =
31862306a36Sopenharmony_ci			{ 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
32162306a36Sopenharmony_ci	case 0:
32262306a36Sopenharmony_ci		cxinit = cx_inits_640;
32362306a36Sopenharmony_ci		break;
32462306a36Sopenharmony_ci	case 1:
32562306a36Sopenharmony_ci		cxinit = cx_inits_352;
32662306a36Sopenharmony_ci		break;
32762306a36Sopenharmony_ci	default:
32862306a36Sopenharmony_ci/*	case 2: */
32962306a36Sopenharmony_ci		cxinit = cx_inits_320;
33062306a36Sopenharmony_ci		break;
33162306a36Sopenharmony_ci	case 3:
33262306a36Sopenharmony_ci		cxinit = cx_inits_176;
33362306a36Sopenharmony_ci		break;
33462306a36Sopenharmony_ci	}
33562306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x009a, 0x01);
33662306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0010, 0x10);
33762306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0012, reg12, 5);
33862306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0017, reg17, 8);
33962306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x00c0, 0x00);
34062306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x00c1, 0x04);
34162306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x00c2, 0x04);
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0061, cxinit, 8);
34462306a36Sopenharmony_ci	cxinit += 8;
34562306a36Sopenharmony_ci	reg_w(gspca_dev, 0x00ca, cxinit, 8);
34662306a36Sopenharmony_ci	cxinit += 8;
34762306a36Sopenharmony_ci	reg_w(gspca_dev, 0x00d2, cxinit, 8);
34862306a36Sopenharmony_ci	cxinit += 8;
34962306a36Sopenharmony_ci	reg_w(gspca_dev, 0x00da, cxinit, 6);
35062306a36Sopenharmony_ci	cxinit += 8;
35162306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0041, cxinit, 8);
35262306a36Sopenharmony_ci	cxinit += 8;
35362306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0049, cxinit, 8);
35462306a36Sopenharmony_ci	cxinit += 8;
35562306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0051, cxinit, 2);
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0010, 1);
35862306a36Sopenharmony_ci}
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_cistatic const __u8 cx_jpeg_init[][8] = {
36162306a36Sopenharmony_ci	{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15},	/* 1 */
36262306a36Sopenharmony_ci	{0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
36362306a36Sopenharmony_ci	{0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
36462306a36Sopenharmony_ci	{0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
36562306a36Sopenharmony_ci	{0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
36662306a36Sopenharmony_ci	{0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
36762306a36Sopenharmony_ci	{0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
36862306a36Sopenharmony_ci	{0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
36962306a36Sopenharmony_ci	{0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
37062306a36Sopenharmony_ci	{0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
37162306a36Sopenharmony_ci	{0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
37262306a36Sopenharmony_ci	{0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
37362306a36Sopenharmony_ci	{0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
37462306a36Sopenharmony_ci	{0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
37562306a36Sopenharmony_ci	{0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
37662306a36Sopenharmony_ci	{0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
37762306a36Sopenharmony_ci	{0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
37862306a36Sopenharmony_ci	{0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
37962306a36Sopenharmony_ci	{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
38062306a36Sopenharmony_ci	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
38162306a36Sopenharmony_ci	{0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
38262306a36Sopenharmony_ci	{0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
38362306a36Sopenharmony_ci	{0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
38462306a36Sopenharmony_ci	{0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
38562306a36Sopenharmony_ci	{0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
38662306a36Sopenharmony_ci	{0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
38762306a36Sopenharmony_ci	{0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
38862306a36Sopenharmony_ci	{0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
38962306a36Sopenharmony_ci	{0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
39062306a36Sopenharmony_ci	{0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
39162306a36Sopenharmony_ci	{0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
39262306a36Sopenharmony_ci	{0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
39362306a36Sopenharmony_ci	{0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
39462306a36Sopenharmony_ci	{0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
39562306a36Sopenharmony_ci	{0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
39662306a36Sopenharmony_ci	{0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
39762306a36Sopenharmony_ci	{0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
39862306a36Sopenharmony_ci	{0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
39962306a36Sopenharmony_ci	{0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
40062306a36Sopenharmony_ci	{0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
40162306a36Sopenharmony_ci	{0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
40262306a36Sopenharmony_ci	{0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
40362306a36Sopenharmony_ci	{0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
40462306a36Sopenharmony_ci	{0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
40562306a36Sopenharmony_ci	{0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
40662306a36Sopenharmony_ci	{0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
40762306a36Sopenharmony_ci	{0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
40862306a36Sopenharmony_ci	{0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
40962306a36Sopenharmony_ci	{0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
41062306a36Sopenharmony_ci	{0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
41162306a36Sopenharmony_ci	{0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
41262306a36Sopenharmony_ci	{0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
41362306a36Sopenharmony_ci	{0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
41462306a36Sopenharmony_ci	{0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
41562306a36Sopenharmony_ci	{0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
41662306a36Sopenharmony_ci	{0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
41762306a36Sopenharmony_ci	{0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
41862306a36Sopenharmony_ci	{0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
41962306a36Sopenharmony_ci	{0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
42062306a36Sopenharmony_ci	{0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
42162306a36Sopenharmony_ci	{0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
42262306a36Sopenharmony_ci	{0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
42362306a36Sopenharmony_ci	{0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
42462306a36Sopenharmony_ci	{0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
42562306a36Sopenharmony_ci	{0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
42662306a36Sopenharmony_ci	{0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
42762306a36Sopenharmony_ci	{0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
42862306a36Sopenharmony_ci	{0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
42962306a36Sopenharmony_ci	{0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
43062306a36Sopenharmony_ci	{0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
43162306a36Sopenharmony_ci	{0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
43262306a36Sopenharmony_ci	{0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
43362306a36Sopenharmony_ci	{0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
43462306a36Sopenharmony_ci	{0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
43562306a36Sopenharmony_ci	{0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
43662306a36Sopenharmony_ci	{0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
43762306a36Sopenharmony_ci	{0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
43862306a36Sopenharmony_ci	{0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
43962306a36Sopenharmony_ci	{0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00}	/* 79 */
44062306a36Sopenharmony_ci};
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_cistatic const __u8 cxjpeg_640[][8] = {
44462306a36Sopenharmony_ci	{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10},	/* 1 */
44562306a36Sopenharmony_ci	{0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
44662306a36Sopenharmony_ci	{0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
44762306a36Sopenharmony_ci	{0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
44862306a36Sopenharmony_ci	{0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
44962306a36Sopenharmony_ci	{0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
45062306a36Sopenharmony_ci	{0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
45162306a36Sopenharmony_ci	{0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
45262306a36Sopenharmony_ci	{0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
45362306a36Sopenharmony_ci	{0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
45462306a36Sopenharmony_ci	{0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
45562306a36Sopenharmony_ci	{0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
45662306a36Sopenharmony_ci	{0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
45762306a36Sopenharmony_ci	{0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
45862306a36Sopenharmony_ci	{0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
45962306a36Sopenharmony_ci	{0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
46062306a36Sopenharmony_ci	{0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
46162306a36Sopenharmony_ci	{0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
46262306a36Sopenharmony_ci	{0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
46362306a36Sopenharmony_ci	{0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
46462306a36Sopenharmony_ci	{0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
46562306a36Sopenharmony_ci	{0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
46662306a36Sopenharmony_ci	{0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
46762306a36Sopenharmony_ci	{0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
46862306a36Sopenharmony_ci	{0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
46962306a36Sopenharmony_ci	{0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
47062306a36Sopenharmony_ci	{0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}	/* 27 */
47162306a36Sopenharmony_ci};
47262306a36Sopenharmony_cistatic const __u8 cxjpeg_352[][8] = {
47362306a36Sopenharmony_ci	{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
47462306a36Sopenharmony_ci	{0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
47562306a36Sopenharmony_ci	{0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
47662306a36Sopenharmony_ci	{0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
47762306a36Sopenharmony_ci	{0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
47862306a36Sopenharmony_ci	{0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
47962306a36Sopenharmony_ci	{0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
48062306a36Sopenharmony_ci	{0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
48162306a36Sopenharmony_ci	{0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
48262306a36Sopenharmony_ci	{0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
48362306a36Sopenharmony_ci	{0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
48462306a36Sopenharmony_ci	{0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
48562306a36Sopenharmony_ci	{0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
48662306a36Sopenharmony_ci	{0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
48762306a36Sopenharmony_ci	{0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
48862306a36Sopenharmony_ci	{0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
48962306a36Sopenharmony_ci	{0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
49062306a36Sopenharmony_ci	{0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
49162306a36Sopenharmony_ci	{0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
49262306a36Sopenharmony_ci	{0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
49362306a36Sopenharmony_ci	{0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
49462306a36Sopenharmony_ci	{0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
49562306a36Sopenharmony_ci	{0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
49662306a36Sopenharmony_ci	{0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
49762306a36Sopenharmony_ci	{0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
49862306a36Sopenharmony_ci	{0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
49962306a36Sopenharmony_ci	{0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
50062306a36Sopenharmony_ci};
50162306a36Sopenharmony_cistatic const __u8 cxjpeg_320[][8] = {
50262306a36Sopenharmony_ci	{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
50362306a36Sopenharmony_ci	{0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
50462306a36Sopenharmony_ci	{0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
50562306a36Sopenharmony_ci	{0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
50662306a36Sopenharmony_ci	{0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
50762306a36Sopenharmony_ci	{0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
50862306a36Sopenharmony_ci	{0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
50962306a36Sopenharmony_ci	{0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
51062306a36Sopenharmony_ci	{0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
51162306a36Sopenharmony_ci	{0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
51262306a36Sopenharmony_ci	{0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
51362306a36Sopenharmony_ci	{0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
51462306a36Sopenharmony_ci	{0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
51562306a36Sopenharmony_ci	{0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
51662306a36Sopenharmony_ci	{0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
51762306a36Sopenharmony_ci	{0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
51862306a36Sopenharmony_ci	{0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
51962306a36Sopenharmony_ci	{0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
52062306a36Sopenharmony_ci	{0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
52162306a36Sopenharmony_ci	{0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
52262306a36Sopenharmony_ci	{0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
52362306a36Sopenharmony_ci	{0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
52462306a36Sopenharmony_ci	{0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
52562306a36Sopenharmony_ci	{0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
52662306a36Sopenharmony_ci	{0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
52762306a36Sopenharmony_ci	{0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
52862306a36Sopenharmony_ci	{0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}	/* 27 */
52962306a36Sopenharmony_ci};
53062306a36Sopenharmony_cistatic const __u8 cxjpeg_176[][8] = {
53162306a36Sopenharmony_ci	{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
53262306a36Sopenharmony_ci	{0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
53362306a36Sopenharmony_ci	{0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
53462306a36Sopenharmony_ci	{0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
53562306a36Sopenharmony_ci	{0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
53662306a36Sopenharmony_ci	{0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
53762306a36Sopenharmony_ci	{0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
53862306a36Sopenharmony_ci	{0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
53962306a36Sopenharmony_ci	{0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
54062306a36Sopenharmony_ci	{0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
54162306a36Sopenharmony_ci	{0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
54262306a36Sopenharmony_ci	{0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
54362306a36Sopenharmony_ci	{0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
54462306a36Sopenharmony_ci	{0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
54562306a36Sopenharmony_ci	{0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
54662306a36Sopenharmony_ci	{0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
54762306a36Sopenharmony_ci	{0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
54862306a36Sopenharmony_ci	{0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
54962306a36Sopenharmony_ci	{0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
55062306a36Sopenharmony_ci	{0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
55162306a36Sopenharmony_ci	{0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
55262306a36Sopenharmony_ci	{0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
55362306a36Sopenharmony_ci	{0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
55462306a36Sopenharmony_ci	{0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
55562306a36Sopenharmony_ci	{0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
55662306a36Sopenharmony_ci	{0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
55762306a36Sopenharmony_ci	{0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
55862306a36Sopenharmony_ci};
55962306a36Sopenharmony_ci/* 640 take with the zcx30x part */
56062306a36Sopenharmony_cistatic const __u8 cxjpeg_qtable[][8] = {
56162306a36Sopenharmony_ci	{0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
56262306a36Sopenharmony_ci	{0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
56362306a36Sopenharmony_ci	{0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
56462306a36Sopenharmony_ci	{0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
56562306a36Sopenharmony_ci	{0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
56662306a36Sopenharmony_ci	{0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
56762306a36Sopenharmony_ci	{0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
56862306a36Sopenharmony_ci	{0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
56962306a36Sopenharmony_ci	{0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
57062306a36Sopenharmony_ci	{0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
57162306a36Sopenharmony_ci	{0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
57262306a36Sopenharmony_ci	{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
57362306a36Sopenharmony_ci	{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
57462306a36Sopenharmony_ci	{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
57562306a36Sopenharmony_ci	{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
57662306a36Sopenharmony_ci	{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
57762306a36Sopenharmony_ci	{0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
57862306a36Sopenharmony_ci	{0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}	/* 18 */
57962306a36Sopenharmony_ci};
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_cistatic void cx11646_jpegInit(struct gspca_dev*gspca_dev)
58362306a36Sopenharmony_ci{
58462306a36Sopenharmony_ci	int i;
58562306a36Sopenharmony_ci	int length;
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x00c0, 0x01);
58862306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x00c3, 0x00);
58962306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x00c0, 0x00);
59062306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0001, 1);
59162306a36Sopenharmony_ci	length = 8;
59262306a36Sopenharmony_ci	for (i = 0; i < 79; i++) {
59362306a36Sopenharmony_ci		if (i == 78)
59462306a36Sopenharmony_ci			length = 6;
59562306a36Sopenharmony_ci		reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
59662306a36Sopenharmony_ci	}
59762306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0002, 1);
59862306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0055, 0x14);
59962306a36Sopenharmony_ci}
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_cistatic const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
60262306a36Sopenharmony_cistatic const __u8 regE5_8[] =
60362306a36Sopenharmony_ci		{ 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
60462306a36Sopenharmony_cistatic const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
60562306a36Sopenharmony_cistatic const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
60662306a36Sopenharmony_cistatic const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
60762306a36Sopenharmony_cistatic const __u8 reg51[] = { 0x77, 0x03 };
60862306a36Sopenharmony_ci#define reg70 0x03
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_cistatic void cx11646_jpeg(struct gspca_dev*gspca_dev)
61162306a36Sopenharmony_ci{
61262306a36Sopenharmony_ci	int i;
61362306a36Sopenharmony_ci	int length;
61462306a36Sopenharmony_ci	__u8 Reg55;
61562306a36Sopenharmony_ci	int retry;
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x00c0, 0x01);
61862306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x00c3, 0x00);
61962306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x00c0, 0x00);
62062306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0001, 1);
62162306a36Sopenharmony_ci	length = 8;
62262306a36Sopenharmony_ci	switch (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv) {
62362306a36Sopenharmony_ci	case 0:
62462306a36Sopenharmony_ci		for (i = 0; i < 27; i++) {
62562306a36Sopenharmony_ci			if (i == 26)
62662306a36Sopenharmony_ci				length = 2;
62762306a36Sopenharmony_ci			reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
62862306a36Sopenharmony_ci		}
62962306a36Sopenharmony_ci		Reg55 = 0x28;
63062306a36Sopenharmony_ci		break;
63162306a36Sopenharmony_ci	case 1:
63262306a36Sopenharmony_ci		for (i = 0; i < 27; i++) {
63362306a36Sopenharmony_ci			if (i == 26)
63462306a36Sopenharmony_ci				length = 2;
63562306a36Sopenharmony_ci			reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
63662306a36Sopenharmony_ci		}
63762306a36Sopenharmony_ci		Reg55 = 0x16;
63862306a36Sopenharmony_ci		break;
63962306a36Sopenharmony_ci	default:
64062306a36Sopenharmony_ci/*	case 2: */
64162306a36Sopenharmony_ci		for (i = 0; i < 27; i++) {
64262306a36Sopenharmony_ci			if (i == 26)
64362306a36Sopenharmony_ci				length = 2;
64462306a36Sopenharmony_ci			reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
64562306a36Sopenharmony_ci		}
64662306a36Sopenharmony_ci		Reg55 = 0x14;
64762306a36Sopenharmony_ci		break;
64862306a36Sopenharmony_ci	case 3:
64962306a36Sopenharmony_ci		for (i = 0; i < 27; i++) {
65062306a36Sopenharmony_ci			if (i == 26)
65162306a36Sopenharmony_ci				length = 2;
65262306a36Sopenharmony_ci			reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
65362306a36Sopenharmony_ci		}
65462306a36Sopenharmony_ci		Reg55 = 0x0B;
65562306a36Sopenharmony_ci		break;
65662306a36Sopenharmony_ci	}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0002, 1);
65962306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0055, Reg55);
66062306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0002, 1);
66162306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0010, reg10, 2);
66262306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0054, 0x02);
66362306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0054, 0x01);
66462306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0000, 0x94);
66562306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0053, 0xc0);
66662306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x00fc, 0xe1);
66762306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0000, 0x00);
66862306a36Sopenharmony_ci	/* wait for completion */
66962306a36Sopenharmony_ci	retry = 50;
67062306a36Sopenharmony_ci	do {
67162306a36Sopenharmony_ci		reg_r(gspca_dev, 0x0002, 1);
67262306a36Sopenharmony_ci							/* 0x07 until 0x00 */
67362306a36Sopenharmony_ci		if (gspca_dev->usb_buf[0] == 0x00)
67462306a36Sopenharmony_ci			break;
67562306a36Sopenharmony_ci		reg_w_val(gspca_dev, 0x0053, 0x00);
67662306a36Sopenharmony_ci	} while (--retry);
67762306a36Sopenharmony_ci	if (retry == 0)
67862306a36Sopenharmony_ci		gspca_err(gspca_dev, "Damned Errors sending jpeg Table\n");
67962306a36Sopenharmony_ci	/* send the qtable now */
68062306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0001, 1);		/* -> 0x18 */
68162306a36Sopenharmony_ci	length = 8;
68262306a36Sopenharmony_ci	for (i = 0; i < 18; i++) {
68362306a36Sopenharmony_ci		if (i == 17)
68462306a36Sopenharmony_ci			length = 2;
68562306a36Sopenharmony_ci		reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	}
68862306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0002, 1);	/* 0x00 */
68962306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0053, 1);	/* 0x00 */
69062306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0054, 0x02);
69162306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0054, 0x01);
69262306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0000, 0x94);
69362306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0053, 0xc0);
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0038, 1);		/* 0x40 */
69662306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0038, 1);		/* 0x40 */
69762306a36Sopenharmony_ci	reg_r(gspca_dev, 0x001f, 1);		/* 0x38 */
69862306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0012, reg12, 5);
69962306a36Sopenharmony_ci	reg_w(gspca_dev, 0x00e5, regE5_8, 8);
70062306a36Sopenharmony_ci	reg_r(gspca_dev, 0x00e8, 8);
70162306a36Sopenharmony_ci	reg_w(gspca_dev, 0x00e5, regE5a, 4);
70262306a36Sopenharmony_ci	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */
70362306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x009a, 0x01);
70462306a36Sopenharmony_ci	reg_w(gspca_dev, 0x00e5, regE5b, 4);
70562306a36Sopenharmony_ci	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */
70662306a36Sopenharmony_ci	reg_w(gspca_dev, 0x00e5, regE5c, 4);
70762306a36Sopenharmony_ci	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0051, reg51, 2);
71062306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0010, reg10, 2);
71162306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0070, reg70);
71262306a36Sopenharmony_ci}
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_cistatic void cx11646_init1(struct gspca_dev *gspca_dev)
71562306a36Sopenharmony_ci{
71662306a36Sopenharmony_ci	int i = 0;
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0010, 0x00);
71962306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0053, 0x00);
72062306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0052, 0x00);
72162306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x009b, 0x2f);
72262306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x009c, 0x10);
72362306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0098, 1);
72462306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0098, 0x40);
72562306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0099, 1);
72662306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0099, 0x07);
72762306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0039, 0x40);
72862306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x003c, 0xff);
72962306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x003f, 0x1f);
73062306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x003d, 0x40);
73162306a36Sopenharmony_ci/*	reg_w_val(gspca_dev, 0x003d, 0x60); */
73262306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0099, 1);			/* ->0x07 */
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci	while (cx_sensor_init[i][0]) {
73562306a36Sopenharmony_ci		reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
73662306a36Sopenharmony_ci		reg_r(gspca_dev, 0x00e8, 1);		/* -> 0x00 */
73762306a36Sopenharmony_ci		if (i == 1) {
73862306a36Sopenharmony_ci			reg_w_val(gspca_dev, 0x00ed, 0x01);
73962306a36Sopenharmony_ci			reg_r(gspca_dev, 0x00ed, 1);	/* -> 0x01 */
74062306a36Sopenharmony_ci		}
74162306a36Sopenharmony_ci		i++;
74262306a36Sopenharmony_ci	}
74362306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x00c3, 0x00);
74462306a36Sopenharmony_ci}
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci/* this function is called at probe time */
74762306a36Sopenharmony_cistatic int sd_config(struct gspca_dev *gspca_dev,
74862306a36Sopenharmony_ci			const struct usb_device_id *id)
74962306a36Sopenharmony_ci{
75062306a36Sopenharmony_ci	struct cam *cam;
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci	cam = &gspca_dev->cam;
75362306a36Sopenharmony_ci	cam->cam_mode = vga_mode;
75462306a36Sopenharmony_ci	cam->nmodes = ARRAY_SIZE(vga_mode);
75562306a36Sopenharmony_ci	return 0;
75662306a36Sopenharmony_ci}
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci/* this function is called at probe and resume time */
75962306a36Sopenharmony_cistatic int sd_init(struct gspca_dev *gspca_dev)
76062306a36Sopenharmony_ci{
76162306a36Sopenharmony_ci	cx11646_init1(gspca_dev);
76262306a36Sopenharmony_ci	cx11646_initsize(gspca_dev);
76362306a36Sopenharmony_ci	cx11646_fw(gspca_dev);
76462306a36Sopenharmony_ci	cx_sensor(gspca_dev);
76562306a36Sopenharmony_ci	cx11646_jpegInit(gspca_dev);
76662306a36Sopenharmony_ci	return 0;
76762306a36Sopenharmony_ci}
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_cistatic int sd_start(struct gspca_dev *gspca_dev)
77062306a36Sopenharmony_ci{
77162306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	/* create the JPEG header */
77462306a36Sopenharmony_ci	jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
77562306a36Sopenharmony_ci			gspca_dev->pixfmt.width,
77662306a36Sopenharmony_ci			0x22);		/* JPEG 411 */
77762306a36Sopenharmony_ci	jpeg_set_qual(sd->jpeg_hdr, QUALITY);
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci	cx11646_initsize(gspca_dev);
78062306a36Sopenharmony_ci	cx11646_fw(gspca_dev);
78162306a36Sopenharmony_ci	cx_sensor(gspca_dev);
78262306a36Sopenharmony_ci	cx11646_jpeg(gspca_dev);
78362306a36Sopenharmony_ci	return 0;
78462306a36Sopenharmony_ci}
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci/* called on streamoff with alt 0 and on disconnect */
78762306a36Sopenharmony_cistatic void sd_stop0(struct gspca_dev *gspca_dev)
78862306a36Sopenharmony_ci{
78962306a36Sopenharmony_ci	int retry = 50;
79062306a36Sopenharmony_ci
79162306a36Sopenharmony_ci	if (!gspca_dev->present)
79262306a36Sopenharmony_ci		return;
79362306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0000, 0x00);
79462306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0002, 1);
79562306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0053, 0x00);
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci	while (retry--) {
79862306a36Sopenharmony_ci/*		reg_r(gspca_dev, 0x0002, 1);*/
79962306a36Sopenharmony_ci		reg_r(gspca_dev, 0x0053, 1);
80062306a36Sopenharmony_ci		if (gspca_dev->usb_buf[0] == 0)
80162306a36Sopenharmony_ci			break;
80262306a36Sopenharmony_ci	}
80362306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0000, 0x00);
80462306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0002, 1);
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0010, 0x00);
80762306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0033, 1);
80862306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x00fc, 0xe0);
80962306a36Sopenharmony_ci}
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_cistatic void sd_pkt_scan(struct gspca_dev *gspca_dev,
81262306a36Sopenharmony_ci			u8 *data,			/* isoc packet */
81362306a36Sopenharmony_ci			int len)			/* iso packet length */
81462306a36Sopenharmony_ci{
81562306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	if (data[0] == 0xff && data[1] == 0xd8) {
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci		/* start of frame */
82062306a36Sopenharmony_ci		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci		/* put the JPEG header in the new frame */
82362306a36Sopenharmony_ci		gspca_frame_add(gspca_dev, FIRST_PACKET,
82462306a36Sopenharmony_ci				sd->jpeg_hdr, JPEG_HDR_SZ);
82562306a36Sopenharmony_ci		data += 2;
82662306a36Sopenharmony_ci		len -= 2;
82762306a36Sopenharmony_ci	}
82862306a36Sopenharmony_ci	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
82962306a36Sopenharmony_ci}
83062306a36Sopenharmony_ci
83162306a36Sopenharmony_cistatic void setbrightness(struct gspca_dev *gspca_dev, s32 val, s32 sat)
83262306a36Sopenharmony_ci{
83362306a36Sopenharmony_ci	__u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
83462306a36Sopenharmony_ci	__u8 reg51c[2];
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci	regE5cbx[2] = val;
83762306a36Sopenharmony_ci	reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
83862306a36Sopenharmony_ci	reg_r(gspca_dev, 0x00e8, 8);
83962306a36Sopenharmony_ci	reg_w(gspca_dev, 0x00e5, regE5c, 4);
84062306a36Sopenharmony_ci	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci	reg51c[0] = 0x77;
84362306a36Sopenharmony_ci	reg51c[1] = sat;
84462306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0051, reg51c, 2);
84562306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0010, reg10, 2);
84662306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0070, reg70);
84762306a36Sopenharmony_ci}
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_cistatic void setcontrast(struct gspca_dev *gspca_dev, s32 val, s32 sat)
85062306a36Sopenharmony_ci{
85162306a36Sopenharmony_ci	__u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 };	/* seem MSB */
85262306a36Sopenharmony_ci/*	__u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01};	 * LSB */
85362306a36Sopenharmony_ci	__u8 reg51c[2];
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_ci	regE5acx[2] = val;
85662306a36Sopenharmony_ci	reg_w(gspca_dev, 0x00e5, regE5acx, 4);
85762306a36Sopenharmony_ci	reg_r(gspca_dev, 0x00e8, 1);		/* 0x00 */
85862306a36Sopenharmony_ci	reg51c[0] = 0x77;
85962306a36Sopenharmony_ci	reg51c[1] = sat;
86062306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0051, reg51c, 2);
86162306a36Sopenharmony_ci	reg_w(gspca_dev, 0x0010, reg10, 2);
86262306a36Sopenharmony_ci	reg_w_val(gspca_dev, 0x0070, reg70);
86362306a36Sopenharmony_ci}
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_cistatic int sd_s_ctrl(struct v4l2_ctrl *ctrl)
86662306a36Sopenharmony_ci{
86762306a36Sopenharmony_ci	struct gspca_dev *gspca_dev =
86862306a36Sopenharmony_ci		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
86962306a36Sopenharmony_ci	struct sd *sd = (struct sd *)gspca_dev;
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci	gspca_dev->usb_err = 0;
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci	if (!gspca_dev->streaming)
87462306a36Sopenharmony_ci		return 0;
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci	switch (ctrl->id) {
87762306a36Sopenharmony_ci	case V4L2_CID_BRIGHTNESS:
87862306a36Sopenharmony_ci		setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val);
87962306a36Sopenharmony_ci		break;
88062306a36Sopenharmony_ci	case V4L2_CID_CONTRAST:
88162306a36Sopenharmony_ci		setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val);
88262306a36Sopenharmony_ci		break;
88362306a36Sopenharmony_ci	case V4L2_CID_SATURATION:
88462306a36Sopenharmony_ci		setbrightness(gspca_dev, sd->brightness->cur.val, ctrl->val);
88562306a36Sopenharmony_ci		setcontrast(gspca_dev, sd->contrast->cur.val, ctrl->val);
88662306a36Sopenharmony_ci		break;
88762306a36Sopenharmony_ci	}
88862306a36Sopenharmony_ci	return gspca_dev->usb_err;
88962306a36Sopenharmony_ci}
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops sd_ctrl_ops = {
89262306a36Sopenharmony_ci	.s_ctrl = sd_s_ctrl,
89362306a36Sopenharmony_ci};
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_cistatic int sd_init_controls(struct gspca_dev *gspca_dev)
89662306a36Sopenharmony_ci{
89762306a36Sopenharmony_ci	struct sd *sd = (struct sd *)gspca_dev;
89862306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	gspca_dev->vdev.ctrl_handler = hdl;
90162306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl, 3);
90262306a36Sopenharmony_ci	sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
90362306a36Sopenharmony_ci			V4L2_CID_BRIGHTNESS, 0, 255, 1, 0xd4);
90462306a36Sopenharmony_ci	sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
90562306a36Sopenharmony_ci			V4L2_CID_CONTRAST, 0x0a, 0x1f, 1, 0x0c);
90662306a36Sopenharmony_ci	sd->sat = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
90762306a36Sopenharmony_ci			V4L2_CID_SATURATION, 0, 7, 1, 3);
90862306a36Sopenharmony_ci	if (hdl->error) {
90962306a36Sopenharmony_ci		pr_err("Could not initialize controls\n");
91062306a36Sopenharmony_ci		return hdl->error;
91162306a36Sopenharmony_ci	}
91262306a36Sopenharmony_ci	return 0;
91362306a36Sopenharmony_ci}
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci/* sub-driver description */
91662306a36Sopenharmony_cistatic const struct sd_desc sd_desc = {
91762306a36Sopenharmony_ci	.name = MODULE_NAME,
91862306a36Sopenharmony_ci	.config = sd_config,
91962306a36Sopenharmony_ci	.init = sd_init,
92062306a36Sopenharmony_ci	.init_controls = sd_init_controls,
92162306a36Sopenharmony_ci	.start = sd_start,
92262306a36Sopenharmony_ci	.stop0 = sd_stop0,
92362306a36Sopenharmony_ci	.pkt_scan = sd_pkt_scan,
92462306a36Sopenharmony_ci};
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci/* -- module initialisation -- */
92762306a36Sopenharmony_cistatic const struct usb_device_id device_table[] = {
92862306a36Sopenharmony_ci	{USB_DEVICE(0x0572, 0x0041)},
92962306a36Sopenharmony_ci	{}
93062306a36Sopenharmony_ci};
93162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, device_table);
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci/* -- device connect -- */
93462306a36Sopenharmony_cistatic int sd_probe(struct usb_interface *intf,
93562306a36Sopenharmony_ci			const struct usb_device_id *id)
93662306a36Sopenharmony_ci{
93762306a36Sopenharmony_ci	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
93862306a36Sopenharmony_ci				THIS_MODULE);
93962306a36Sopenharmony_ci}
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_cistatic struct usb_driver sd_driver = {
94262306a36Sopenharmony_ci	.name = MODULE_NAME,
94362306a36Sopenharmony_ci	.id_table = device_table,
94462306a36Sopenharmony_ci	.probe = sd_probe,
94562306a36Sopenharmony_ci	.disconnect = gspca_disconnect,
94662306a36Sopenharmony_ci#ifdef CONFIG_PM
94762306a36Sopenharmony_ci	.suspend = gspca_suspend,
94862306a36Sopenharmony_ci	.resume = gspca_resume,
94962306a36Sopenharmony_ci	.reset_resume = gspca_resume,
95062306a36Sopenharmony_ci#endif
95162306a36Sopenharmony_ci};
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_cimodule_usb_driver(sd_driver);
954