[media] gspca: Use current logging styles
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / media / video / gspca / stv06xx / stv06xx_st6422.c
CommitLineData
8668d504
HG
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.
5 *
6 * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com>
7 *
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
12 *
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.
17 *
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.
22 *
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
26 *
27 */
28
133a9fe9
JP
29#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30
8668d504
HG
31#include "stv06xx_st6422.h"
32
71e84ea7
JFM
33/* controls */
34enum e_ctrl {
35 BRIGHTNESS,
36 CONTRAST,
37 GAIN,
38 EXPOSURE,
39 NCTRLS /* number of controls */
40};
41
42/* sensor settings */
43struct st6422_settings {
44 struct gspca_ctrl ctrls[NCTRLS];
45};
46
8668d504
HG
47static 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 */
50 {
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
59 },
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. */
64 {
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
73 },
74};
75
71e84ea7
JFM
76/* V4L2 controls supported by the driver */
77static void st6422_set_brightness(struct gspca_dev *gspca_dev);
78static void st6422_set_contrast(struct gspca_dev *gspca_dev);
79static void st6422_set_gain(struct gspca_dev *gspca_dev);
80static void st6422_set_exposure(struct gspca_dev *gspca_dev);
81
82static const struct ctrl st6422_ctrl[NCTRLS] = {
83[BRIGHTNESS] = {
8668d504
HG
84 {
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
92 },
71e84ea7 93 .set_control = st6422_set_brightness
8668d504 94 },
71e84ea7 95[CONTRAST] = {
8668d504
HG
96 {
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
104 },
71e84ea7 105 .set_control = st6422_set_contrast
8668d504 106 },
71e84ea7 107[GAIN] = {
8668d504
HG
108 {
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
116 },
71e84ea7 117 .set_control = st6422_set_gain
8668d504 118 },
71e84ea7 119[EXPOSURE] = {
8668d504
HG
120 {
121 .id = V4L2_CID_EXPOSURE,
122 .type = V4L2_CTRL_TYPE_INTEGER,
123 .name = "Exposure",
124 .minimum = 0,
71e84ea7
JFM
125#define EXPOSURE_MAX 1023
126 .maximum = EXPOSURE_MAX,
8668d504
HG
127 .step = 1,
128 .default_value = 256
129 },
71e84ea7 130 .set_control = st6422_set_exposure
8668d504
HG
131 },
132};
133
134static int st6422_probe(struct sd *sd)
135{
71e84ea7 136 struct st6422_settings *sensor_settings;
8668d504
HG
137
138 if (sd->bridge != BRIDGE_ST6422)
139 return -ENODEV;
140
133a9fe9 141 pr_info("st6422 sensor detected\n");
8668d504 142
71e84ea7 143 sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL);
8668d504
HG
144 if (!sensor_settings)
145 return -ENOMEM;
146
147 sd->gspca_dev.cam.cam_mode = st6422_mode;
148 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
71e84ea7 149 sd->gspca_dev.cam.ctrls = sensor_settings->ctrls;
8668d504
HG
150 sd->desc.ctrls = st6422_ctrl;
151 sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl);
152 sd->sensor_priv = sensor_settings;
153
8668d504
HG
154 return 0;
155}
156
157static int st6422_init(struct sd *sd)
158{
159 int err = 0, i;
160
161 const u16 st6422_bridge_init[][2] = {
162 { STV_ISO_ENABLE, 0x00 }, /* disable capture */
163 { 0x1436, 0x00 },
164 { 0x1432, 0x03 }, /* 0x00-0x1F brightness */
1d00d6c1 165 { 0x143a, 0xf9 }, /* 0x00-0x0F contrast */
8668d504
HG
166 { 0x0509, 0x38 }, /* R */
167 { 0x050a, 0x38 }, /* G */
168 { 0x050b, 0x38 }, /* B */
1d00d6c1 169 { 0x050c, 0x2a },
8668d504
HG
170 { 0x050d, 0x01 },
171
172
173 { 0x1431, 0x00 }, /* 0x00-0x07 ??? */
174 { 0x1433, 0x34 }, /* 160x120, 0x00-0x01 night filter */
175 { 0x1438, 0x18 }, /* 640x480 */
176/* 18 bayes */
177/* 10 compressed? */
178
179 { 0x1439, 0x00 },
bf5c562a 180/* anti-noise? 0xa2 gives a perfect image */
8668d504
HG
181
182 { 0x143b, 0x05 },
183 { 0x143c, 0x00 }, /* 0x00-0x01 - ??? */
184
185
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 },
191
192 { 0x1442, 0xe2 },
193/* write: 1x1x xxxx */
194/* read: 1x1x xxxx */
195/* bit 5 == button pressed and hold if 0 */
196/* write 0xe2,0xea */
197
198/* 0x144a */
199/* 0x00 init */
200/* bit 7 == button has been pressed, but not handled */
201
202/* interrupt */
203/* if(urb->iso_frame_desc[i].status == 0x80) { */
204/* if(urb->iso_frame_desc[i].status == 0x88) { */
205
206 { 0x1500, 0xd0 },
207 { 0x1500, 0xd0 },
208 { 0x1500, 0x50 }, /* 0x00 - 0xFF 0x80 == compr ? */
209
210 { 0x1501, 0xaf },
bf5c562a
EA
211/* high val-> light area gets darker */
212/* low val -> light area gets lighter */
8668d504 213 { 0x1502, 0xc2 },
bf5c562a
EA
214/* high val-> light area gets darker */
215/* low val -> light area gets lighter */
8668d504 216 { 0x1503, 0x45 },
bf5c562a
EA
217/* high val-> light area gets darker */
218/* low val -> light area gets lighter */
8668d504
HG
219 { 0x1505, 0x02 },
220/* 2 : 324x248 80352 bytes */
221/* 7 : 248x162 40176 bytes */
222/* c+f: 162*124 20088 bytes */
223
224 { 0x150e, 0x8e },
225 { 0x150f, 0x37 },
226 { 0x15c0, 0x00 },
8668d504
HG
227 { 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? */
228
229
230 { 0x143f, 0x01 }, /* commit settings */
231
232 };
233
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]);
237 }
238
239 return err;
240}
241
242static void st6422_disconnect(struct sd *sd)
243{
244 sd->sensor = NULL;
245 kfree(sd->sensor_priv);
246}
247
71e84ea7
JFM
248static int setbrightness(struct sd *sd)
249{
250 struct st6422_settings *sensor_settings = sd->sensor_priv;
251
252 /* val goes from 0 -> 31 */
253 return stv06xx_write_bridge(sd, 0x1432,
254 sensor_settings->ctrls[BRIGHTNESS].val);
255}
256
257static int setcontrast(struct sd *sd)
258{
259 struct st6422_settings *sensor_settings = sd->sensor_priv;
260
261 /* Val goes from 0 -> 15 */
262 return stv06xx_write_bridge(sd, 0x143a,
263 sensor_settings->ctrls[CONTRAST].val | 0xf0);
264}
265
266static int setgain(struct sd *sd)
8668d504 267{
71e84ea7
JFM
268 struct st6422_settings *sensor_settings = sd->sensor_priv;
269 u8 gain;
c0b33bdc 270 int err;
8668d504 271
71e84ea7 272 gain = sensor_settings->ctrls[GAIN].val;
8668d504 273
71e84ea7
JFM
274 /* Set red, green, blue, gain */
275 err = stv06xx_write_bridge(sd, 0x0509, gain);
8668d504
HG
276 if (err < 0)
277 return err;
278
71e84ea7 279 err = stv06xx_write_bridge(sd, 0x050a, gain);
8668d504
HG
280 if (err < 0)
281 return err;
282
71e84ea7 283 err = stv06xx_write_bridge(sd, 0x050b, gain);
8668d504
HG
284 if (err < 0)
285 return err;
286
71e84ea7
JFM
287 /* 2 mystery writes */
288 err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
8668d504
HG
289 if (err < 0)
290 return err;
291
71e84ea7 292 return stv06xx_write_bridge(sd, 0x050d, 0x01);
8668d504
HG
293}
294
71e84ea7 295static int setexposure(struct sd *sd)
8668d504 296{
71e84ea7
JFM
297 struct st6422_settings *sensor_settings = sd->sensor_priv;
298 u16 expo;
299 int err;
8668d504 300
71e84ea7
JFM
301 expo = sensor_settings->ctrls[EXPOSURE].val;
302 err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff);
303 if (err < 0)
304 return err;
8668d504 305
71e84ea7 306 return stv06xx_write_bridge(sd, 0x143e, expo >> 8);
8668d504
HG
307}
308
71e84ea7 309static int st6422_start(struct sd *sd)
8668d504
HG
310{
311 int err;
71e84ea7 312 struct cam *cam = &sd->gspca_dev.cam;
8668d504 313
71e84ea7
JFM
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;
8668d504 320
71e84ea7
JFM
321 err = setbrightness(sd);
322 if (err < 0)
323 return err;
8668d504 324
71e84ea7
JFM
325 err = setcontrast(sd);
326 if (err < 0)
327 return err;
328
329 err = setexposure(sd);
330 if (err < 0)
331 return err;
332
333 err = setgain(sd);
8668d504
HG
334 if (err < 0)
335 return err;
336
337 /* commit settings */
338 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
339 return (err < 0) ? err : 0;
340}
341
71e84ea7 342static int st6422_stop(struct sd *sd)
8668d504 343{
71e84ea7 344 PDEBUG(D_STREAM, "Halting stream");
8668d504
HG
345
346 return 0;
347}
348
71e84ea7 349static void st6422_set_brightness(struct gspca_dev *gspca_dev)
8668d504
HG
350{
351 int err;
352 struct sd *sd = (struct sd *) gspca_dev;
8668d504 353
71e84ea7 354 err = setbrightness(sd);
8668d504
HG
355
356 /* commit settings */
71e84ea7
JFM
357 if (err >= 0)
358 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
8668d504 359
71e84ea7 360 gspca_dev->usb_err = err;
8668d504
HG
361}
362
71e84ea7 363static void st6422_set_contrast(struct gspca_dev *gspca_dev)
8668d504
HG
364{
365 int err;
366 struct sd *sd = (struct sd *) gspca_dev;
8668d504 367
71e84ea7 368 err = setcontrast(sd);
8668d504
HG
369
370 /* commit settings */
71e84ea7
JFM
371 if (err >= 0)
372 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
373
374 gspca_dev->usb_err = err;
8668d504
HG
375}
376
71e84ea7 377static void st6422_set_gain(struct gspca_dev *gspca_dev)
8668d504 378{
71e84ea7 379 int err;
8668d504 380 struct sd *sd = (struct sd *) gspca_dev;
8668d504 381
71e84ea7 382 err = setgain(sd);
8668d504 383
71e84ea7
JFM
384 /* commit settings */
385 if (err >= 0)
386 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
8668d504 387
71e84ea7 388 gspca_dev->usb_err = err;
8668d504
HG
389}
390
71e84ea7 391static void st6422_set_exposure(struct gspca_dev *gspca_dev)
8668d504
HG
392{
393 int err;
394 struct sd *sd = (struct sd *) gspca_dev;
8668d504 395
71e84ea7 396 err = setexposure(sd);
8668d504
HG
397
398 /* commit settings */
71e84ea7
JFM
399 if (err >= 0)
400 err = stv06xx_write_bridge(sd, 0x143f, 0x01);
401
402 gspca_dev->usb_err = err;
8668d504 403}