Avoid beyond bounds copy while caching ACL
[zen-stable.git] / drivers / media / video / gspca / stv06xx / stv06xx_st6422.c
blob9940e035b3ab4b0ef0dd318eb31f36b90d70c640
1 /*
2 * Support for the sensor part which is integrated (I think) into the
3 * st6422 stv06xx alike bridge, as its integrated there are no i2c writes
4 * but instead direct bridge writes.
6 * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com>
8 * Strongly based on qc-usb-messenger, which is:
9 * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
10 * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
11 * Copyright (c) 2002, 2003 Tuukka Toivonen
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31 #include "stv06xx_st6422.h"
33 /* controls */
34 enum e_ctrl {
35 BRIGHTNESS,
36 CONTRAST,
37 GAIN,
38 EXPOSURE,
39 NCTRLS /* number of controls */
42 /* sensor settings */
43 struct st6422_settings {
44 struct gspca_ctrl ctrls[NCTRLS];
47 static struct v4l2_pix_format st6422_mode[] = {
48 /* Note we actually get 124 lines of data, of which we skip the 4st
49 4 as they are garbage */
51 162,
52 120,
53 V4L2_PIX_FMT_SGRBG8,
54 V4L2_FIELD_NONE,
55 .sizeimage = 162 * 120,
56 .bytesperline = 162,
57 .colorspace = V4L2_COLORSPACE_SRGB,
58 .priv = 1
60 /* Note we actually get 248 lines of data, of which we skip the 4st
61 4 as they are garbage, and we tell the app it only gets the
62 first 240 of the 244 lines it actually gets, so that it ignores
63 the last 4. */
65 324,
66 240,
67 V4L2_PIX_FMT_SGRBG8,
68 V4L2_FIELD_NONE,
69 .sizeimage = 324 * 244,
70 .bytesperline = 324,
71 .colorspace = V4L2_COLORSPACE_SRGB,
72 .priv = 0
76 /* V4L2 controls supported by the driver */
77 static void st6422_set_brightness(struct gspca_dev *gspca_dev);
78 static void st6422_set_contrast(struct gspca_dev *gspca_dev);
79 static void st6422_set_gain(struct gspca_dev *gspca_dev);
80 static void st6422_set_exposure(struct gspca_dev *gspca_dev);
82 static const struct ctrl st6422_ctrl[NCTRLS] = {
83 [BRIGHTNESS] = {
85 .id = V4L2_CID_BRIGHTNESS,
86 .type = V4L2_CTRL_TYPE_INTEGER,
87 .name = "Brightness",
88 .minimum = 0,
89 .maximum = 31,
90 .step = 1,
91 .default_value = 3
93 .set_control = st6422_set_brightness
95 [CONTRAST] = {
97 .id = V4L2_CID_CONTRAST,
98 .type = V4L2_CTRL_TYPE_INTEGER,
99 .name = "Contrast",
100 .minimum = 0,
101 .maximum = 15,
102 .step = 1,
103 .default_value = 11
105 .set_control = st6422_set_contrast
107 [GAIN] = {
109 .id = V4L2_CID_GAIN,
110 .type = V4L2_CTRL_TYPE_INTEGER,
111 .name = "Gain",
112 .minimum = 0,
113 .maximum = 255,
114 .step = 1,
115 .default_value = 64
117 .set_control = st6422_set_gain
119 [EXPOSURE] = {
121 .id = V4L2_CID_EXPOSURE,
122 .type = V4L2_CTRL_TYPE_INTEGER,
123 .name = "Exposure",
124 .minimum = 0,
125 #define EXPOSURE_MAX 1023
126 .maximum = EXPOSURE_MAX,
127 .step = 1,
128 .default_value = 256
130 .set_control = st6422_set_exposure
134 static int st6422_probe(struct sd *sd)
136 struct st6422_settings *sensor_settings;
138 if (sd->bridge != BRIDGE_ST6422)
139 return -ENODEV;
141 pr_info("st6422 sensor detected\n");
143 sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL);
144 if (!sensor_settings)
145 return -ENOMEM;
147 sd->gspca_dev.cam.cam_mode = st6422_mode;
148 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
149 sd->gspca_dev.cam.ctrls = sensor_settings->ctrls;
150 sd->desc.ctrls = st6422_ctrl;
151 sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl);
152 sd->sensor_priv = sensor_settings;
154 return 0;
157 static int st6422_init(struct sd *sd)
159 int err = 0, i;
161 const u16 st6422_bridge_init[][2] = {
162 { STV_ISO_ENABLE, 0x00 }, /* disable capture */
163 { 0x1436, 0x00 },
164 { 0x1432, 0x03 }, /* 0x00-0x1F brightness */
165 { 0x143a, 0xf9 }, /* 0x00-0x0F contrast */
166 { 0x0509, 0x38 }, /* R */
167 { 0x050a, 0x38 }, /* G */
168 { 0x050b, 0x38 }, /* B */
169 { 0x050c, 0x2a },
170 { 0x050d, 0x01 },
173 { 0x1431, 0x00 }, /* 0x00-0x07 ??? */
174 { 0x1433, 0x34 }, /* 160x120, 0x00-0x01 night filter */
175 { 0x1438, 0x18 }, /* 640x480 */
176 /* 18 bayes */
177 /* 10 compressed? */
179 { 0x1439, 0x00 },
180 /* anti-noise? 0xa2 gives a perfect image */
182 { 0x143b, 0x05 },
183 { 0x143c, 0x00 }, /* 0x00-0x01 - ??? */
186 /* shutter time 0x0000-0x03FF */
187 /* low value give good picures on moving objects (but requires much light) */
188 /* high value gives good picures in darkness (but tends to be overexposed) */
189 { 0x143e, 0x01 },
190 { 0x143d, 0x00 },
192 { 0x1442, 0xe2 },
193 /* write: 1x1x xxxx */
194 /* read: 1x1x xxxx */
195 /* bit 5 == button pressed and hold if 0 */
196 /* write 0xe2,0xea */
198 /* 0x144a */
199 /* 0x00 init */
200 /* bit 7 == button has been pressed, but not handled */
202 /* interrupt */
203 /* if(urb->iso_frame_desc[i].status == 0x80) { */
204 /* if(urb->iso_frame_desc[i].status == 0x88) { */
206 { 0x1500, 0xd0 },
207 { 0x1500, 0xd0 },
208 { 0x1500, 0x50 }, /* 0x00 - 0xFF 0x80 == compr ? */
210 { 0x1501, 0xaf },
211 /* high val-> light area gets darker */
212 /* low val -> light area gets lighter */
213 { 0x1502, 0xc2 },
214 /* high val-> light area gets darker */
215 /* low val -> light area gets lighter */
216 { 0x1503, 0x45 },
217 /* high val-> light area gets darker */
218 /* low val -> light area gets lighter */
219 { 0x1505, 0x02 },
220 /* 2 : 324x248 80352 bytes */
221 /* 7 : 248x162 40176 bytes */
222 /* c+f: 162*124 20088 bytes */
224 { 0x150e, 0x8e },
225 { 0x150f, 0x37 },
226 { 0x15c0, 0x00 },
227 { 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? */
230 { 0x143f, 0x01 }, /* commit settings */
234 for (i = 0; i < ARRAY_SIZE(st6422_bridge_init) && !err; i++) {
235 err = stv06xx_write_bridge(sd, st6422_bridge_init[i][0],
236 st6422_bridge_init[i][1]);
239 return err;
242 static void st6422_disconnect(struct sd *sd)
244 sd->sensor = NULL;
245 kfree(sd->sensor_priv);
248 static int setbrightness(struct sd *sd)
250 struct st6422_settings *sensor_settings = sd->sensor_priv;
252 /* val goes from 0 -> 31 */
253 return stv06xx_write_bridge(sd, 0x1432,
254 sensor_settings->ctrls[BRIGHTNESS].val);
257 static int setcontrast(struct sd *sd)
259 struct st6422_settings *sensor_settings = sd->sensor_priv;
261 /* Val goes from 0 -> 15 */
262 return stv06xx_write_bridge(sd, 0x143a,
263 sensor_settings->ctrls[CONTRAST].val | 0xf0);
266 static int setgain(struct sd *sd)
268 struct st6422_settings *sensor_settings = sd->sensor_priv;
269 u8 gain;
270 int err;
272 gain = sensor_settings->ctrls[GAIN].val;
274 /* Set red, green, blue, gain */
275 err = stv06xx_write_bridge(sd, 0x0509, gain);
276 if (err < 0)
277 return err;
279 err = stv06xx_write_bridge(sd, 0x050a, gain);
280 if (err < 0)
281 return err;
283 err = stv06xx_write_bridge(sd, 0x050b, gain);
284 if (err < 0)
285 return err;
287 /* 2 mystery writes */
288 err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
289 if (err < 0)
290 return err;
292 return stv06xx_write_bridge(sd, 0x050d, 0x01);
295 static int setexposure(struct sd *sd)
297 struct st6422_settings *sensor_settings = sd->sensor_priv;
298 u16 expo;
299 int err;
301 expo = sensor_settings->ctrls[EXPOSURE].val;
302 err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff);
303 if (err < 0)
304 return err;
306 return stv06xx_write_bridge(sd, 0x143e, expo >> 8);
309 static int st6422_start(struct sd *sd)
311 int err;
312 struct cam *cam = &sd->gspca_dev.cam;
314 if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
315 err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
316 else
317 err = stv06xx_write_bridge(sd, 0x1505, 0x02);
318 if (err < 0)
319 return err;
321 err = setbrightness(sd);
322 if (err < 0)
323 return err;
325 err = setcontrast(sd);
326 if (err < 0)
327 return err;
329 err = setexposure(sd);
330 if (err < 0)
331 return err;
333 err = setgain(sd);
334 if (err < 0)
335 return err;
337 /* commit settings */
338 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
339 return (err < 0) ? err : 0;
342 static int st6422_stop(struct sd *sd)
344 PDEBUG(D_STREAM, "Halting stream");
346 return 0;
349 static void st6422_set_brightness(struct gspca_dev *gspca_dev)
351 int err;
352 struct sd *sd = (struct sd *) gspca_dev;
354 err = setbrightness(sd);
356 /* commit settings */
357 if (err >= 0)
358 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
360 gspca_dev->usb_err = err;
363 static void st6422_set_contrast(struct gspca_dev *gspca_dev)
365 int err;
366 struct sd *sd = (struct sd *) gspca_dev;
368 err = setcontrast(sd);
370 /* commit settings */
371 if (err >= 0)
372 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
374 gspca_dev->usb_err = err;
377 static void st6422_set_gain(struct gspca_dev *gspca_dev)
379 int err;
380 struct sd *sd = (struct sd *) gspca_dev;
382 err = setgain(sd);
384 /* commit settings */
385 if (err >= 0)
386 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
388 gspca_dev->usb_err = err;
391 static void st6422_set_exposure(struct gspca_dev *gspca_dev)
393 int err;
394 struct sd *sd = (struct sd *) gspca_dev;
396 err = setexposure(sd);
398 /* commit settings */
399 if (err >= 0)
400 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
402 gspca_dev->usb_err = err;