aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/media/sn9c102_pas202bcb.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/usb/media/sn9c102_pas202bcb.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/usb/media/sn9c102_pas202bcb.c')
-rw-r--r--drivers/usb/media/sn9c102_pas202bcb.c293
1 files changed, 293 insertions, 0 deletions
diff --git a/drivers/usb/media/sn9c102_pas202bcb.c b/drivers/usb/media/sn9c102_pas202bcb.c
new file mode 100644
index 000000000000..5ca54c7daaf2
--- /dev/null
+++ b/drivers/usb/media/sn9c102_pas202bcb.c
@@ -0,0 +1,293 @@
1/***************************************************************************
2 * Plug-in for PAS202BCB image sensor connected to the SN9C10x PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio *
6 * <medaglia@undl.org.br> *
7 * http://cadu.homelinux.com:8080/ *
8 * *
9 * DAC Magnitude, exposure and green gain controls added by *
10 * Luca Risolia <luca.risolia@studio.unibo.it> *
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 * This program is distributed in the hope that it will be useful, *
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
20 * GNU General Public License for more details. *
21 * *
22 * You should have received a copy of the GNU General Public License *
23 * along with this program; if not, write to the Free Software *
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
25 ***************************************************************************/
26
27#include <linux/delay.h>
28#include "sn9c102_sensor.h"
29
30
31static struct sn9c102_sensor pas202bcb;
32
33
34static int pas202bcb_init(struct sn9c102_device* cam)
35{
36 int err = 0;
37
38 err += sn9c102_write_reg(cam, 0x00, 0x10);
39 err += sn9c102_write_reg(cam, 0x00, 0x11);
40 err += sn9c102_write_reg(cam, 0x00, 0x14);
41 err += sn9c102_write_reg(cam, 0x20, 0x17);
42 err += sn9c102_write_reg(cam, 0x30, 0x19);
43 err += sn9c102_write_reg(cam, 0x09, 0x18);
44
45 err += sn9c102_i2c_write(cam, 0x02, 0x14);
46 err += sn9c102_i2c_write(cam, 0x03, 0x40);
47 err += sn9c102_i2c_write(cam, 0x0d, 0x2c);
48 err += sn9c102_i2c_write(cam, 0x0e, 0x01);
49 err += sn9c102_i2c_write(cam, 0x0f, 0xa9);
50 err += sn9c102_i2c_write(cam, 0x10, 0x08);
51 err += sn9c102_i2c_write(cam, 0x13, 0x63);
52 err += sn9c102_i2c_write(cam, 0x15, 0x70);
53 err += sn9c102_i2c_write(cam, 0x11, 0x01);
54
55 msleep(400);
56
57 return err;
58}
59
60
61static int pas202bcb_get_ctrl(struct sn9c102_device* cam,
62 struct v4l2_control* ctrl)
63{
64 switch (ctrl->id) {
65 case V4L2_CID_EXPOSURE:
66 {
67 int r1 = sn9c102_i2c_read(cam, 0x04),
68 r2 = sn9c102_i2c_read(cam, 0x05);
69 if (r1 < 0 || r2 < 0)
70 return -EIO;
71 ctrl->value = (r1 << 6) | (r2 & 0x3f);
72 }
73 return 0;
74 case V4L2_CID_RED_BALANCE:
75 if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0)
76 return -EIO;
77 ctrl->value &= 0x0f;
78 return 0;
79 case V4L2_CID_BLUE_BALANCE:
80 if ((ctrl->value = sn9c102_i2c_read(cam, 0x07)) < 0)
81 return -EIO;
82 ctrl->value &= 0x0f;
83 return 0;
84 case V4L2_CID_GAIN:
85 if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
86 return -EIO;
87 ctrl->value &= 0x1f;
88 return 0;
89 case SN9C102_V4L2_CID_GREEN_BALANCE:
90 if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0)
91 return -EIO;
92 ctrl->value &= 0x0f;
93 return 0;
94 case SN9C102_V4L2_CID_DAC_MAGNITUDE:
95 if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
96 return -EIO;
97 return 0;
98 default:
99 return -EINVAL;
100 }
101}
102
103
104static int pas202bcb_set_pix_format(struct sn9c102_device* cam,
105 const struct v4l2_pix_format* pix)
106{
107 int err = 0;
108
109 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
110 err += sn9c102_write_reg(cam, 0x24, 0x17);
111 else
112 err += sn9c102_write_reg(cam, 0x20, 0x17);
113
114 return err;
115}
116
117
118static int pas202bcb_set_ctrl(struct sn9c102_device* cam,
119 const struct v4l2_control* ctrl)
120{
121 int err = 0;
122
123 switch (ctrl->id) {
124 case V4L2_CID_EXPOSURE:
125 err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6);
126 err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f);
127 break;
128 case V4L2_CID_RED_BALANCE:
129 err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
130 break;
131 case V4L2_CID_BLUE_BALANCE:
132 err += sn9c102_i2c_write(cam, 0x07, ctrl->value);
133 break;
134 case V4L2_CID_GAIN:
135 err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
136 break;
137 case SN9C102_V4L2_CID_GREEN_BALANCE:
138 err += sn9c102_i2c_write(cam, 0x08, ctrl->value);
139 break;
140 case SN9C102_V4L2_CID_DAC_MAGNITUDE:
141 err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
142 break;
143 default:
144 return -EINVAL;
145 }
146 err += sn9c102_i2c_write(cam, 0x11, 0x01);
147
148 return err ? -EIO : 0;
149}
150
151
152static int pas202bcb_set_crop(struct sn9c102_device* cam,
153 const struct v4l2_rect* rect)
154{
155 struct sn9c102_sensor* s = &pas202bcb;
156 int err = 0;
157 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4,
158 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
159
160 err += sn9c102_write_reg(cam, h_start, 0x12);
161 err += sn9c102_write_reg(cam, v_start, 0x13);
162
163 return err;
164}
165
166
167static struct sn9c102_sensor pas202bcb = {
168 .name = "PAS202BCB",
169 .maintainer = "Carlos Eduardo Medaglia Dyonisio "
170 "<medaglia@undl.org.br>",
171 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
172 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
173 .interface = SN9C102_I2C_2WIRES,
174 .i2c_slave_id = 0x40,
175 .init = &pas202bcb_init,
176 .qctrl = {
177 {
178 .id = V4L2_CID_EXPOSURE,
179 .type = V4L2_CTRL_TYPE_INTEGER,
180 .name = "exposure",
181 .minimum = 0x01e5,
182 .maximum = 0x3fff,
183 .step = 0x0001,
184 .default_value = 0x01e5,
185 .flags = 0,
186 },
187 {
188 .id = V4L2_CID_GAIN,
189 .type = V4L2_CTRL_TYPE_INTEGER,
190 .name = "global gain",
191 .minimum = 0x00,
192 .maximum = 0x1f,
193 .step = 0x01,
194 .default_value = 0x0c,
195 .flags = 0,
196 },
197 {
198 .id = V4L2_CID_RED_BALANCE,
199 .type = V4L2_CTRL_TYPE_INTEGER,
200 .name = "red balance",
201 .minimum = 0x00,
202 .maximum = 0x0f,
203 .step = 0x01,
204 .default_value = 0x01,
205 .flags = 0,
206 },
207 {
208 .id = V4L2_CID_BLUE_BALANCE,
209 .type = V4L2_CTRL_TYPE_INTEGER,
210 .name = "blue balance",
211 .minimum = 0x00,
212 .maximum = 0x0f,
213 .step = 0x01,
214 .default_value = 0x05,
215 .flags = 0,
216 },
217 {
218 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
219 .type = V4L2_CTRL_TYPE_INTEGER,
220 .name = "green balance",
221 .minimum = 0x00,
222 .maximum = 0x0f,
223 .step = 0x01,
224 .default_value = 0x00,
225 .flags = 0,
226 },
227 {
228 .id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
229 .type = V4L2_CTRL_TYPE_INTEGER,
230 .name = "DAC magnitude",
231 .minimum = 0x00,
232 .maximum = 0xff,
233 .step = 0x01,
234 .default_value = 0x04,
235 .flags = 0,
236 },
237 },
238 .get_ctrl = &pas202bcb_get_ctrl,
239 .set_ctrl = &pas202bcb_set_ctrl,
240 .cropcap = {
241 .bounds = {
242 .left = 0,
243 .top = 0,
244 .width = 640,
245 .height = 480,
246 },
247 .defrect = {
248 .left = 0,
249 .top = 0,
250 .width = 640,
251 .height = 480,
252 },
253 },
254 .set_crop = &pas202bcb_set_crop,
255 .pix_format = {
256 .width = 640,
257 .height = 480,
258 .pixelformat = V4L2_PIX_FMT_SBGGR8,
259 .priv = 8,
260 },
261 .set_pix_format = &pas202bcb_set_pix_format
262};
263
264
265int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
266{
267 int r0 = 0, r1 = 0, err = 0;
268 unsigned int pid = 0;
269
270 /*
271 * Minimal initialization to enable the I2C communication
272 * NOTE: do NOT change the values!
273 */
274 err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */
275 err += sn9c102_write_reg(cam, 0x40, 0x01); /* sensor power on */
276 err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */
277 if (err)
278 return -EIO;
279
280 r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00);
281 r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01);
282
283 if (r0 < 0 || r1 < 0)
284 return -EIO;
285
286 pid = (r0 << 4) | ((r1 & 0xf0) >> 4);
287 if (pid != 0x017)
288 return -ENODEV;
289
290 sn9c102_attach_sensor(cam, &pas202bcb);
291
292 return 0;
293}