1 /***************************************************************************
2 * Plug-in for PAS202BCB image sensor connected to the ZC030! Image *
3 * Processor and Control Chip *
5 * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
7 * Initialization values of the ZC0301 have been taken from the SPCA5XX *
8 * driver maintained by Michel Xhaard <mxhaard@magic.fr> *
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. *
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. *
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 ***************************************************************************/
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
33 #include <linux/delay.h>
34 #include "zc0301_sensor.h"
37 static struct zc0301_sensor pas202bcb
;
40 static int pas202bcb_init(struct zc0301_device
* cam
)
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);
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);
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);
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);
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);
159 err
+= zc0301_i2c_write(cam
, 0x11, 0x01);
167 static int pas202bcb_get_ctrl(struct zc0301_device
* cam
,
168 struct v4l2_control
* ctrl
)
171 case V4L2_CID_EXPOSURE
:
173 int r1
= zc0301_i2c_read(cam
, 0x04, 1),
174 r2
= zc0301_i2c_read(cam
, 0x05, 1);
175 if (r1
< 0 || r2
< 0)
177 ctrl
->value
= (r1
<< 6) | (r2
& 0x3f);
180 case V4L2_CID_RED_BALANCE
:
181 if ((ctrl
->value
= zc0301_i2c_read(cam
, 0x09, 1)) < 0)
185 case V4L2_CID_BLUE_BALANCE
:
186 if ((ctrl
->value
= zc0301_i2c_read(cam
, 0x07, 1)) < 0)
191 if ((ctrl
->value
= zc0301_i2c_read(cam
, 0x10, 1)) < 0)
195 case ZC0301_V4L2_CID_GREEN_BALANCE
:
196 if ((ctrl
->value
= zc0301_i2c_read(cam
, 0x08, 1)) < 0)
200 case ZC0301_V4L2_CID_DAC_MAGNITUDE
:
201 if ((ctrl
->value
= zc0301_i2c_read(cam
, 0x0c, 1)) < 0)
210 static int pas202bcb_set_ctrl(struct zc0301_device
* cam
,
211 const struct v4l2_control
* ctrl
)
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);
220 case V4L2_CID_RED_BALANCE
:
221 err
+= zc0301_i2c_write(cam
, 0x09, ctrl
->value
);
223 case V4L2_CID_BLUE_BALANCE
:
224 err
+= zc0301_i2c_write(cam
, 0x07, ctrl
->value
);
227 err
+= zc0301_i2c_write(cam
, 0x10, ctrl
->value
);
229 case ZC0301_V4L2_CID_GREEN_BALANCE
:
230 err
+= zc0301_i2c_write(cam
, 0x08, ctrl
->value
);
232 case ZC0301_V4L2_CID_DAC_MAGNITUDE
:
233 err
+= zc0301_i2c_write(cam
, 0x0c, ctrl
->value
);
238 err
+= zc0301_i2c_write(cam
, 0x11, 0x01);
240 return err
? -EIO
: 0;
244 static struct zc0301_sensor pas202bcb
= {
246 .init
= &pas202bcb_init
,
249 .id
= V4L2_CID_EXPOSURE
,
250 .type
= V4L2_CTRL_TYPE_INTEGER
,
255 .default_value
= 0x01e5,
256 .flags
= V4L2_CTRL_FLAG_DISABLED
,
260 .type
= V4L2_CTRL_TYPE_INTEGER
,
261 .name
= "global gain",
265 .default_value
= 0x0c,
266 .flags
= V4L2_CTRL_FLAG_DISABLED
,
269 .id
= ZC0301_V4L2_CID_DAC_MAGNITUDE
,
270 .type
= V4L2_CTRL_TYPE_INTEGER
,
271 .name
= "DAC magnitude",
275 .default_value
= 0x00,
276 .flags
= V4L2_CTRL_FLAG_DISABLED
,
279 .id
= V4L2_CID_RED_BALANCE
,
280 .type
= V4L2_CTRL_TYPE_INTEGER
,
281 .name
= "red balance",
285 .default_value
= 0x01,
286 .flags
= V4L2_CTRL_FLAG_DISABLED
,
289 .id
= V4L2_CID_BLUE_BALANCE
,
290 .type
= V4L2_CTRL_TYPE_INTEGER
,
291 .name
= "blue balance",
295 .default_value
= 0x05,
296 .flags
= V4L2_CTRL_FLAG_DISABLED
,
299 .id
= ZC0301_V4L2_CID_GREEN_BALANCE
,
300 .type
= V4L2_CTRL_TYPE_INTEGER
,
301 .name
= "green balance",
305 .default_value
= 0x00,
306 .flags
= V4L2_CTRL_FLAG_DISABLED
,
309 .get_ctrl
= &pas202bcb_get_ctrl
,
310 .set_ctrl
= &pas202bcb_set_ctrl
,
328 .pixelformat
= V4L2_PIX_FMT_JPEG
,
334 int zc0301_probe_pas202bcb(struct zc0301_device
* cam
)
336 int r0
= 0, r1
= 0, err
= 0;
337 unsigned int pid
= 0;
339 err
+= zc0301_write_reg(cam
, 0x0000, 0x01);
340 err
+= zc0301_write_reg(cam
, 0x0010, 0x0e);
341 err
+= zc0301_write_reg(cam
, 0x0001, 0x01);
342 err
+= zc0301_write_reg(cam
, 0x0012, 0x03);
343 err
+= zc0301_write_reg(cam
, 0x0012, 0x01);
344 err
+= zc0301_write_reg(cam
, 0x008d, 0x08);
348 r0
= zc0301_i2c_read(cam
, 0x00, 1);
349 r1
= zc0301_i2c_read(cam
, 0x01, 1);
351 if (r0
< 0 || r1
< 0 || err
)
354 pid
= (r0
<< 4) | ((r1
& 0xf0) >> 4);
358 zc0301_attach_sensor(cam
, &pas202bcb
);