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"
39 NCTRLS
/* number of controls */
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 */
55 .sizeimage
= 162 * 120,
57 .colorspace
= V4L2_COLORSPACE_SRGB
,
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
69 .sizeimage
= 324 * 244,
71 .colorspace
= V4L2_COLORSPACE_SRGB
,
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
] = {
85 .id
= V4L2_CID_BRIGHTNESS
,
86 .type
= V4L2_CTRL_TYPE_INTEGER
,
93 .set_control
= st6422_set_brightness
97 .id
= V4L2_CID_CONTRAST
,
98 .type
= V4L2_CTRL_TYPE_INTEGER
,
105 .set_control
= st6422_set_contrast
110 .type
= V4L2_CTRL_TYPE_INTEGER
,
117 .set_control
= st6422_set_gain
121 .id
= V4L2_CID_EXPOSURE
,
122 .type
= V4L2_CTRL_TYPE_INTEGER
,
125 #define EXPOSURE_MAX 1023
126 .maximum
= EXPOSURE_MAX
,
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
)
141 pr_info("st6422 sensor detected\n");
143 sensor_settings
= kmalloc(sizeof *sensor_settings
, GFP_KERNEL
);
144 if (!sensor_settings
)
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
;
157 static int st6422_init(struct sd
*sd
)
161 const u16 st6422_bridge_init
[][2] = {
162 { STV_ISO_ENABLE
, 0x00 }, /* disable capture */
164 { 0x1432, 0x03 }, /* 0x00-0x1F brightness */
165 { 0x143a, 0xf9 }, /* 0x00-0x0F contrast */
166 { 0x0509, 0x38 }, /* R */
167 { 0x050a, 0x38 }, /* G */
168 { 0x050b, 0x38 }, /* B */
173 { 0x1431, 0x00 }, /* 0x00-0x07 ??? */
174 { 0x1433, 0x34 }, /* 160x120, 0x00-0x01 night filter */
175 { 0x1438, 0x18 }, /* 640x480 */
180 /* anti-noise? 0xa2 gives a perfect image */
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) */
193 /* write: 1x1x xxxx */
194 /* read: 1x1x xxxx */
195 /* bit 5 == button pressed and hold if 0 */
196 /* write 0xe2,0xea */
200 /* bit 7 == button has been pressed, but not handled */
203 /* if(urb->iso_frame_desc[i].status == 0x80) { */
204 /* if(urb->iso_frame_desc[i].status == 0x88) { */
208 { 0x1500, 0x50 }, /* 0x00 - 0xFF 0x80 == compr ? */
211 /* high val-> light area gets darker */
212 /* low val -> light area gets lighter */
214 /* high val-> light area gets darker */
215 /* low val -> light area gets lighter */
217 /* high val-> light area gets darker */
218 /* low val -> light area gets lighter */
220 /* 2 : 324x248 80352 bytes */
221 /* 7 : 248x162 40176 bytes */
222 /* c+f: 162*124 20088 bytes */
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]);
242 static void st6422_disconnect(struct sd
*sd
)
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
;
272 gain
= sensor_settings
->ctrls
[GAIN
].val
;
274 /* Set red, green, blue, gain */
275 err
= stv06xx_write_bridge(sd
, 0x0509, gain
);
279 err
= stv06xx_write_bridge(sd
, 0x050a, gain
);
283 err
= stv06xx_write_bridge(sd
, 0x050b, gain
);
287 /* 2 mystery writes */
288 err
= stv06xx_write_bridge(sd
, 0x050c, 0x2a);
292 return stv06xx_write_bridge(sd
, 0x050d, 0x01);
295 static int setexposure(struct sd
*sd
)
297 struct st6422_settings
*sensor_settings
= sd
->sensor_priv
;
301 expo
= sensor_settings
->ctrls
[EXPOSURE
].val
;
302 err
= stv06xx_write_bridge(sd
, 0x143d, expo
& 0xff);
306 return stv06xx_write_bridge(sd
, 0x143e, expo
>> 8);
309 static int st6422_start(struct sd
*sd
)
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);
317 err
= stv06xx_write_bridge(sd
, 0x1505, 0x02);
321 err
= setbrightness(sd
);
325 err
= setcontrast(sd
);
329 err
= setexposure(sd
);
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");
349 static void st6422_set_brightness(struct gspca_dev
*gspca_dev
)
352 struct sd
*sd
= (struct sd
*) gspca_dev
;
354 err
= setbrightness(sd
);
356 /* commit settings */
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
)
366 struct sd
*sd
= (struct sd
*) gspca_dev
;
368 err
= setcontrast(sd
);
370 /* commit settings */
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
)
380 struct sd
*sd
= (struct sd
*) gspca_dev
;
384 /* commit settings */
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
)
394 struct sd
*sd
= (struct sd
*) gspca_dev
;
396 err
= setexposure(sd
);
398 /* commit settings */
400 err
= stv06xx_write_bridge(sd
, 0x143f, 0x01);
402 gspca_dev
->usb_err
= err
;