• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  * Plug-in for PAS202BCB image sensor connected to the ZC0301 Image        *
3  * Processor and Control Chip                                              *
4  *                                                                         *
5  * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
6  *                                                                         *
7  * Initialization values of the ZC0301[P] have been taken from the SPCA5XX *
8  * driver maintained by Michel Xhaard <mxhaard@magic.fr>                   *
9  *                                                                         *
10  * This program is free software; you can redistribute it and/or modify    *
11  * it under the terms of the GNU General Public License as published by    *
12  * the Free Software Foundation; either version 2 of the License, or       *
13  * (at your option) any later version.                                     *
14  *                                                                         *
15  * This program is distributed in the hope that it will be useful,         *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
18  * GNU General Public License for more details.                            *
19  *                                                                         *
20  * You should have received a copy of the GNU General Public License       *
21  * along with this program; if not, write to the Free Software             *
22  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
23  ***************************************************************************/
24 
25 /*
26    NOTE: Sensor controls are disabled for now, becouse changing them while
27 	 streaming sometimes results in out-of-sync video frames. We'll use
28 	 the default initialization, until we know how to stop and start video
29 	 in the chip. However, the image quality still looks good under various
30 	 light conditions.
31 */
32 
33 #include <linux/delay.h>
34 #include "zc0301_sensor.h"
35 
36 
37 static struct zc0301_sensor pas202bcb;
38 
39 
pas202bcb_init(struct zc0301_device * cam)40 static int pas202bcb_init(struct zc0301_device* cam)
41 {
42 	int err = 0;
43 
44 	err += zc0301_write_reg(cam, 0x0002, 0x00);
45 	err += zc0301_write_reg(cam, 0x0003, 0x02);
46 	err += zc0301_write_reg(cam, 0x0004, 0x80);
47 	err += zc0301_write_reg(cam, 0x0005, 0x01);
48 	err += zc0301_write_reg(cam, 0x0006, 0xE0);
49 	err += zc0301_write_reg(cam, 0x0098, 0x00);
50 	err += zc0301_write_reg(cam, 0x009A, 0x03);
51 	err += zc0301_write_reg(cam, 0x011A, 0x00);
52 	err += zc0301_write_reg(cam, 0x011C, 0x03);
53 	err += zc0301_write_reg(cam, 0x009B, 0x01);
54 	err += zc0301_write_reg(cam, 0x009C, 0xE6);
55 	err += zc0301_write_reg(cam, 0x009D, 0x02);
56 	err += zc0301_write_reg(cam, 0x009E, 0x86);
57 
58 	err += zc0301_i2c_write(cam, 0x02, 0x02);
59 	err += zc0301_i2c_write(cam, 0x0A, 0x01);
60 	err += zc0301_i2c_write(cam, 0x0B, 0x01);
61 	err += zc0301_i2c_write(cam, 0x0D, 0x00);
62 	err += zc0301_i2c_write(cam, 0x12, 0x05);
63 	err += zc0301_i2c_write(cam, 0x13, 0x63);
64 	err += zc0301_i2c_write(cam, 0x15, 0x70);
65 
66 	err += zc0301_write_reg(cam, 0x0101, 0xB7);
67 	err += zc0301_write_reg(cam, 0x0100, 0x0D);
68 	err += zc0301_write_reg(cam, 0x0189, 0x06);
69 	err += zc0301_write_reg(cam, 0x01AD, 0x00);
70 	err += zc0301_write_reg(cam, 0x01C5, 0x03);
71 	err += zc0301_write_reg(cam, 0x01CB, 0x13);
72 	err += zc0301_write_reg(cam, 0x0250, 0x08);
73 	err += zc0301_write_reg(cam, 0x0301, 0x08);
74 	err += zc0301_write_reg(cam, 0x018D, 0x70);
75 	err += zc0301_write_reg(cam, 0x0008, 0x03);
76 	err += zc0301_write_reg(cam, 0x01C6, 0x04);
77 	err += zc0301_write_reg(cam, 0x01CB, 0x07);
78 	err += zc0301_write_reg(cam, 0x0120, 0x11);
79 	err += zc0301_write_reg(cam, 0x0121, 0x37);
80 	err += zc0301_write_reg(cam, 0x0122, 0x58);
81 	err += zc0301_write_reg(cam, 0x0123, 0x79);
82 	err += zc0301_write_reg(cam, 0x0124, 0x91);
83 	err += zc0301_write_reg(cam, 0x0125, 0xA6);
84 	err += zc0301_write_reg(cam, 0x0126, 0xB8);
85 	err += zc0301_write_reg(cam, 0x0127, 0xC7);
86 	err += zc0301_write_reg(cam, 0x0128, 0xD3);
87 	err += zc0301_write_reg(cam, 0x0129, 0xDE);
88 	err += zc0301_write_reg(cam, 0x012A, 0xE6);
89 	err += zc0301_write_reg(cam, 0x012B, 0xED);
90 	err += zc0301_write_reg(cam, 0x012C, 0xF3);
91 	err += zc0301_write_reg(cam, 0x012D, 0xF8);
92 	err += zc0301_write_reg(cam, 0x012E, 0xFB);
93 	err += zc0301_write_reg(cam, 0x012F, 0xFF);
94 	err += zc0301_write_reg(cam, 0x0130, 0x26);
95 	err += zc0301_write_reg(cam, 0x0131, 0x23);
96 	err += zc0301_write_reg(cam, 0x0132, 0x20);
97 	err += zc0301_write_reg(cam, 0x0133, 0x1C);
98 	err += zc0301_write_reg(cam, 0x0134, 0x16);
99 	err += zc0301_write_reg(cam, 0x0135, 0x13);
100 	err += zc0301_write_reg(cam, 0x0136, 0x10);
101 	err += zc0301_write_reg(cam, 0x0137, 0x0D);
102 	err += zc0301_write_reg(cam, 0x0138, 0x0B);
103 	err += zc0301_write_reg(cam, 0x0139, 0x09);
104 	err += zc0301_write_reg(cam, 0x013A, 0x07);
105 	err += zc0301_write_reg(cam, 0x013B, 0x06);
106 	err += zc0301_write_reg(cam, 0x013C, 0x05);
107 	err += zc0301_write_reg(cam, 0x013D, 0x04);
108 	err += zc0301_write_reg(cam, 0x013E, 0x03);
109 	err += zc0301_write_reg(cam, 0x013F, 0x02);
110 	err += zc0301_write_reg(cam, 0x010A, 0x4C);
111 	err += zc0301_write_reg(cam, 0x010B, 0xF5);
112 	err += zc0301_write_reg(cam, 0x010C, 0xFF);
113 	err += zc0301_write_reg(cam, 0x010D, 0xF9);
114 	err += zc0301_write_reg(cam, 0x010E, 0x51);
115 	err += zc0301_write_reg(cam, 0x010F, 0xF5);
116 	err += zc0301_write_reg(cam, 0x0110, 0xFB);
117 	err += zc0301_write_reg(cam, 0x0111, 0xED);
118 	err += zc0301_write_reg(cam, 0x0112, 0x5F);
119 	err += zc0301_write_reg(cam, 0x0180, 0x00);
120 	err += zc0301_write_reg(cam, 0x0019, 0x00);
121 	err += zc0301_write_reg(cam, 0x0087, 0x20);
122 	err += zc0301_write_reg(cam, 0x0088, 0x21);
123 
124 	err += zc0301_i2c_write(cam, 0x20, 0x02);
125 	err += zc0301_i2c_write(cam, 0x21, 0x1B);
126 	err += zc0301_i2c_write(cam, 0x03, 0x44);
127 	err += zc0301_i2c_write(cam, 0x0E, 0x01);
128 	err += zc0301_i2c_write(cam, 0x0F, 0x00);
129 
130 	err += zc0301_write_reg(cam, 0x01A9, 0x14);
131 	err += zc0301_write_reg(cam, 0x01AA, 0x24);
132 	err += zc0301_write_reg(cam, 0x0190, 0x00);
133 	err += zc0301_write_reg(cam, 0x0191, 0x02);
134 	err += zc0301_write_reg(cam, 0x0192, 0x1B);
135 	err += zc0301_write_reg(cam, 0x0195, 0x00);
136 	err += zc0301_write_reg(cam, 0x0196, 0x00);
137 	err += zc0301_write_reg(cam, 0x0197, 0x4D);
138 	err += zc0301_write_reg(cam, 0x018C, 0x10);
139 	err += zc0301_write_reg(cam, 0x018F, 0x20);
140 	err += zc0301_write_reg(cam, 0x001D, 0x44);
141 	err += zc0301_write_reg(cam, 0x001E, 0x6F);
142 	err += zc0301_write_reg(cam, 0x001F, 0xAD);
143 	err += zc0301_write_reg(cam, 0x0020, 0xEB);
144 	err += zc0301_write_reg(cam, 0x0087, 0x0F);
145 	err += zc0301_write_reg(cam, 0x0088, 0x0E);
146 	err += zc0301_write_reg(cam, 0x0180, 0x40);
147 	err += zc0301_write_reg(cam, 0x0192, 0x1B);
148 	err += zc0301_write_reg(cam, 0x0191, 0x02);
149 	err += zc0301_write_reg(cam, 0x0190, 0x00);
150 	err += zc0301_write_reg(cam, 0x0116, 0x1D);
151 	err += zc0301_write_reg(cam, 0x0117, 0x40);
152 	err += zc0301_write_reg(cam, 0x0118, 0x99);
153 	err += zc0301_write_reg(cam, 0x0180, 0x42);
154 	err += zc0301_write_reg(cam, 0x0116, 0x1D);
155 	err += zc0301_write_reg(cam, 0x0117, 0x40);
156 	err += zc0301_write_reg(cam, 0x0118, 0x99);
157 	err += zc0301_write_reg(cam, 0x0007, 0x00);
158 
159 	err += zc0301_i2c_write(cam, 0x11, 0x01);
160 
161 	msleep(100);
162 
163 	return err;
164 }
165 
166 
pas202bcb_get_ctrl(struct zc0301_device * cam,struct v4l2_control * ctrl)167 static int pas202bcb_get_ctrl(struct zc0301_device* cam,
168 			      struct v4l2_control* ctrl)
169 {
170 	switch (ctrl->id) {
171 	case V4L2_CID_EXPOSURE:
172 		{
173 			int r1 = zc0301_i2c_read(cam, 0x04, 1),
174 			    r2 = zc0301_i2c_read(cam, 0x05, 1);
175 			if (r1 < 0 || r2 < 0)
176 				return -EIO;
177 			ctrl->value = (r1 << 6) | (r2 & 0x3f);
178 		}
179 		return 0;
180 	case V4L2_CID_RED_BALANCE:
181 		if ((ctrl->value = zc0301_i2c_read(cam, 0x09, 1)) < 0)
182 			return -EIO;
183 		ctrl->value &= 0x0f;
184 		return 0;
185 	case V4L2_CID_BLUE_BALANCE:
186 		if ((ctrl->value = zc0301_i2c_read(cam, 0x07, 1)) < 0)
187 			return -EIO;
188 		ctrl->value &= 0x0f;
189 		return 0;
190 	case V4L2_CID_GAIN:
191 		if ((ctrl->value = zc0301_i2c_read(cam, 0x10, 1)) < 0)
192 			return -EIO;
193 		ctrl->value &= 0x1f;
194 		return 0;
195 	case ZC0301_V4L2_CID_GREEN_BALANCE:
196 		if ((ctrl->value = zc0301_i2c_read(cam, 0x08, 1)) < 0)
197 			return -EIO;
198 		ctrl->value &= 0x0f;
199 		return 0;
200 	case ZC0301_V4L2_CID_DAC_MAGNITUDE:
201 		if ((ctrl->value = zc0301_i2c_read(cam, 0x0c, 1)) < 0)
202 			return -EIO;
203 		return 0;
204 	default:
205 		return -EINVAL;
206 	}
207 }
208 
209 
pas202bcb_set_ctrl(struct zc0301_device * cam,const struct v4l2_control * ctrl)210 static int pas202bcb_set_ctrl(struct zc0301_device* cam,
211 			      const struct v4l2_control* ctrl)
212 {
213 	int err = 0;
214 
215 	switch (ctrl->id) {
216 	case V4L2_CID_EXPOSURE:
217 		err += zc0301_i2c_write(cam, 0x04, ctrl->value >> 6);
218 		err += zc0301_i2c_write(cam, 0x05, ctrl->value & 0x3f);
219 		break;
220 	case V4L2_CID_RED_BALANCE:
221 		err += zc0301_i2c_write(cam, 0x09, ctrl->value);
222 		break;
223 	case V4L2_CID_BLUE_BALANCE:
224 		err += zc0301_i2c_write(cam, 0x07, ctrl->value);
225 		break;
226 	case V4L2_CID_GAIN:
227 		err += zc0301_i2c_write(cam, 0x10, ctrl->value);
228 		break;
229 	case ZC0301_V4L2_CID_GREEN_BALANCE:
230 		err += zc0301_i2c_write(cam, 0x08, ctrl->value);
231 		break;
232 	case ZC0301_V4L2_CID_DAC_MAGNITUDE:
233 		err += zc0301_i2c_write(cam, 0x0c, ctrl->value);
234 		break;
235 	default:
236 		return -EINVAL;
237 	}
238 	err += zc0301_i2c_write(cam, 0x11, 0x01);
239 
240 	return err ? -EIO : 0;
241 }
242 
243 
244 static struct zc0301_sensor pas202bcb = {
245 	.name = "PAS202BCB",
246 	.init = &pas202bcb_init,
247 	.qctrl = {
248 		{
249 			.id = V4L2_CID_EXPOSURE,
250 			.type = V4L2_CTRL_TYPE_INTEGER,
251 			.name = "exposure",
252 			.minimum = 0x01e5,
253 			.maximum = 0x3fff,
254 			.step = 0x0001,
255 			.default_value = 0x01e5,
256 			.flags = V4L2_CTRL_FLAG_DISABLED,
257 		},
258 		{
259 			.id = V4L2_CID_GAIN,
260 			.type = V4L2_CTRL_TYPE_INTEGER,
261 			.name = "global gain",
262 			.minimum = 0x00,
263 			.maximum = 0x1f,
264 			.step = 0x01,
265 			.default_value = 0x0c,
266 			.flags = V4L2_CTRL_FLAG_DISABLED,
267 		},
268 		{
269 			.id = ZC0301_V4L2_CID_DAC_MAGNITUDE,
270 			.type = V4L2_CTRL_TYPE_INTEGER,
271 			.name = "DAC magnitude",
272 			.minimum = 0x00,
273 			.maximum = 0xff,
274 			.step = 0x01,
275 			.default_value = 0x00,
276 			.flags = V4L2_CTRL_FLAG_DISABLED,
277 		},
278 		{
279 			.id = V4L2_CID_RED_BALANCE,
280 			.type = V4L2_CTRL_TYPE_INTEGER,
281 			.name = "red balance",
282 			.minimum = 0x00,
283 			.maximum = 0x0f,
284 			.step = 0x01,
285 			.default_value = 0x01,
286 			.flags = V4L2_CTRL_FLAG_DISABLED,
287 		},
288 		{
289 			.id = V4L2_CID_BLUE_BALANCE,
290 			.type = V4L2_CTRL_TYPE_INTEGER,
291 			.name = "blue balance",
292 			.minimum = 0x00,
293 			.maximum = 0x0f,
294 			.step = 0x01,
295 			.default_value = 0x05,
296 			.flags = V4L2_CTRL_FLAG_DISABLED,
297 		},
298 		{
299 			.id = ZC0301_V4L2_CID_GREEN_BALANCE,
300 			.type = V4L2_CTRL_TYPE_INTEGER,
301 			.name = "green balance",
302 			.minimum = 0x00,
303 			.maximum = 0x0f,
304 			.step = 0x01,
305 			.default_value = 0x00,
306 			.flags = V4L2_CTRL_FLAG_DISABLED,
307 		},
308 	},
309 	.get_ctrl = &pas202bcb_get_ctrl,
310 	.set_ctrl = &pas202bcb_set_ctrl,
311 	.cropcap = {
312 		.bounds = {
313 			.left = 0,
314 			.top = 0,
315 			.width = 640,
316 			.height = 480,
317 		},
318 		.defrect = {
319 			.left = 0,
320 			.top = 0,
321 			.width = 640,
322 			.height = 480,
323 		},
324 	},
325 	.pix_format = {
326 		.width = 640,
327 		.height = 480,
328 		.pixelformat = V4L2_PIX_FMT_JPEG,
329 		.priv = 8,
330 		.colorspace = V4L2_COLORSPACE_JPEG,
331 	},
332 };
333 
334 
zc0301_probe_pas202bcb(struct zc0301_device * cam)335 int zc0301_probe_pas202bcb(struct zc0301_device* cam)
336 {
337 	int r0 = 0, r1 = 0, err = 0;
338 	unsigned int pid = 0;
339 
340 	err += zc0301_write_reg(cam, 0x0000, 0x01);
341 	err += zc0301_write_reg(cam, 0x0010, 0x0e);
342 	err += zc0301_write_reg(cam, 0x0001, 0x01);
343 	err += zc0301_write_reg(cam, 0x0012, 0x03);
344 	err += zc0301_write_reg(cam, 0x0012, 0x01);
345 	err += zc0301_write_reg(cam, 0x008d, 0x08);
346 
347 	msleep(10);
348 
349 	r0 = zc0301_i2c_read(cam, 0x00, 1);
350 	r1 = zc0301_i2c_read(cam, 0x01, 1);
351 
352 	if (r0 < 0 || r1 < 0 || err)
353 		return -EIO;
354 
355 	pid = (r0 << 4) | ((r1 & 0xf0) >> 4);
356 	if (pid != 0x017)
357 		return -ENODEV;
358 
359 	zc0301_attach_sensor(cam, &pas202bcb);
360 
361 	return 0;
362 }
363