xref: /OK3568_Linux_fs/kernel/drivers/media/usb/gspca/mr97310a.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Mars MR97310A library
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * The original mr97310a driver, which supported the Aiptek Pencam VGA+, is
6*4882a593Smuzhiyun  * Copyright (C) 2009 Kyle Guinn <elyk03@gmail.com>
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+
9*4882a593Smuzhiyun  * and for the routines for detecting and classifying these various cameras,
10*4882a593Smuzhiyun  * is Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  * Support for the control settings for the CIF cameras is
13*4882a593Smuzhiyun  * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> and
14*4882a593Smuzhiyun  * Thomas Kaiser <thomas@kaiser-linux.li>
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  * Support for the control settings for the VGA cameras is
17*4882a593Smuzhiyun  * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
18*4882a593Smuzhiyun  *
19*4882a593Smuzhiyun  * Several previously unsupported cameras are owned and have been tested by
20*4882a593Smuzhiyun  * Hans de Goede <hdegoede@redhat.com> and
21*4882a593Smuzhiyun  * Thomas Kaiser <thomas@kaiser-linux.li> and
22*4882a593Smuzhiyun  * Theodore Kilgore <kilgota@auburn.edu> and
23*4882a593Smuzhiyun  * Edmond Rodriguez <erodrig_97@yahoo.com> and
24*4882a593Smuzhiyun  * Aurelien Jacobs <aurel@gnuage.org>
25*4882a593Smuzhiyun  *
26*4882a593Smuzhiyun  * The MR97311A support in gspca/mars.c has been helpful in understanding some
27*4882a593Smuzhiyun  * of the registers in these cameras.
28*4882a593Smuzhiyun  */
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #define MODULE_NAME "mr97310a"
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #include "gspca.h"
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #define CAM_TYPE_CIF			0
37*4882a593Smuzhiyun #define CAM_TYPE_VGA			1
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #define MR97310A_BRIGHTNESS_DEFAULT	0
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #define MR97310A_EXPOSURE_MIN		0
42*4882a593Smuzhiyun #define MR97310A_EXPOSURE_MAX		4095
43*4882a593Smuzhiyun #define MR97310A_EXPOSURE_DEFAULT	1000
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun #define MR97310A_GAIN_MIN		0
46*4882a593Smuzhiyun #define MR97310A_GAIN_MAX		31
47*4882a593Smuzhiyun #define MR97310A_GAIN_DEFAULT		25
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun #define MR97310A_CONTRAST_MIN		0
50*4882a593Smuzhiyun #define MR97310A_CONTRAST_MAX		31
51*4882a593Smuzhiyun #define MR97310A_CONTRAST_DEFAULT	23
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun #define MR97310A_CS_GAIN_MIN		0
54*4882a593Smuzhiyun #define MR97310A_CS_GAIN_MAX		0x7ff
55*4882a593Smuzhiyun #define MR97310A_CS_GAIN_DEFAULT	0x110
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun #define MR97310A_CID_CLOCKDIV (V4L2_CTRL_CLASS_USER + 0x1000)
58*4882a593Smuzhiyun #define MR97310A_MIN_CLOCKDIV_MIN	3
59*4882a593Smuzhiyun #define MR97310A_MIN_CLOCKDIV_MAX	8
60*4882a593Smuzhiyun #define MR97310A_MIN_CLOCKDIV_DEFAULT	3
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>,Theodore Kilgore <kilgota@auburn.edu>");
63*4882a593Smuzhiyun MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver");
64*4882a593Smuzhiyun MODULE_LICENSE("GPL");
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun /* global parameters */
67*4882a593Smuzhiyun static int force_sensor_type = -1;
68*4882a593Smuzhiyun module_param(force_sensor_type, int, 0644);
69*4882a593Smuzhiyun MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)");
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun /* specific webcam descriptor */
72*4882a593Smuzhiyun struct sd {
73*4882a593Smuzhiyun 	struct gspca_dev gspca_dev;  /* !! must be the first item */
74*4882a593Smuzhiyun 	struct { /* exposure/min_clockdiv control cluster */
75*4882a593Smuzhiyun 		struct v4l2_ctrl *exposure;
76*4882a593Smuzhiyun 		struct v4l2_ctrl *min_clockdiv;
77*4882a593Smuzhiyun 	};
78*4882a593Smuzhiyun 	u8 sof_read;
79*4882a593Smuzhiyun 	u8 cam_type;	/* 0 is CIF and 1 is VGA */
80*4882a593Smuzhiyun 	u8 sensor_type;	/* We use 0 and 1 here, too. */
81*4882a593Smuzhiyun 	u8 do_lcd_stop;
82*4882a593Smuzhiyun 	u8 adj_colors;
83*4882a593Smuzhiyun };
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun struct sensor_w_data {
86*4882a593Smuzhiyun 	u8 reg;
87*4882a593Smuzhiyun 	u8 flags;
88*4882a593Smuzhiyun 	u8 data[16];
89*4882a593Smuzhiyun 	int len;
90*4882a593Smuzhiyun };
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun static void sd_stopN(struct gspca_dev *gspca_dev);
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun static const struct v4l2_pix_format vga_mode[] = {
95*4882a593Smuzhiyun 	{160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
96*4882a593Smuzhiyun 		.bytesperline = 160,
97*4882a593Smuzhiyun 		.sizeimage = 160 * 120,
98*4882a593Smuzhiyun 		.colorspace = V4L2_COLORSPACE_SRGB,
99*4882a593Smuzhiyun 		.priv = 4},
100*4882a593Smuzhiyun 	{176, 144, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
101*4882a593Smuzhiyun 		.bytesperline = 176,
102*4882a593Smuzhiyun 		.sizeimage = 176 * 144,
103*4882a593Smuzhiyun 		.colorspace = V4L2_COLORSPACE_SRGB,
104*4882a593Smuzhiyun 		.priv = 3},
105*4882a593Smuzhiyun 	{320, 240, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
106*4882a593Smuzhiyun 		.bytesperline = 320,
107*4882a593Smuzhiyun 		.sizeimage = 320 * 240,
108*4882a593Smuzhiyun 		.colorspace = V4L2_COLORSPACE_SRGB,
109*4882a593Smuzhiyun 		.priv = 2},
110*4882a593Smuzhiyun 	{352, 288, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
111*4882a593Smuzhiyun 		.bytesperline = 352,
112*4882a593Smuzhiyun 		.sizeimage = 352 * 288,
113*4882a593Smuzhiyun 		.colorspace = V4L2_COLORSPACE_SRGB,
114*4882a593Smuzhiyun 		.priv = 1},
115*4882a593Smuzhiyun 	{640, 480, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
116*4882a593Smuzhiyun 		.bytesperline = 640,
117*4882a593Smuzhiyun 		.sizeimage = 640 * 480,
118*4882a593Smuzhiyun 		.colorspace = V4L2_COLORSPACE_SRGB,
119*4882a593Smuzhiyun 		.priv = 0},
120*4882a593Smuzhiyun };
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun /* the bytes to write are in gspca_dev->usb_buf */
mr_write(struct gspca_dev * gspca_dev,int len)123*4882a593Smuzhiyun static int mr_write(struct gspca_dev *gspca_dev, int len)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun 	int rc;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	rc = usb_bulk_msg(gspca_dev->dev,
128*4882a593Smuzhiyun 			  usb_sndbulkpipe(gspca_dev->dev, 4),
129*4882a593Smuzhiyun 			  gspca_dev->usb_buf, len, NULL, 500);
130*4882a593Smuzhiyun 	if (rc < 0)
131*4882a593Smuzhiyun 		pr_err("reg write [%02x] error %d\n",
132*4882a593Smuzhiyun 		       gspca_dev->usb_buf[0], rc);
133*4882a593Smuzhiyun 	return rc;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun /* the bytes are read into gspca_dev->usb_buf */
mr_read(struct gspca_dev * gspca_dev,int len)137*4882a593Smuzhiyun static int mr_read(struct gspca_dev *gspca_dev, int len)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun 	int rc;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	rc = usb_bulk_msg(gspca_dev->dev,
142*4882a593Smuzhiyun 			  usb_rcvbulkpipe(gspca_dev->dev, 3),
143*4882a593Smuzhiyun 			  gspca_dev->usb_buf, len, NULL, 500);
144*4882a593Smuzhiyun 	if (rc < 0)
145*4882a593Smuzhiyun 		pr_err("reg read [%02x] error %d\n",
146*4882a593Smuzhiyun 		       gspca_dev->usb_buf[0], rc);
147*4882a593Smuzhiyun 	return rc;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun 
sensor_write_reg(struct gspca_dev * gspca_dev,u8 reg,u8 flags,const u8 * data,int len)150*4882a593Smuzhiyun static int sensor_write_reg(struct gspca_dev *gspca_dev, u8 reg, u8 flags,
151*4882a593Smuzhiyun 	const u8 *data, int len)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun 	gspca_dev->usb_buf[0] = 0x1f;
154*4882a593Smuzhiyun 	gspca_dev->usb_buf[1] = flags;
155*4882a593Smuzhiyun 	gspca_dev->usb_buf[2] = reg;
156*4882a593Smuzhiyun 	memcpy(gspca_dev->usb_buf + 3, data, len);
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	return mr_write(gspca_dev, len + 3);
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun 
sensor_write_regs(struct gspca_dev * gspca_dev,const struct sensor_w_data * data,int len)161*4882a593Smuzhiyun static int sensor_write_regs(struct gspca_dev *gspca_dev,
162*4882a593Smuzhiyun 	const struct sensor_w_data *data, int len)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun 	int i, rc;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	for (i = 0; i < len; i++) {
167*4882a593Smuzhiyun 		rc = sensor_write_reg(gspca_dev, data[i].reg, data[i].flags,
168*4882a593Smuzhiyun 					  data[i].data, data[i].len);
169*4882a593Smuzhiyun 		if (rc < 0)
170*4882a593Smuzhiyun 			return rc;
171*4882a593Smuzhiyun 	}
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	return 0;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
sensor_write1(struct gspca_dev * gspca_dev,u8 reg,u8 data)176*4882a593Smuzhiyun static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun 	struct sd *sd = (struct sd *) gspca_dev;
179*4882a593Smuzhiyun 	u8 buf, confirm_reg;
180*4882a593Smuzhiyun 	int rc;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	buf = data;
183*4882a593Smuzhiyun 	if (sd->cam_type == CAM_TYPE_CIF) {
184*4882a593Smuzhiyun 		rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1);
185*4882a593Smuzhiyun 		confirm_reg = sd->sensor_type ? 0x13 : 0x11;
186*4882a593Smuzhiyun 	} else {
187*4882a593Smuzhiyun 		rc = sensor_write_reg(gspca_dev, reg, 0x00, &buf, 1);
188*4882a593Smuzhiyun 		confirm_reg = 0x11;
189*4882a593Smuzhiyun 	}
190*4882a593Smuzhiyun 	if (rc < 0)
191*4882a593Smuzhiyun 		return rc;
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	buf = 0x01;
194*4882a593Smuzhiyun 	rc = sensor_write_reg(gspca_dev, confirm_reg, 0x00, &buf, 1);
195*4882a593Smuzhiyun 	if (rc < 0)
196*4882a593Smuzhiyun 		return rc;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	return 0;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun 
cam_get_response16(struct gspca_dev * gspca_dev,u8 reg,int verbose)201*4882a593Smuzhiyun static int cam_get_response16(struct gspca_dev *gspca_dev, u8 reg, int verbose)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun 	int err_code;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	gspca_dev->usb_buf[0] = reg;
206*4882a593Smuzhiyun 	err_code = mr_write(gspca_dev, 1);
207*4882a593Smuzhiyun 	if (err_code < 0)
208*4882a593Smuzhiyun 		return err_code;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	err_code = mr_read(gspca_dev, 16);
211*4882a593Smuzhiyun 	if (err_code < 0)
212*4882a593Smuzhiyun 		return err_code;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	if (verbose)
215*4882a593Smuzhiyun 		gspca_dbg(gspca_dev, D_PROBE, "Register: %02x reads %02x%02x%02x\n",
216*4882a593Smuzhiyun 			  reg,
217*4882a593Smuzhiyun 			  gspca_dev->usb_buf[0],
218*4882a593Smuzhiyun 			  gspca_dev->usb_buf[1],
219*4882a593Smuzhiyun 			  gspca_dev->usb_buf[2]);
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	return 0;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun 
zero_the_pointer(struct gspca_dev * gspca_dev)224*4882a593Smuzhiyun static int zero_the_pointer(struct gspca_dev *gspca_dev)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun 	__u8 *data = gspca_dev->usb_buf;
227*4882a593Smuzhiyun 	int err_code;
228*4882a593Smuzhiyun 	u8 status = 0;
229*4882a593Smuzhiyun 	int tries = 0;
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	err_code = cam_get_response16(gspca_dev, 0x21, 0);
232*4882a593Smuzhiyun 	if (err_code < 0)
233*4882a593Smuzhiyun 		return err_code;
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	data[0] = 0x19;
236*4882a593Smuzhiyun 	data[1] = 0x51;
237*4882a593Smuzhiyun 	err_code = mr_write(gspca_dev, 2);
238*4882a593Smuzhiyun 	if (err_code < 0)
239*4882a593Smuzhiyun 		return err_code;
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	err_code = cam_get_response16(gspca_dev, 0x21, 0);
242*4882a593Smuzhiyun 	if (err_code < 0)
243*4882a593Smuzhiyun 		return err_code;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	data[0] = 0x19;
246*4882a593Smuzhiyun 	data[1] = 0xba;
247*4882a593Smuzhiyun 	err_code = mr_write(gspca_dev, 2);
248*4882a593Smuzhiyun 	if (err_code < 0)
249*4882a593Smuzhiyun 		return err_code;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	err_code = cam_get_response16(gspca_dev, 0x21, 0);
252*4882a593Smuzhiyun 	if (err_code < 0)
253*4882a593Smuzhiyun 		return err_code;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	data[0] = 0x19;
256*4882a593Smuzhiyun 	data[1] = 0x00;
257*4882a593Smuzhiyun 	err_code = mr_write(gspca_dev, 2);
258*4882a593Smuzhiyun 	if (err_code < 0)
259*4882a593Smuzhiyun 		return err_code;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	err_code = cam_get_response16(gspca_dev, 0x21, 0);
262*4882a593Smuzhiyun 	if (err_code < 0)
263*4882a593Smuzhiyun 		return err_code;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	data[0] = 0x19;
266*4882a593Smuzhiyun 	data[1] = 0x00;
267*4882a593Smuzhiyun 	err_code = mr_write(gspca_dev, 2);
268*4882a593Smuzhiyun 	if (err_code < 0)
269*4882a593Smuzhiyun 		return err_code;
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	while (status != 0x0a && tries < 256) {
272*4882a593Smuzhiyun 		err_code = cam_get_response16(gspca_dev, 0x21, 0);
273*4882a593Smuzhiyun 		status = data[0];
274*4882a593Smuzhiyun 		tries++;
275*4882a593Smuzhiyun 		if (err_code < 0)
276*4882a593Smuzhiyun 			return err_code;
277*4882a593Smuzhiyun 	}
278*4882a593Smuzhiyun 	if (status != 0x0a)
279*4882a593Smuzhiyun 		gspca_err(gspca_dev, "status is %02x\n", status);
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	tries = 0;
282*4882a593Smuzhiyun 	while (tries < 4) {
283*4882a593Smuzhiyun 		data[0] = 0x19;
284*4882a593Smuzhiyun 		data[1] = 0x00;
285*4882a593Smuzhiyun 		err_code = mr_write(gspca_dev, 2);
286*4882a593Smuzhiyun 		if (err_code < 0)
287*4882a593Smuzhiyun 			return err_code;
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 		err_code = cam_get_response16(gspca_dev, 0x21, 0);
290*4882a593Smuzhiyun 		tries++;
291*4882a593Smuzhiyun 		if (err_code < 0)
292*4882a593Smuzhiyun 			return err_code;
293*4882a593Smuzhiyun 	}
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	data[0] = 0x19;
296*4882a593Smuzhiyun 	err_code = mr_write(gspca_dev, 1);
297*4882a593Smuzhiyun 	if (err_code < 0)
298*4882a593Smuzhiyun 		return err_code;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	err_code = mr_read(gspca_dev, 16);
301*4882a593Smuzhiyun 	if (err_code < 0)
302*4882a593Smuzhiyun 		return err_code;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	return 0;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
stream_start(struct gspca_dev * gspca_dev)307*4882a593Smuzhiyun static int stream_start(struct gspca_dev *gspca_dev)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun 	gspca_dev->usb_buf[0] = 0x01;
310*4882a593Smuzhiyun 	gspca_dev->usb_buf[1] = 0x01;
311*4882a593Smuzhiyun 	return mr_write(gspca_dev, 2);
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun 
stream_stop(struct gspca_dev * gspca_dev)314*4882a593Smuzhiyun static void stream_stop(struct gspca_dev *gspca_dev)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun 	gspca_dev->usb_buf[0] = 0x01;
317*4882a593Smuzhiyun 	gspca_dev->usb_buf[1] = 0x00;
318*4882a593Smuzhiyun 	if (mr_write(gspca_dev, 2) < 0)
319*4882a593Smuzhiyun 		gspca_err(gspca_dev, "Stream Stop failed\n");
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun 
lcd_stop(struct gspca_dev * gspca_dev)322*4882a593Smuzhiyun static void lcd_stop(struct gspca_dev *gspca_dev)
323*4882a593Smuzhiyun {
324*4882a593Smuzhiyun 	gspca_dev->usb_buf[0] = 0x19;
325*4882a593Smuzhiyun 	gspca_dev->usb_buf[1] = 0x54;
326*4882a593Smuzhiyun 	if (mr_write(gspca_dev, 2) < 0)
327*4882a593Smuzhiyun 		gspca_err(gspca_dev, "LCD Stop failed\n");
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun 
isoc_enable(struct gspca_dev * gspca_dev)330*4882a593Smuzhiyun static int isoc_enable(struct gspca_dev *gspca_dev)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun 	gspca_dev->usb_buf[0] = 0x00;
333*4882a593Smuzhiyun 	gspca_dev->usb_buf[1] = 0x4d;  /* ISOC transferring enable... */
334*4882a593Smuzhiyun 	return mr_write(gspca_dev, 2);
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun /* This function is called at probe time */
sd_config(struct gspca_dev * gspca_dev,const struct usb_device_id * id)338*4882a593Smuzhiyun static int sd_config(struct gspca_dev *gspca_dev,
339*4882a593Smuzhiyun 		     const struct usb_device_id *id)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun 	struct sd *sd = (struct sd *) gspca_dev;
342*4882a593Smuzhiyun 	struct cam *cam;
343*4882a593Smuzhiyun 	int err_code;
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	cam = &gspca_dev->cam;
346*4882a593Smuzhiyun 	cam->cam_mode = vga_mode;
347*4882a593Smuzhiyun 	cam->nmodes = ARRAY_SIZE(vga_mode);
348*4882a593Smuzhiyun 	sd->do_lcd_stop = 0;
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 	/* Several of the supported CIF cameras share the same USB ID but
351*4882a593Smuzhiyun 	 * require different initializations and different control settings.
352*4882a593Smuzhiyun 	 * The same is true of the VGA cameras. Therefore, we are forced
353*4882a593Smuzhiyun 	 * to start the initialization process in order to determine which
354*4882a593Smuzhiyun 	 * camera is present. Some of the supported cameras require the
355*4882a593Smuzhiyun 	 * memory pointer to be set to 0 as the very first item of business
356*4882a593Smuzhiyun 	 * or else they will not stream. So we do that immediately.
357*4882a593Smuzhiyun 	 */
358*4882a593Smuzhiyun 	err_code = zero_the_pointer(gspca_dev);
359*4882a593Smuzhiyun 	if (err_code < 0)
360*4882a593Smuzhiyun 		return err_code;
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	err_code = stream_start(gspca_dev);
363*4882a593Smuzhiyun 	if (err_code < 0)
364*4882a593Smuzhiyun 		return err_code;
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	/* Now, the query for sensor type. */
367*4882a593Smuzhiyun 	err_code = cam_get_response16(gspca_dev, 0x07, 1);
368*4882a593Smuzhiyun 	if (err_code < 0)
369*4882a593Smuzhiyun 		return err_code;
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	if (id->idProduct == 0x0110 || id->idProduct == 0x010e) {
372*4882a593Smuzhiyun 		sd->cam_type = CAM_TYPE_CIF;
373*4882a593Smuzhiyun 		cam->nmodes--;
374*4882a593Smuzhiyun 		/*
375*4882a593Smuzhiyun 		 * All but one of the known CIF cameras share the same USB ID,
376*4882a593Smuzhiyun 		 * but two different init routines are in use, and the control
377*4882a593Smuzhiyun 		 * settings are different, too. We need to detect which camera
378*4882a593Smuzhiyun 		 * of the two known varieties is connected!
379*4882a593Smuzhiyun 		 *
380*4882a593Smuzhiyun 		 * A list of known CIF cameras follows. They all report either
381*4882a593Smuzhiyun 		 * 0200 for type 0 or 0300 for type 1.
382*4882a593Smuzhiyun 		 * If you have another to report, please do
383*4882a593Smuzhiyun 		 *
384*4882a593Smuzhiyun 		 * Name		sd->sensor_type		reported by
385*4882a593Smuzhiyun 		 *
386*4882a593Smuzhiyun 		 * Sakar 56379 Spy-shot	0		T. Kilgore
387*4882a593Smuzhiyun 		 * Innovage		0		T. Kilgore
388*4882a593Smuzhiyun 		 * Vivitar Mini		0		H. De Goede
389*4882a593Smuzhiyun 		 * Vivitar Mini		0		E. Rodriguez
390*4882a593Smuzhiyun 		 * Vivitar Mini		1		T. Kilgore
391*4882a593Smuzhiyun 		 * Elta-Media 8212dc	1		T. Kaiser
392*4882a593Smuzhiyun 		 * Philips dig. keych.	1		T. Kilgore
393*4882a593Smuzhiyun 		 * Trust Spyc@m 100	1		A. Jacobs
394*4882a593Smuzhiyun 		 */
395*4882a593Smuzhiyun 		switch (gspca_dev->usb_buf[0]) {
396*4882a593Smuzhiyun 		case 2:
397*4882a593Smuzhiyun 			sd->sensor_type = 0;
398*4882a593Smuzhiyun 			break;
399*4882a593Smuzhiyun 		case 3:
400*4882a593Smuzhiyun 			sd->sensor_type = 1;
401*4882a593Smuzhiyun 			break;
402*4882a593Smuzhiyun 		default:
403*4882a593Smuzhiyun 			pr_err("Unknown CIF Sensor id : %02x\n",
404*4882a593Smuzhiyun 			       gspca_dev->usb_buf[1]);
405*4882a593Smuzhiyun 			return -ENODEV;
406*4882a593Smuzhiyun 		}
407*4882a593Smuzhiyun 		gspca_dbg(gspca_dev, D_PROBE, "MR97310A CIF camera detected, sensor: %d\n",
408*4882a593Smuzhiyun 			  sd->sensor_type);
409*4882a593Smuzhiyun 	} else {
410*4882a593Smuzhiyun 		sd->cam_type = CAM_TYPE_VGA;
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 		/*
413*4882a593Smuzhiyun 		 * Here is a table of the responses to the query for sensor
414*4882a593Smuzhiyun 		 * type, from the known MR97310A VGA cameras. Six different
415*4882a593Smuzhiyun 		 * cameras of which five share the same USB ID.
416*4882a593Smuzhiyun 		 *
417*4882a593Smuzhiyun 		 * Name			gspca_dev->usb_buf[]	sd->sensor_type
418*4882a593Smuzhiyun 		 *				sd->do_lcd_stop
419*4882a593Smuzhiyun 		 * Aiptek Pencam VGA+	0300		0		1
420*4882a593Smuzhiyun 		 * ION digital		0300		0		1
421*4882a593Smuzhiyun 		 * Argus DC-1620	0450		1		0
422*4882a593Smuzhiyun 		 * Argus QuickClix	0420		1		1
423*4882a593Smuzhiyun 		 * Sakar 77379 Digital	0350		0		1
424*4882a593Smuzhiyun 		 * Sakar 1638x CyberPix	0120		0		2
425*4882a593Smuzhiyun 		 *
426*4882a593Smuzhiyun 		 * Based upon these results, we assume default settings
427*4882a593Smuzhiyun 		 * and then correct as necessary, as follows.
428*4882a593Smuzhiyun 		 *
429*4882a593Smuzhiyun 		 */
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 		sd->sensor_type = 1;
432*4882a593Smuzhiyun 		sd->do_lcd_stop = 0;
433*4882a593Smuzhiyun 		sd->adj_colors = 0;
434*4882a593Smuzhiyun 		if (gspca_dev->usb_buf[0] == 0x01) {
435*4882a593Smuzhiyun 			sd->sensor_type = 2;
436*4882a593Smuzhiyun 		} else if ((gspca_dev->usb_buf[0] != 0x03) &&
437*4882a593Smuzhiyun 					(gspca_dev->usb_buf[0] != 0x04)) {
438*4882a593Smuzhiyun 			pr_err("Unknown VGA Sensor id Byte 0: %02x\n",
439*4882a593Smuzhiyun 			       gspca_dev->usb_buf[0]);
440*4882a593Smuzhiyun 			pr_err("Defaults assumed, may not work\n");
441*4882a593Smuzhiyun 			pr_err("Please report this\n");
442*4882a593Smuzhiyun 		}
443*4882a593Smuzhiyun 		/* Sakar Digital color needs to be adjusted. */
444*4882a593Smuzhiyun 		if ((gspca_dev->usb_buf[0] == 0x03) &&
445*4882a593Smuzhiyun 					(gspca_dev->usb_buf[1] == 0x50))
446*4882a593Smuzhiyun 			sd->adj_colors = 1;
447*4882a593Smuzhiyun 		if (gspca_dev->usb_buf[0] == 0x04) {
448*4882a593Smuzhiyun 			sd->do_lcd_stop = 1;
449*4882a593Smuzhiyun 			switch (gspca_dev->usb_buf[1]) {
450*4882a593Smuzhiyun 			case 0x50:
451*4882a593Smuzhiyun 				sd->sensor_type = 0;
452*4882a593Smuzhiyun 				gspca_dbg(gspca_dev, D_PROBE, "sensor_type corrected to 0\n");
453*4882a593Smuzhiyun 				break;
454*4882a593Smuzhiyun 			case 0x20:
455*4882a593Smuzhiyun 				/* Nothing to do here. */
456*4882a593Smuzhiyun 				break;
457*4882a593Smuzhiyun 			default:
458*4882a593Smuzhiyun 				pr_err("Unknown VGA Sensor id Byte 1: %02x\n",
459*4882a593Smuzhiyun 				       gspca_dev->usb_buf[1]);
460*4882a593Smuzhiyun 				pr_err("Defaults assumed, may not work\n");
461*4882a593Smuzhiyun 				pr_err("Please report this\n");
462*4882a593Smuzhiyun 			}
463*4882a593Smuzhiyun 		}
464*4882a593Smuzhiyun 		gspca_dbg(gspca_dev, D_PROBE, "MR97310A VGA camera detected, sensor: %d\n",
465*4882a593Smuzhiyun 			  sd->sensor_type);
466*4882a593Smuzhiyun 	}
467*4882a593Smuzhiyun 	/* Stop streaming as we've started it only to probe the sensor type. */
468*4882a593Smuzhiyun 	sd_stopN(gspca_dev);
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	if (force_sensor_type != -1) {
471*4882a593Smuzhiyun 		sd->sensor_type = !!force_sensor_type;
472*4882a593Smuzhiyun 		gspca_dbg(gspca_dev, D_PROBE, "Forcing sensor type to: %d\n",
473*4882a593Smuzhiyun 			  sd->sensor_type);
474*4882a593Smuzhiyun 	}
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	return 0;
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun /* this function is called at probe and resume time */
sd_init(struct gspca_dev * gspca_dev)480*4882a593Smuzhiyun static int sd_init(struct gspca_dev *gspca_dev)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun 	return 0;
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun 
start_cif_cam(struct gspca_dev * gspca_dev)485*4882a593Smuzhiyun static int start_cif_cam(struct gspca_dev *gspca_dev)
486*4882a593Smuzhiyun {
487*4882a593Smuzhiyun 	struct sd *sd = (struct sd *) gspca_dev;
488*4882a593Smuzhiyun 	__u8 *data = gspca_dev->usb_buf;
489*4882a593Smuzhiyun 	int err_code;
490*4882a593Smuzhiyun 	static const __u8 startup_string[] = {
491*4882a593Smuzhiyun 		0x00,
492*4882a593Smuzhiyun 		0x0d,
493*4882a593Smuzhiyun 		0x01,
494*4882a593Smuzhiyun 		0x00, /* Hsize/8 for 352 or 320 */
495*4882a593Smuzhiyun 		0x00, /* Vsize/4 for 288 or 240 */
496*4882a593Smuzhiyun 		0x13, /* or 0xbb, depends on sensor */
497*4882a593Smuzhiyun 		0x00, /* Hstart, depends on res. */
498*4882a593Smuzhiyun 		0x00, /* reserved ? */
499*4882a593Smuzhiyun 		0x00, /* Vstart, depends on res. and sensor */
500*4882a593Smuzhiyun 		0x50, /* 0x54 to get 176 or 160 */
501*4882a593Smuzhiyun 		0xc0
502*4882a593Smuzhiyun 	};
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 	/* Note: Some of the above descriptions guessed from MR97113A driver */
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	memcpy(data, startup_string, 11);
507*4882a593Smuzhiyun 	if (sd->sensor_type)
508*4882a593Smuzhiyun 		data[5] = 0xbb;
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun 	switch (gspca_dev->pixfmt.width) {
511*4882a593Smuzhiyun 	case 160:
512*4882a593Smuzhiyun 		data[9] |= 0x04;  /* reg 8, 2:1 scale down from 320 */
513*4882a593Smuzhiyun 		fallthrough;
514*4882a593Smuzhiyun 	case 320:
515*4882a593Smuzhiyun 	default:
516*4882a593Smuzhiyun 		data[3] = 0x28;			   /* reg 2, H size/8 */
517*4882a593Smuzhiyun 		data[4] = 0x3c;			   /* reg 3, V size/4 */
518*4882a593Smuzhiyun 		data[6] = 0x14;			   /* reg 5, H start  */
519*4882a593Smuzhiyun 		data[8] = 0x1a + sd->sensor_type;  /* reg 7, V start  */
520*4882a593Smuzhiyun 		break;
521*4882a593Smuzhiyun 	case 176:
522*4882a593Smuzhiyun 		data[9] |= 0x04;  /* reg 8, 2:1 scale down from 352 */
523*4882a593Smuzhiyun 		fallthrough;
524*4882a593Smuzhiyun 	case 352:
525*4882a593Smuzhiyun 		data[3] = 0x2c;			   /* reg 2, H size/8 */
526*4882a593Smuzhiyun 		data[4] = 0x48;			   /* reg 3, V size/4 */
527*4882a593Smuzhiyun 		data[6] = 0x06;			   /* reg 5, H start  */
528*4882a593Smuzhiyun 		data[8] = 0x06 - sd->sensor_type;  /* reg 7, V start  */
529*4882a593Smuzhiyun 		break;
530*4882a593Smuzhiyun 	}
531*4882a593Smuzhiyun 	err_code = mr_write(gspca_dev, 11);
532*4882a593Smuzhiyun 	if (err_code < 0)
533*4882a593Smuzhiyun 		return err_code;
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 	if (!sd->sensor_type) {
536*4882a593Smuzhiyun 		static const struct sensor_w_data cif_sensor0_init_data[] = {
537*4882a593Smuzhiyun 			{0x02, 0x00, {0x03, 0x5a, 0xb5, 0x01,
538*4882a593Smuzhiyun 				      0x0f, 0x14, 0x0f, 0x10}, 8},
539*4882a593Smuzhiyun 			{0x0c, 0x00, {0x04, 0x01, 0x01, 0x00, 0x1f}, 5},
540*4882a593Smuzhiyun 			{0x12, 0x00, {0x07}, 1},
541*4882a593Smuzhiyun 			{0x1f, 0x00, {0x06}, 1},
542*4882a593Smuzhiyun 			{0x27, 0x00, {0x04}, 1},
543*4882a593Smuzhiyun 			{0x29, 0x00, {0x0c}, 1},
544*4882a593Smuzhiyun 			{0x40, 0x00, {0x40, 0x00, 0x04}, 3},
545*4882a593Smuzhiyun 			{0x50, 0x00, {0x60}, 1},
546*4882a593Smuzhiyun 			{0x60, 0x00, {0x06}, 1},
547*4882a593Smuzhiyun 			{0x6b, 0x00, {0x85, 0x85, 0xc8, 0xc8, 0xc8, 0xc8}, 6},
548*4882a593Smuzhiyun 			{0x72, 0x00, {0x1e, 0x56}, 2},
549*4882a593Smuzhiyun 			{0x75, 0x00, {0x58, 0x40, 0xa2, 0x02, 0x31, 0x02,
550*4882a593Smuzhiyun 				      0x31, 0x80, 0x00}, 9},
551*4882a593Smuzhiyun 			{0x11, 0x00, {0x01}, 1},
552*4882a593Smuzhiyun 			{0, 0, {0}, 0}
553*4882a593Smuzhiyun 		};
554*4882a593Smuzhiyun 		err_code = sensor_write_regs(gspca_dev, cif_sensor0_init_data,
555*4882a593Smuzhiyun 					 ARRAY_SIZE(cif_sensor0_init_data));
556*4882a593Smuzhiyun 	} else {	/* sd->sensor_type = 1 */
557*4882a593Smuzhiyun 		static const struct sensor_w_data cif_sensor1_init_data[] = {
558*4882a593Smuzhiyun 			/* Reg 3,4, 7,8 get set by the controls */
559*4882a593Smuzhiyun 			{0x02, 0x00, {0x10}, 1},
560*4882a593Smuzhiyun 			{0x05, 0x01, {0x22}, 1}, /* 5/6 also seen as 65h/32h */
561*4882a593Smuzhiyun 			{0x06, 0x01, {0x00}, 1},
562*4882a593Smuzhiyun 			{0x09, 0x02, {0x0e}, 1},
563*4882a593Smuzhiyun 			{0x0a, 0x02, {0x05}, 1},
564*4882a593Smuzhiyun 			{0x0b, 0x02, {0x05}, 1},
565*4882a593Smuzhiyun 			{0x0c, 0x02, {0x0f}, 1},
566*4882a593Smuzhiyun 			{0x0d, 0x02, {0x07}, 1},
567*4882a593Smuzhiyun 			{0x0e, 0x02, {0x0c}, 1},
568*4882a593Smuzhiyun 			{0x0f, 0x00, {0x00}, 1},
569*4882a593Smuzhiyun 			{0x10, 0x00, {0x06}, 1},
570*4882a593Smuzhiyun 			{0x11, 0x00, {0x07}, 1},
571*4882a593Smuzhiyun 			{0x12, 0x00, {0x00}, 1},
572*4882a593Smuzhiyun 			{0x13, 0x00, {0x01}, 1},
573*4882a593Smuzhiyun 			{0, 0, {0}, 0}
574*4882a593Smuzhiyun 		};
575*4882a593Smuzhiyun 		/* Without this command the cam won't work with USB-UHCI */
576*4882a593Smuzhiyun 		gspca_dev->usb_buf[0] = 0x0a;
577*4882a593Smuzhiyun 		gspca_dev->usb_buf[1] = 0x00;
578*4882a593Smuzhiyun 		err_code = mr_write(gspca_dev, 2);
579*4882a593Smuzhiyun 		if (err_code < 0)
580*4882a593Smuzhiyun 			return err_code;
581*4882a593Smuzhiyun 		err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data,
582*4882a593Smuzhiyun 					 ARRAY_SIZE(cif_sensor1_init_data));
583*4882a593Smuzhiyun 	}
584*4882a593Smuzhiyun 	return err_code;
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun 
start_vga_cam(struct gspca_dev * gspca_dev)587*4882a593Smuzhiyun static int start_vga_cam(struct gspca_dev *gspca_dev)
588*4882a593Smuzhiyun {
589*4882a593Smuzhiyun 	struct sd *sd = (struct sd *) gspca_dev;
590*4882a593Smuzhiyun 	__u8 *data = gspca_dev->usb_buf;
591*4882a593Smuzhiyun 	int err_code;
592*4882a593Smuzhiyun 	static const __u8 startup_string[] =
593*4882a593Smuzhiyun 		{0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b, 0x00, 0x00,
594*4882a593Smuzhiyun 		 0x00, 0x50, 0xc0};
595*4882a593Smuzhiyun 	/* What some of these mean is explained in start_cif_cam(), above */
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	memcpy(data, startup_string, 11);
598*4882a593Smuzhiyun 	if (!sd->sensor_type) {
599*4882a593Smuzhiyun 		data[5]  = 0x00;
600*4882a593Smuzhiyun 		data[10] = 0x91;
601*4882a593Smuzhiyun 	}
602*4882a593Smuzhiyun 	if (sd->sensor_type == 2) {
603*4882a593Smuzhiyun 		data[5]  = 0x00;
604*4882a593Smuzhiyun 		data[10] = 0x18;
605*4882a593Smuzhiyun 	}
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun 	switch (gspca_dev->pixfmt.width) {
608*4882a593Smuzhiyun 	case 160:
609*4882a593Smuzhiyun 		data[9] |= 0x0c;  /* reg 8, 4:1 scale down */
610*4882a593Smuzhiyun 		fallthrough;
611*4882a593Smuzhiyun 	case 320:
612*4882a593Smuzhiyun 		data[9] |= 0x04;  /* reg 8, 2:1 scale down */
613*4882a593Smuzhiyun 		fallthrough;
614*4882a593Smuzhiyun 	case 640:
615*4882a593Smuzhiyun 	default:
616*4882a593Smuzhiyun 		data[3] = 0x50;  /* reg 2, H size/8 */
617*4882a593Smuzhiyun 		data[4] = 0x78;  /* reg 3, V size/4 */
618*4882a593Smuzhiyun 		data[6] = 0x04;  /* reg 5, H start */
619*4882a593Smuzhiyun 		data[8] = 0x03;  /* reg 7, V start */
620*4882a593Smuzhiyun 		if (sd->sensor_type == 2) {
621*4882a593Smuzhiyun 			data[6] = 2;
622*4882a593Smuzhiyun 			data[8] = 1;
623*4882a593Smuzhiyun 		}
624*4882a593Smuzhiyun 		if (sd->do_lcd_stop)
625*4882a593Smuzhiyun 			data[8] = 0x04;  /* Bayer tile shifted */
626*4882a593Smuzhiyun 		break;
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 	case 176:
629*4882a593Smuzhiyun 		data[9] |= 0x04;  /* reg 8, 2:1 scale down */
630*4882a593Smuzhiyun 		fallthrough;
631*4882a593Smuzhiyun 	case 352:
632*4882a593Smuzhiyun 		data[3] = 0x2c;  /* reg 2, H size */
633*4882a593Smuzhiyun 		data[4] = 0x48;  /* reg 3, V size */
634*4882a593Smuzhiyun 		data[6] = 0x94;  /* reg 5, H start */
635*4882a593Smuzhiyun 		data[8] = 0x63;  /* reg 7, V start */
636*4882a593Smuzhiyun 		if (sd->do_lcd_stop)
637*4882a593Smuzhiyun 			data[8] = 0x64;  /* Bayer tile shifted */
638*4882a593Smuzhiyun 		break;
639*4882a593Smuzhiyun 	}
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun 	err_code = mr_write(gspca_dev, 11);
642*4882a593Smuzhiyun 	if (err_code < 0)
643*4882a593Smuzhiyun 		return err_code;
644*4882a593Smuzhiyun 
645*4882a593Smuzhiyun 	if (!sd->sensor_type) {
646*4882a593Smuzhiyun 		static const struct sensor_w_data vga_sensor0_init_data[] = {
647*4882a593Smuzhiyun 			{0x01, 0x00, {0x0c, 0x00, 0x04}, 3},
648*4882a593Smuzhiyun 			{0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4},
649*4882a593Smuzhiyun 			{0x20, 0x00, {0x00, 0x80, 0x00, 0x08}, 4},
650*4882a593Smuzhiyun 			{0x25, 0x00, {0x03, 0xa9, 0x80}, 3},
651*4882a593Smuzhiyun 			{0x30, 0x00, {0x30, 0x18, 0x10, 0x18}, 4},
652*4882a593Smuzhiyun 			{0, 0, {0}, 0}
653*4882a593Smuzhiyun 		};
654*4882a593Smuzhiyun 		err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data,
655*4882a593Smuzhiyun 					 ARRAY_SIZE(vga_sensor0_init_data));
656*4882a593Smuzhiyun 	} else if (sd->sensor_type == 1) {
657*4882a593Smuzhiyun 		static const struct sensor_w_data color_adj[] = {
658*4882a593Smuzhiyun 			{0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
659*4882a593Smuzhiyun 				/* adjusted blue, green, red gain correct
660*4882a593Smuzhiyun 				   too much blue from the Sakar Digital */
661*4882a593Smuzhiyun 				0x05, 0x01, 0x04}, 8}
662*4882a593Smuzhiyun 		};
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 		static const struct sensor_w_data color_no_adj[] = {
665*4882a593Smuzhiyun 			{0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
666*4882a593Smuzhiyun 				/* default blue, green, red gain settings */
667*4882a593Smuzhiyun 				0x07, 0x00, 0x01}, 8}
668*4882a593Smuzhiyun 		};
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 		static const struct sensor_w_data vga_sensor1_init_data[] = {
671*4882a593Smuzhiyun 			{0x11, 0x04, {0x01}, 1},
672*4882a593Smuzhiyun 			{0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01,
673*4882a593Smuzhiyun 			/* These settings may be better for some cameras */
674*4882a593Smuzhiyun 			/* {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, */
675*4882a593Smuzhiyun 				0x00, 0x0a}, 7},
676*4882a593Smuzhiyun 			{0x11, 0x04, {0x01}, 1},
677*4882a593Smuzhiyun 			{0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6},
678*4882a593Smuzhiyun 			{0x11, 0x04, {0x01}, 1},
679*4882a593Smuzhiyun 			{0, 0, {0}, 0}
680*4882a593Smuzhiyun 		};
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 		if (sd->adj_colors)
683*4882a593Smuzhiyun 			err_code = sensor_write_regs(gspca_dev, color_adj,
684*4882a593Smuzhiyun 					 ARRAY_SIZE(color_adj));
685*4882a593Smuzhiyun 		else
686*4882a593Smuzhiyun 			err_code = sensor_write_regs(gspca_dev, color_no_adj,
687*4882a593Smuzhiyun 					 ARRAY_SIZE(color_no_adj));
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun 		if (err_code < 0)
690*4882a593Smuzhiyun 			return err_code;
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 		err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data,
693*4882a593Smuzhiyun 					 ARRAY_SIZE(vga_sensor1_init_data));
694*4882a593Smuzhiyun 	} else {	/* sensor type == 2 */
695*4882a593Smuzhiyun 		static const struct sensor_w_data vga_sensor2_init_data[] = {
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun 			{0x01, 0x00, {0x48}, 1},
698*4882a593Smuzhiyun 			{0x02, 0x00, {0x22}, 1},
699*4882a593Smuzhiyun 			/* Reg 3 msb and 4 is lsb of the exposure setting*/
700*4882a593Smuzhiyun 			{0x05, 0x00, {0x10}, 1},
701*4882a593Smuzhiyun 			{0x06, 0x00, {0x00}, 1},
702*4882a593Smuzhiyun 			{0x07, 0x00, {0x00}, 1},
703*4882a593Smuzhiyun 			{0x08, 0x00, {0x00}, 1},
704*4882a593Smuzhiyun 			{0x09, 0x00, {0x00}, 1},
705*4882a593Smuzhiyun 			/* The following are used in the gain control
706*4882a593Smuzhiyun 			 * which is BTW completely borked in the OEM driver
707*4882a593Smuzhiyun 			 * The values for each color go from 0 to 0x7ff
708*4882a593Smuzhiyun 			 *{0x0a, 0x00, {0x01}, 1},  green1 gain msb
709*4882a593Smuzhiyun 			 *{0x0b, 0x00, {0x10}, 1},  green1 gain lsb
710*4882a593Smuzhiyun 			 *{0x0c, 0x00, {0x01}, 1},  red gain msb
711*4882a593Smuzhiyun 			 *{0x0d, 0x00, {0x10}, 1},  red gain lsb
712*4882a593Smuzhiyun 			 *{0x0e, 0x00, {0x01}, 1},  blue gain msb
713*4882a593Smuzhiyun 			 *{0x0f, 0x00, {0x10}, 1},  blue gain lsb
714*4882a593Smuzhiyun 			 *{0x10, 0x00, {0x01}, 1}, green2 gain msb
715*4882a593Smuzhiyun 			 *{0x11, 0x00, {0x10}, 1}, green2 gain lsb
716*4882a593Smuzhiyun 			 */
717*4882a593Smuzhiyun 			{0x12, 0x00, {0x00}, 1},
718*4882a593Smuzhiyun 			{0x13, 0x00, {0x04}, 1}, /* weird effect on colors */
719*4882a593Smuzhiyun 			{0x14, 0x00, {0x00}, 1},
720*4882a593Smuzhiyun 			{0x15, 0x00, {0x06}, 1},
721*4882a593Smuzhiyun 			{0x16, 0x00, {0x01}, 1},
722*4882a593Smuzhiyun 			{0x17, 0x00, {0xe2}, 1}, /* vertical alignment */
723*4882a593Smuzhiyun 			{0x18, 0x00, {0x02}, 1},
724*4882a593Smuzhiyun 			{0x19, 0x00, {0x82}, 1}, /* don't mess with */
725*4882a593Smuzhiyun 			{0x1a, 0x00, {0x00}, 1},
726*4882a593Smuzhiyun 			{0x1b, 0x00, {0x20}, 1},
727*4882a593Smuzhiyun 			/* {0x1c, 0x00, {0x17}, 1}, contrast control */
728*4882a593Smuzhiyun 			{0x1d, 0x00, {0x80}, 1}, /* moving causes a mess */
729*4882a593Smuzhiyun 			{0x1e, 0x00, {0x08}, 1}, /* moving jams the camera */
730*4882a593Smuzhiyun 			{0x1f, 0x00, {0x0c}, 1},
731*4882a593Smuzhiyun 			{0x20, 0x00, {0x00}, 1},
732*4882a593Smuzhiyun 			{0, 0, {0}, 0}
733*4882a593Smuzhiyun 		};
734*4882a593Smuzhiyun 		err_code = sensor_write_regs(gspca_dev, vga_sensor2_init_data,
735*4882a593Smuzhiyun 					 ARRAY_SIZE(vga_sensor2_init_data));
736*4882a593Smuzhiyun 	}
737*4882a593Smuzhiyun 	return err_code;
738*4882a593Smuzhiyun }
739*4882a593Smuzhiyun 
sd_start(struct gspca_dev * gspca_dev)740*4882a593Smuzhiyun static int sd_start(struct gspca_dev *gspca_dev)
741*4882a593Smuzhiyun {
742*4882a593Smuzhiyun 	struct sd *sd = (struct sd *) gspca_dev;
743*4882a593Smuzhiyun 	int err_code;
744*4882a593Smuzhiyun 
745*4882a593Smuzhiyun 	sd->sof_read = 0;
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 	/* Some of the VGA cameras require the memory pointer
748*4882a593Smuzhiyun 	 * to be set to 0 again. We have been forced to start the
749*4882a593Smuzhiyun 	 * stream in sd_config() to detect the hardware, and closed it.
750*4882a593Smuzhiyun 	 * Thus, we need here to do a completely fresh and clean start. */
751*4882a593Smuzhiyun 	err_code = zero_the_pointer(gspca_dev);
752*4882a593Smuzhiyun 	if (err_code < 0)
753*4882a593Smuzhiyun 		return err_code;
754*4882a593Smuzhiyun 
755*4882a593Smuzhiyun 	err_code = stream_start(gspca_dev);
756*4882a593Smuzhiyun 	if (err_code < 0)
757*4882a593Smuzhiyun 		return err_code;
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun 	if (sd->cam_type == CAM_TYPE_CIF) {
760*4882a593Smuzhiyun 		err_code = start_cif_cam(gspca_dev);
761*4882a593Smuzhiyun 	} else {
762*4882a593Smuzhiyun 		err_code = start_vga_cam(gspca_dev);
763*4882a593Smuzhiyun 	}
764*4882a593Smuzhiyun 	if (err_code < 0)
765*4882a593Smuzhiyun 		return err_code;
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun 	return isoc_enable(gspca_dev);
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun 
sd_stopN(struct gspca_dev * gspca_dev)770*4882a593Smuzhiyun static void sd_stopN(struct gspca_dev *gspca_dev)
771*4882a593Smuzhiyun {
772*4882a593Smuzhiyun 	struct sd *sd = (struct sd *) gspca_dev;
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun 	stream_stop(gspca_dev);
775*4882a593Smuzhiyun 	/* Not all the cams need this, but even if not, probably a good idea */
776*4882a593Smuzhiyun 	zero_the_pointer(gspca_dev);
777*4882a593Smuzhiyun 	if (sd->do_lcd_stop)
778*4882a593Smuzhiyun 		lcd_stop(gspca_dev);
779*4882a593Smuzhiyun }
780*4882a593Smuzhiyun 
setbrightness(struct gspca_dev * gspca_dev,s32 val)781*4882a593Smuzhiyun static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
782*4882a593Smuzhiyun {
783*4882a593Smuzhiyun 	struct sd *sd = (struct sd *) gspca_dev;
784*4882a593Smuzhiyun 	u8 sign_reg = 7;  /* This reg and the next one used on CIF cams. */
785*4882a593Smuzhiyun 	u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */
786*4882a593Smuzhiyun 	static const u8 quick_clix_table[] =
787*4882a593Smuzhiyun 	/*	  0  1  2   3  4  5  6  7  8  9  10  11  12  13  14  15 */
788*4882a593Smuzhiyun 		{ 0, 4, 8, 12, 1, 2, 3, 5, 6, 9,  7, 10, 13, 11, 14, 15};
789*4882a593Smuzhiyun 	if (sd->cam_type == CAM_TYPE_VGA) {
790*4882a593Smuzhiyun 		sign_reg += 4;
791*4882a593Smuzhiyun 		value_reg += 4;
792*4882a593Smuzhiyun 	}
793*4882a593Smuzhiyun 
794*4882a593Smuzhiyun 	/* Note register 7 is also seen as 0x8x or 0xCx in some dumps */
795*4882a593Smuzhiyun 	if (val > 0) {
796*4882a593Smuzhiyun 		sensor_write1(gspca_dev, sign_reg, 0x00);
797*4882a593Smuzhiyun 	} else {
798*4882a593Smuzhiyun 		sensor_write1(gspca_dev, sign_reg, 0x01);
799*4882a593Smuzhiyun 		val = 257 - val;
800*4882a593Smuzhiyun 	}
801*4882a593Smuzhiyun 	/* Use lookup table for funky Argus QuickClix brightness */
802*4882a593Smuzhiyun 	if (sd->do_lcd_stop)
803*4882a593Smuzhiyun 		val = quick_clix_table[val];
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun 	sensor_write1(gspca_dev, value_reg, val);
806*4882a593Smuzhiyun }
807*4882a593Smuzhiyun 
setexposure(struct gspca_dev * gspca_dev,s32 expo,s32 min_clockdiv)808*4882a593Smuzhiyun static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 min_clockdiv)
809*4882a593Smuzhiyun {
810*4882a593Smuzhiyun 	struct sd *sd = (struct sd *) gspca_dev;
811*4882a593Smuzhiyun 	int exposure = MR97310A_EXPOSURE_DEFAULT;
812*4882a593Smuzhiyun 	u8 buf[2];
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun 	if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) {
815*4882a593Smuzhiyun 		/* This cam does not like exposure settings < 300,
816*4882a593Smuzhiyun 		   so scale 0 - 4095 to 300 - 4095 */
817*4882a593Smuzhiyun 		exposure = (expo * 9267) / 10000 + 300;
818*4882a593Smuzhiyun 		sensor_write1(gspca_dev, 3, exposure >> 4);
819*4882a593Smuzhiyun 		sensor_write1(gspca_dev, 4, exposure & 0x0f);
820*4882a593Smuzhiyun 	} else if (sd->sensor_type == 2) {
821*4882a593Smuzhiyun 		exposure = expo;
822*4882a593Smuzhiyun 		exposure >>= 3;
823*4882a593Smuzhiyun 		sensor_write1(gspca_dev, 3, exposure >> 8);
824*4882a593Smuzhiyun 		sensor_write1(gspca_dev, 4, exposure & 0xff);
825*4882a593Smuzhiyun 	} else {
826*4882a593Smuzhiyun 		/* We have both a clock divider and an exposure register.
827*4882a593Smuzhiyun 		   We first calculate the clock divider, as that determines
828*4882a593Smuzhiyun 		   the maximum exposure and then we calculate the exposure
829*4882a593Smuzhiyun 		   register setting (which goes from 0 - 511).
830*4882a593Smuzhiyun 
831*4882a593Smuzhiyun 		   Note our 0 - 4095 exposure is mapped to 0 - 511
832*4882a593Smuzhiyun 		   milliseconds exposure time */
833*4882a593Smuzhiyun 		u8 clockdiv = (60 * expo + 7999) / 8000;
834*4882a593Smuzhiyun 
835*4882a593Smuzhiyun 		/* Limit framerate to not exceed usb bandwidth */
836*4882a593Smuzhiyun 		if (clockdiv < min_clockdiv && gspca_dev->pixfmt.width >= 320)
837*4882a593Smuzhiyun 			clockdiv = min_clockdiv;
838*4882a593Smuzhiyun 		else if (clockdiv < 2)
839*4882a593Smuzhiyun 			clockdiv = 2;
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun 		if (sd->cam_type == CAM_TYPE_VGA && clockdiv < 4)
842*4882a593Smuzhiyun 			clockdiv = 4;
843*4882a593Smuzhiyun 
844*4882a593Smuzhiyun 		/* Frame exposure time in ms = 1000 * clockdiv / 60 ->
845*4882a593Smuzhiyun 		exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */
846*4882a593Smuzhiyun 		exposure = (60 * 511 * expo) / (8000 * clockdiv);
847*4882a593Smuzhiyun 		if (exposure > 511)
848*4882a593Smuzhiyun 			exposure = 511;
849*4882a593Smuzhiyun 
850*4882a593Smuzhiyun 		/* exposure register value is reversed! */
851*4882a593Smuzhiyun 		exposure = 511 - exposure;
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun 		buf[0] = exposure & 0xff;
854*4882a593Smuzhiyun 		buf[1] = exposure >> 8;
855*4882a593Smuzhiyun 		sensor_write_reg(gspca_dev, 0x0e, 0, buf, 2);
856*4882a593Smuzhiyun 		sensor_write1(gspca_dev, 0x02, clockdiv);
857*4882a593Smuzhiyun 	}
858*4882a593Smuzhiyun }
859*4882a593Smuzhiyun 
setgain(struct gspca_dev * gspca_dev,s32 val)860*4882a593Smuzhiyun static void setgain(struct gspca_dev *gspca_dev, s32 val)
861*4882a593Smuzhiyun {
862*4882a593Smuzhiyun 	struct sd *sd = (struct sd *) gspca_dev;
863*4882a593Smuzhiyun 	u8 gainreg;
864*4882a593Smuzhiyun 
865*4882a593Smuzhiyun 	if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1)
866*4882a593Smuzhiyun 		sensor_write1(gspca_dev, 0x0e, val);
867*4882a593Smuzhiyun 	else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2)
868*4882a593Smuzhiyun 		for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) {
869*4882a593Smuzhiyun 			sensor_write1(gspca_dev, gainreg, val >> 8);
870*4882a593Smuzhiyun 			sensor_write1(gspca_dev, gainreg + 1, val & 0xff);
871*4882a593Smuzhiyun 		}
872*4882a593Smuzhiyun 	else
873*4882a593Smuzhiyun 		sensor_write1(gspca_dev, 0x10, val);
874*4882a593Smuzhiyun }
875*4882a593Smuzhiyun 
setcontrast(struct gspca_dev * gspca_dev,s32 val)876*4882a593Smuzhiyun static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
877*4882a593Smuzhiyun {
878*4882a593Smuzhiyun 	sensor_write1(gspca_dev, 0x1c, val);
879*4882a593Smuzhiyun }
880*4882a593Smuzhiyun 
sd_s_ctrl(struct v4l2_ctrl * ctrl)881*4882a593Smuzhiyun static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
882*4882a593Smuzhiyun {
883*4882a593Smuzhiyun 	struct gspca_dev *gspca_dev =
884*4882a593Smuzhiyun 		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
885*4882a593Smuzhiyun 	struct sd *sd = (struct sd *)gspca_dev;
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 	gspca_dev->usb_err = 0;
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun 	if (!gspca_dev->streaming)
890*4882a593Smuzhiyun 		return 0;
891*4882a593Smuzhiyun 
892*4882a593Smuzhiyun 	switch (ctrl->id) {
893*4882a593Smuzhiyun 	case V4L2_CID_BRIGHTNESS:
894*4882a593Smuzhiyun 		setbrightness(gspca_dev, ctrl->val);
895*4882a593Smuzhiyun 		break;
896*4882a593Smuzhiyun 	case V4L2_CID_CONTRAST:
897*4882a593Smuzhiyun 		setcontrast(gspca_dev, ctrl->val);
898*4882a593Smuzhiyun 		break;
899*4882a593Smuzhiyun 	case V4L2_CID_EXPOSURE:
900*4882a593Smuzhiyun 		setexposure(gspca_dev, sd->exposure->val,
901*4882a593Smuzhiyun 			    sd->min_clockdiv ? sd->min_clockdiv->val : 0);
902*4882a593Smuzhiyun 		break;
903*4882a593Smuzhiyun 	case V4L2_CID_GAIN:
904*4882a593Smuzhiyun 		setgain(gspca_dev, ctrl->val);
905*4882a593Smuzhiyun 		break;
906*4882a593Smuzhiyun 	}
907*4882a593Smuzhiyun 	return gspca_dev->usb_err;
908*4882a593Smuzhiyun }
909*4882a593Smuzhiyun 
910*4882a593Smuzhiyun static const struct v4l2_ctrl_ops sd_ctrl_ops = {
911*4882a593Smuzhiyun 	.s_ctrl = sd_s_ctrl,
912*4882a593Smuzhiyun };
913*4882a593Smuzhiyun 
sd_init_controls(struct gspca_dev * gspca_dev)914*4882a593Smuzhiyun static int sd_init_controls(struct gspca_dev *gspca_dev)
915*4882a593Smuzhiyun {
916*4882a593Smuzhiyun 	struct sd *sd = (struct sd *)gspca_dev;
917*4882a593Smuzhiyun 	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
918*4882a593Smuzhiyun 	static const struct v4l2_ctrl_config clockdiv = {
919*4882a593Smuzhiyun 		.ops = &sd_ctrl_ops,
920*4882a593Smuzhiyun 		.id = MR97310A_CID_CLOCKDIV,
921*4882a593Smuzhiyun 		.type = V4L2_CTRL_TYPE_INTEGER,
922*4882a593Smuzhiyun 		.name = "Minimum Clock Divider",
923*4882a593Smuzhiyun 		.min = MR97310A_MIN_CLOCKDIV_MIN,
924*4882a593Smuzhiyun 		.max = MR97310A_MIN_CLOCKDIV_MAX,
925*4882a593Smuzhiyun 		.step = 1,
926*4882a593Smuzhiyun 		.def = MR97310A_MIN_CLOCKDIV_DEFAULT,
927*4882a593Smuzhiyun 	};
928*4882a593Smuzhiyun 	bool has_brightness = false;
929*4882a593Smuzhiyun 	bool has_argus_brightness = false;
930*4882a593Smuzhiyun 	bool has_contrast = false;
931*4882a593Smuzhiyun 	bool has_gain = false;
932*4882a593Smuzhiyun 	bool has_cs_gain = false;
933*4882a593Smuzhiyun 	bool has_exposure = false;
934*4882a593Smuzhiyun 	bool has_clockdiv = false;
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun 	gspca_dev->vdev.ctrl_handler = hdl;
937*4882a593Smuzhiyun 	v4l2_ctrl_handler_init(hdl, 4);
938*4882a593Smuzhiyun 
939*4882a593Smuzhiyun 	/* Setup controls depending on camera type */
940*4882a593Smuzhiyun 	if (sd->cam_type == CAM_TYPE_CIF) {
941*4882a593Smuzhiyun 		/* No brightness for sensor_type 0 */
942*4882a593Smuzhiyun 		if (sd->sensor_type == 0)
943*4882a593Smuzhiyun 			has_exposure = has_gain = has_clockdiv = true;
944*4882a593Smuzhiyun 		else
945*4882a593Smuzhiyun 			has_exposure = has_gain = has_brightness = true;
946*4882a593Smuzhiyun 	} else {
947*4882a593Smuzhiyun 		/* All controls need to be disabled if VGA sensor_type is 0 */
948*4882a593Smuzhiyun 		if (sd->sensor_type == 0)
949*4882a593Smuzhiyun 			; /* no controls! */
950*4882a593Smuzhiyun 		else if (sd->sensor_type == 2)
951*4882a593Smuzhiyun 			has_exposure = has_cs_gain = has_contrast = true;
952*4882a593Smuzhiyun 		else if (sd->do_lcd_stop)
953*4882a593Smuzhiyun 			has_exposure = has_gain = has_argus_brightness =
954*4882a593Smuzhiyun 				has_clockdiv = true;
955*4882a593Smuzhiyun 		else
956*4882a593Smuzhiyun 			has_exposure = has_gain = has_brightness =
957*4882a593Smuzhiyun 				has_clockdiv = true;
958*4882a593Smuzhiyun 	}
959*4882a593Smuzhiyun 
960*4882a593Smuzhiyun 	/* Separate brightness control description for Argus QuickClix as it has
961*4882a593Smuzhiyun 	 * different limits from the other mr97310a cameras, and separate gain
962*4882a593Smuzhiyun 	 * control for Sakar CyberPix camera. */
963*4882a593Smuzhiyun 	/*
964*4882a593Smuzhiyun 	 * This control is disabled for CIF type 1 and VGA type 0 cameras.
965*4882a593Smuzhiyun 	 * It does not quite act linearly for the Argus QuickClix camera,
966*4882a593Smuzhiyun 	 * but it does control brightness. The values are 0 - 15 only, and
967*4882a593Smuzhiyun 	 * the table above makes them act consecutively.
968*4882a593Smuzhiyun 	 */
969*4882a593Smuzhiyun 	if (has_brightness)
970*4882a593Smuzhiyun 		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
971*4882a593Smuzhiyun 			V4L2_CID_BRIGHTNESS, -254, 255, 1,
972*4882a593Smuzhiyun 			MR97310A_BRIGHTNESS_DEFAULT);
973*4882a593Smuzhiyun 	else if (has_argus_brightness)
974*4882a593Smuzhiyun 		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
975*4882a593Smuzhiyun 			V4L2_CID_BRIGHTNESS, 0, 15, 1,
976*4882a593Smuzhiyun 			MR97310A_BRIGHTNESS_DEFAULT);
977*4882a593Smuzhiyun 	if (has_contrast)
978*4882a593Smuzhiyun 		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
979*4882a593Smuzhiyun 			V4L2_CID_CONTRAST, MR97310A_CONTRAST_MIN,
980*4882a593Smuzhiyun 			MR97310A_CONTRAST_MAX, 1, MR97310A_CONTRAST_DEFAULT);
981*4882a593Smuzhiyun 	if (has_gain)
982*4882a593Smuzhiyun 		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
983*4882a593Smuzhiyun 			V4L2_CID_GAIN, MR97310A_GAIN_MIN, MR97310A_GAIN_MAX,
984*4882a593Smuzhiyun 			1, MR97310A_GAIN_DEFAULT);
985*4882a593Smuzhiyun 	else if (has_cs_gain)
986*4882a593Smuzhiyun 		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_GAIN,
987*4882a593Smuzhiyun 			MR97310A_CS_GAIN_MIN, MR97310A_CS_GAIN_MAX,
988*4882a593Smuzhiyun 			1, MR97310A_CS_GAIN_DEFAULT);
989*4882a593Smuzhiyun 	if (has_exposure)
990*4882a593Smuzhiyun 		sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
991*4882a593Smuzhiyun 			V4L2_CID_EXPOSURE, MR97310A_EXPOSURE_MIN,
992*4882a593Smuzhiyun 			MR97310A_EXPOSURE_MAX, 1, MR97310A_EXPOSURE_DEFAULT);
993*4882a593Smuzhiyun 	if (has_clockdiv)
994*4882a593Smuzhiyun 		sd->min_clockdiv = v4l2_ctrl_new_custom(hdl, &clockdiv, NULL);
995*4882a593Smuzhiyun 
996*4882a593Smuzhiyun 	if (hdl->error) {
997*4882a593Smuzhiyun 		pr_err("Could not initialize controls\n");
998*4882a593Smuzhiyun 		return hdl->error;
999*4882a593Smuzhiyun 	}
1000*4882a593Smuzhiyun 	if (has_exposure && has_clockdiv)
1001*4882a593Smuzhiyun 		v4l2_ctrl_cluster(2, &sd->exposure);
1002*4882a593Smuzhiyun 	return 0;
1003*4882a593Smuzhiyun }
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun /* Include pac common sof detection functions */
1006*4882a593Smuzhiyun #include "pac_common.h"
1007*4882a593Smuzhiyun 
sd_pkt_scan(struct gspca_dev * gspca_dev,u8 * data,int len)1008*4882a593Smuzhiyun static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1009*4882a593Smuzhiyun 			u8 *data,		/* isoc packet */
1010*4882a593Smuzhiyun 			int len)		/* iso packet length */
1011*4882a593Smuzhiyun {
1012*4882a593Smuzhiyun 	struct sd *sd = (struct sd *) gspca_dev;
1013*4882a593Smuzhiyun 	unsigned char *sof;
1014*4882a593Smuzhiyun 
1015*4882a593Smuzhiyun 	sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
1016*4882a593Smuzhiyun 	if (sof) {
1017*4882a593Smuzhiyun 		int n;
1018*4882a593Smuzhiyun 
1019*4882a593Smuzhiyun 		/* finish decoding current frame */
1020*4882a593Smuzhiyun 		n = sof - data;
1021*4882a593Smuzhiyun 		if (n > sizeof pac_sof_marker)
1022*4882a593Smuzhiyun 			n -= sizeof pac_sof_marker;
1023*4882a593Smuzhiyun 		else
1024*4882a593Smuzhiyun 			n = 0;
1025*4882a593Smuzhiyun 		gspca_frame_add(gspca_dev, LAST_PACKET,
1026*4882a593Smuzhiyun 					data, n);
1027*4882a593Smuzhiyun 		/* Start next frame. */
1028*4882a593Smuzhiyun 		gspca_frame_add(gspca_dev, FIRST_PACKET,
1029*4882a593Smuzhiyun 			pac_sof_marker, sizeof pac_sof_marker);
1030*4882a593Smuzhiyun 		len -= sof - data;
1031*4882a593Smuzhiyun 		data = sof;
1032*4882a593Smuzhiyun 	}
1033*4882a593Smuzhiyun 	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1034*4882a593Smuzhiyun }
1035*4882a593Smuzhiyun 
1036*4882a593Smuzhiyun /* sub-driver description */
1037*4882a593Smuzhiyun static const struct sd_desc sd_desc = {
1038*4882a593Smuzhiyun 	.name = MODULE_NAME,
1039*4882a593Smuzhiyun 	.config = sd_config,
1040*4882a593Smuzhiyun 	.init = sd_init,
1041*4882a593Smuzhiyun 	.init_controls = sd_init_controls,
1042*4882a593Smuzhiyun 	.start = sd_start,
1043*4882a593Smuzhiyun 	.stopN = sd_stopN,
1044*4882a593Smuzhiyun 	.pkt_scan = sd_pkt_scan,
1045*4882a593Smuzhiyun };
1046*4882a593Smuzhiyun 
1047*4882a593Smuzhiyun /* -- module initialisation -- */
1048*4882a593Smuzhiyun static const struct usb_device_id device_table[] = {
1049*4882a593Smuzhiyun 	{USB_DEVICE(0x08ca, 0x0110)},	/* Trust Spyc@m 100 */
1050*4882a593Smuzhiyun 	{USB_DEVICE(0x08ca, 0x0111)},	/* Aiptek Pencam VGA+ */
1051*4882a593Smuzhiyun 	{USB_DEVICE(0x093a, 0x010f)},	/* All other known MR97310A VGA cams */
1052*4882a593Smuzhiyun 	{USB_DEVICE(0x093a, 0x010e)},	/* All known MR97310A CIF cams */
1053*4882a593Smuzhiyun 	{}
1054*4882a593Smuzhiyun };
1055*4882a593Smuzhiyun MODULE_DEVICE_TABLE(usb, device_table);
1056*4882a593Smuzhiyun 
1057*4882a593Smuzhiyun /* -- device connect -- */
sd_probe(struct usb_interface * intf,const struct usb_device_id * id)1058*4882a593Smuzhiyun static int sd_probe(struct usb_interface *intf,
1059*4882a593Smuzhiyun 		    const struct usb_device_id *id)
1060*4882a593Smuzhiyun {
1061*4882a593Smuzhiyun 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1062*4882a593Smuzhiyun 			       THIS_MODULE);
1063*4882a593Smuzhiyun }
1064*4882a593Smuzhiyun 
1065*4882a593Smuzhiyun static struct usb_driver sd_driver = {
1066*4882a593Smuzhiyun 	.name = MODULE_NAME,
1067*4882a593Smuzhiyun 	.id_table = device_table,
1068*4882a593Smuzhiyun 	.probe = sd_probe,
1069*4882a593Smuzhiyun 	.disconnect = gspca_disconnect,
1070*4882a593Smuzhiyun #ifdef CONFIG_PM
1071*4882a593Smuzhiyun 	.suspend = gspca_suspend,
1072*4882a593Smuzhiyun 	.resume = gspca_resume,
1073*4882a593Smuzhiyun 	.reset_resume = gspca_resume,
1074*4882a593Smuzhiyun #endif
1075*4882a593Smuzhiyun };
1076*4882a593Smuzhiyun 
1077*4882a593Smuzhiyun module_usb_driver(sd_driver);
1078